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