1e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood/*
2e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood * Bitbanged MDIO support.
3e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood *
4e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood * Author: Scott Wood <scottwood@freescale.com>
5e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood * Copyright (c) 2007 Freescale Semiconductor
6e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood *
7e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood * Based on CPM2 MDIO code which is:
8e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood *
9e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood * Copyright (c) 2003 Intracom S.A.
10e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood *  by Pantelis Antoniou <panto@intracom.gr>
11e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood *
12e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood * 2005 (c) MontaVista Software, Inc.
13e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood * Vitaly Bordug <vbordug@ru.mvista.com>
14e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood *
15e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood * This file is licensed under the terms of the GNU General Public License
16e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood * version 2. This program is licensed "as is" without any warranty of any
17e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood * kind, whether express or implied.
18e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood */
19e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
20e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood#include <linux/module.h>
21e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood#include <linux/mdio-bitbang.h>
22e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood#include <linux/types.h>
23e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood#include <linux/delay.h>
24e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
25abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe#define MDIO_READ 2
26abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe#define MDIO_WRITE 1
27abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe
28abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe#define MDIO_C45 (1<<15)
29abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe#define MDIO_C45_ADDR (MDIO_C45 | 0)
30abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe#define MDIO_C45_READ (MDIO_C45 | 3)
31abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe#define MDIO_C45_WRITE (MDIO_C45 | 1)
32e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
33e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood#define MDIO_SETUP_TIME 10
34e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood#define MDIO_HOLD_TIME 10
35e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
36e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood/* Minimum MDC period is 400 ns, plus some margin for error.  MDIO_DELAY
37e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood * is done twice per period.
38e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood */
39e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood#define MDIO_DELAY 250
40e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
41e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood/* The PHY may take up to 300 ns to produce data, plus some margin
42e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood * for error.
43e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood */
44e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood#define MDIO_READ_DELAY 350
45e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
46e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood/* MDIO must already be configured as output. */
47e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Woodstatic void mdiobb_send_bit(struct mdiobb_ctrl *ctrl, int val)
48e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood{
49e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	const struct mdiobb_ops *ops = ctrl->ops;
50e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
51e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	ops->set_mdio_data(ctrl, val);
52e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	ndelay(MDIO_DELAY);
53e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	ops->set_mdc(ctrl, 1);
54e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	ndelay(MDIO_DELAY);
55e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	ops->set_mdc(ctrl, 0);
56e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood}
57e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
58e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood/* MDIO must already be configured as input. */
59e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Woodstatic int mdiobb_get_bit(struct mdiobb_ctrl *ctrl)
60e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood{
61e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	const struct mdiobb_ops *ops = ctrl->ops;
62e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
63e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	ndelay(MDIO_DELAY);
64e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	ops->set_mdc(ctrl, 1);
65e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	ndelay(MDIO_READ_DELAY);
66e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	ops->set_mdc(ctrl, 0);
67e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
68e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	return ops->get_mdio_data(ctrl);
69e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood}
70e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
71e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood/* MDIO must already be configured as output. */
72e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Woodstatic void mdiobb_send_num(struct mdiobb_ctrl *ctrl, u16 val, int bits)
73e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood{
74e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	int i;
75e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
76e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	for (i = bits - 1; i >= 0; i--)
77e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood		mdiobb_send_bit(ctrl, (val >> i) & 1);
78e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood}
79e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
80e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood/* MDIO must already be configured as input. */
81e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Woodstatic u16 mdiobb_get_num(struct mdiobb_ctrl *ctrl, int bits)
82e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood{
83e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	int i;
84e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	u16 ret = 0;
85e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
86e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	for (i = bits - 1; i >= 0; i--) {
87e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood		ret <<= 1;
88e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood		ret |= mdiobb_get_bit(ctrl);
89e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	}
90e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
91e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	return ret;
92e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood}
93e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
94e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood/* Utility to send the preamble, address, and
95e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood * register (common to read and write).
96e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood */
97abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpestatic void mdiobb_cmd(struct mdiobb_ctrl *ctrl, int op, u8 phy, u8 reg)
98e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood{
99e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	const struct mdiobb_ops *ops = ctrl->ops;
100e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	int i;
101e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
102e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	ops->set_mdio_dir(ctrl, 1);
103e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
104e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	/*
105e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	 * Send a 32 bit preamble ('1's) with an extra '1' bit for good
106e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	 * measure.  The IEEE spec says this is a PHY optional
107e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	 * requirement.  The AMD 79C874 requires one after power up and
108e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	 * one after a MII communications error.  This means that we are
109e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	 * doing more preambles than we need, but it is safer and will be
110e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	 * much more robust.
111e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	 */
112e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
113e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	for (i = 0; i < 32; i++)
114e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood		mdiobb_send_bit(ctrl, 1);
115e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
116abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	/* send the start bit (01) and the read opcode (10) or write (10).
117abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	   Clause 45 operation uses 00 for the start and 11, 10 for
118abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	   read/write */
119e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	mdiobb_send_bit(ctrl, 0);
120abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	if (op & MDIO_C45)
121abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe		mdiobb_send_bit(ctrl, 0);
122abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	else
123abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe		mdiobb_send_bit(ctrl, 1);
124abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	mdiobb_send_bit(ctrl, (op >> 1) & 1);
125abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	mdiobb_send_bit(ctrl, (op >> 0) & 1);
126e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
127e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	mdiobb_send_num(ctrl, phy, 5);
128e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	mdiobb_send_num(ctrl, reg, 5);
129e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood}
130e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
131abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe/* In clause 45 mode all commands are prefixed by MDIO_ADDR to specify the
132abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe   lower 16 bits of the 21 bit address. This transfer is done identically to a
133abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe   MDIO_WRITE except for a different code. To enable clause 45 mode or
134abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe   MII_ADDR_C45 into the address. Theoretically clause 45 and normal devices
135abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe   can exist on the same bus. Normal devices should ignore the MDIO_ADDR
136abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe   phase. */
137abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpestatic int mdiobb_cmd_addr(struct mdiobb_ctrl *ctrl, int phy, u32 addr)
138abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe{
139abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	unsigned int dev_addr = (addr >> 16) & 0x1F;
140abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	unsigned int reg = addr & 0xFFFF;
141abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	mdiobb_cmd(ctrl, MDIO_C45_ADDR, phy, dev_addr);
142abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe
143abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	/* send the turnaround (10) */
144abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	mdiobb_send_bit(ctrl, 1);
145abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	mdiobb_send_bit(ctrl, 0);
146abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe
147abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	mdiobb_send_num(ctrl, reg, 16);
148abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe
149abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	ctrl->ops->set_mdio_dir(ctrl, 0);
150abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	mdiobb_get_bit(ctrl);
151abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe
152abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	return dev_addr;
153abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe}
154e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
155e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Woodstatic int mdiobb_read(struct mii_bus *bus, int phy, int reg)
156e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood{
157e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	struct mdiobb_ctrl *ctrl = bus->priv;
158e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	int ret, i;
159e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
160abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	if (reg & MII_ADDR_C45) {
161abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe		reg = mdiobb_cmd_addr(ctrl, phy, reg);
162abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe		mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg);
163abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	} else
164abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe		mdiobb_cmd(ctrl, MDIO_READ, phy, reg);
165abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe
166e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	ctrl->ops->set_mdio_dir(ctrl, 0);
167e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
168e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	/* check the turnaround bit: the PHY should be driving it to zero */
169e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	if (mdiobb_get_bit(ctrl) != 0) {
170e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood		/* PHY didn't drive TA low -- flush any bits it
171e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood		 * may be trying to send.
172e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood		 */
173e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood		for (i = 0; i < 32; i++)
174e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood			mdiobb_get_bit(ctrl);
175e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
176e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood		return 0xffff;
177e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	}
178e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
179e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	ret = mdiobb_get_num(ctrl, 16);
180e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	mdiobb_get_bit(ctrl);
181e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	return ret;
182e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood}
183e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
184e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Woodstatic int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val)
185e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood{
186e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	struct mdiobb_ctrl *ctrl = bus->priv;
187e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
188abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	if (reg & MII_ADDR_C45) {
189abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe		reg = mdiobb_cmd_addr(ctrl, phy, reg);
190abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe		mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg);
191abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe	} else
192abf35df21513c51d7761c41fa6d3b819cdf4103eJason Gunthorpe		mdiobb_cmd(ctrl, MDIO_WRITE, phy, reg);
193e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
194e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	/* send the turnaround (10) */
195e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	mdiobb_send_bit(ctrl, 1);
196e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	mdiobb_send_bit(ctrl, 0);
197e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
198e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	mdiobb_send_num(ctrl, val, 16);
199e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
200e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	ctrl->ops->set_mdio_dir(ctrl, 0);
201e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	mdiobb_get_bit(ctrl);
202e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	return 0;
203e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood}
204e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
20564882709ef07f3eae29c7afc5aa8b84d12733a72Srinivas Kandagatlastatic int mdiobb_reset(struct mii_bus *bus)
20664882709ef07f3eae29c7afc5aa8b84d12733a72Srinivas Kandagatla{
20764882709ef07f3eae29c7afc5aa8b84d12733a72Srinivas Kandagatla	struct mdiobb_ctrl *ctrl = bus->priv;
20864882709ef07f3eae29c7afc5aa8b84d12733a72Srinivas Kandagatla	if (ctrl->reset)
20964882709ef07f3eae29c7afc5aa8b84d12733a72Srinivas Kandagatla		ctrl->reset(bus);
21064882709ef07f3eae29c7afc5aa8b84d12733a72Srinivas Kandagatla	return 0;
21164882709ef07f3eae29c7afc5aa8b84d12733a72Srinivas Kandagatla}
21264882709ef07f3eae29c7afc5aa8b84d12733a72Srinivas Kandagatla
213e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Woodstruct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl)
214e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood{
215e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	struct mii_bus *bus;
216e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
217298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek	bus = mdiobus_alloc();
218e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	if (!bus)
219e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood		return NULL;
220e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
221e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	__module_get(ctrl->ops->owner);
222e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
223e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	bus->read = mdiobb_read;
224e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	bus->write = mdiobb_write;
22564882709ef07f3eae29c7afc5aa8b84d12733a72Srinivas Kandagatla	bus->reset = mdiobb_reset;
226e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	bus->priv = ctrl;
227e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
228e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	return bus;
229e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood}
230e9911c2c8f87cfda47109c42e399fa487117095cTakashi IwaiEXPORT_SYMBOL(alloc_mdio_bitbang);
231e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
232e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Woodvoid free_mdio_bitbang(struct mii_bus *bus)
233e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood{
234e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	struct mdiobb_ctrl *ctrl = bus->priv;
235e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood
236e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood	module_put(ctrl->ops->owner);
237298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek	mdiobus_free(bus);
238e2ec4581adf7e288c193e981c39ca01cdb20a272Scott Wood}
239e9911c2c8f87cfda47109c42e399fa487117095cTakashi IwaiEXPORT_SYMBOL(free_mdio_bitbang);
2405a46236d20faf1ec3712afb28203f7a1adb5d39dRandy Dunlap
2415a46236d20faf1ec3712afb28203f7a1adb5d39dRandy DunlapMODULE_LICENSE("GPL");
242