1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2009 Industrie Dial Face S.p.A.
4  * Luigi 'Comio' Mantellini <luigi.mantellini@idf-hit.com>
5  *
6  * (C) Copyright 2001
7  * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
8  */
9 
10 /*
11  * This provides a bit-banged interface to the ethernet MII management
12  * channel.
13  */
14 
15 #include <ioports.h>
16 #include <ppc_asm.tmpl>
17 #include <miiphy.h>
18 #include <asm/global_data.h>
19 
20 /*****************************************************************************
21  *
22  * Utility to send the preamble, address, and register (common to read
23  * and write).
24  */
miiphy_pre(struct mii_dev * miidev,const struct bb_miiphy_bus_ops * ops,char read,unsigned char addr,unsigned char reg)25 static void miiphy_pre(struct mii_dev *miidev, const struct bb_miiphy_bus_ops *ops,
26 		       char read, unsigned char addr, unsigned char reg)
27 {
28 	int j;
29 
30 	/*
31 	 * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure.
32 	 * The IEEE spec says this is a PHY optional requirement.  The AMD
33 	 * 79C874 requires one after power up and one after a MII communications
34 	 * error.  This means that we are doing more preambles than we need,
35 	 * but it is safer and will be much more robust.
36 	 */
37 
38 	ops->mdio_active(miidev);
39 	ops->set_mdio(miidev, 1);
40 	for (j = 0; j < 32; j++) {
41 		ops->set_mdc(miidev, 0);
42 		ops->delay(miidev);
43 		ops->set_mdc(miidev, 1);
44 		ops->delay(miidev);
45 	}
46 
47 	/* send the start bit (01) and the read opcode (10) or write (10) */
48 	ops->set_mdc(miidev, 0);
49 	ops->set_mdio(miidev, 0);
50 	ops->delay(miidev);
51 	ops->set_mdc(miidev, 1);
52 	ops->delay(miidev);
53 	ops->set_mdc(miidev, 0);
54 	ops->set_mdio(miidev, 1);
55 	ops->delay(miidev);
56 	ops->set_mdc(miidev, 1);
57 	ops->delay(miidev);
58 	ops->set_mdc(miidev, 0);
59 	ops->set_mdio(miidev, read);
60 	ops->delay(miidev);
61 	ops->set_mdc(miidev, 1);
62 	ops->delay(miidev);
63 	ops->set_mdc(miidev, 0);
64 	ops->set_mdio(miidev, !read);
65 	ops->delay(miidev);
66 	ops->set_mdc(miidev, 1);
67 	ops->delay(miidev);
68 
69 	/* send the PHY address */
70 	for (j = 0; j < 5; j++) {
71 		ops->set_mdc(miidev, 0);
72 		if ((addr & 0x10) == 0) {
73 			ops->set_mdio(miidev, 0);
74 		} else {
75 			ops->set_mdio(miidev, 1);
76 		}
77 		ops->delay(miidev);
78 		ops->set_mdc(miidev, 1);
79 		ops->delay(miidev);
80 		addr <<= 1;
81 	}
82 
83 	/* send the register address */
84 	for (j = 0; j < 5; j++) {
85 		ops->set_mdc(miidev, 0);
86 		if ((reg & 0x10) == 0) {
87 			ops->set_mdio(miidev, 0);
88 		} else {
89 			ops->set_mdio(miidev, 1);
90 		}
91 		ops->delay(miidev);
92 		ops->set_mdc(miidev, 1);
93 		ops->delay(miidev);
94 		reg <<= 1;
95 	}
96 }
97 
98 /*****************************************************************************
99  *
100  * Read a MII PHY register.
101  *
102  * Returns:
103  *   0 on success
104  */
bb_miiphy_read(struct mii_dev * miidev,const struct bb_miiphy_bus_ops * ops,int addr,int devad,int reg)105 int bb_miiphy_read(struct mii_dev *miidev, const struct bb_miiphy_bus_ops *ops,
106 		   int addr, int devad, int reg)
107 {
108 	unsigned short rdreg; /* register working value */
109 	int v;
110 	int j; /* counter */
111 
112 	miiphy_pre(miidev, ops, 1, addr, reg);
113 
114 	/* tri-state our MDIO I/O pin so we can read */
115 	ops->set_mdc(miidev, 0);
116 	ops->mdio_tristate(miidev);
117 	ops->delay(miidev);
118 	ops->set_mdc(miidev, 1);
119 	ops->delay(miidev);
120 
121 	/* check the turnaround bit: the PHY should be driving it to zero */
122 	ops->get_mdio(miidev, &v);
123 	if (v != 0) {
124 		/* puts ("PHY didn't drive TA low\n"); */
125 		for (j = 0; j < 32; j++) {
126 			ops->set_mdc(miidev, 0);
127 			ops->delay(miidev);
128 			ops->set_mdc(miidev, 1);
129 			ops->delay(miidev);
130 		}
131 		/* There is no PHY, return */
132 		return -1;
133 	}
134 
135 	ops->set_mdc(miidev, 0);
136 	ops->delay(miidev);
137 
138 	/* read 16 bits of register data, MSB first */
139 	rdreg = 0;
140 	for (j = 0; j < 16; j++) {
141 		ops->set_mdc(miidev, 1);
142 		ops->delay(miidev);
143 		rdreg <<= 1;
144 		ops->get_mdio(miidev, &v);
145 		rdreg |= (v & 0x1);
146 		ops->set_mdc(miidev, 0);
147 		ops->delay(miidev);
148 	}
149 
150 	ops->set_mdc(miidev, 1);
151 	ops->delay(miidev);
152 	ops->set_mdc(miidev, 0);
153 	ops->delay(miidev);
154 	ops->set_mdc(miidev, 1);
155 	ops->delay(miidev);
156 
157 	debug("%s[%s](0x%x) @ 0x%x = 0x%04x\n", __func__, miidev->name, reg, addr, rdreg);
158 
159 	return rdreg;
160 }
161 
162 /*****************************************************************************
163  *
164  * Write a MII PHY register.
165  *
166  * Returns:
167  *   0 on success
168  */
bb_miiphy_write(struct mii_dev * miidev,const struct bb_miiphy_bus_ops * ops,int addr,int devad,int reg,u16 value)169 int bb_miiphy_write(struct mii_dev *miidev, const struct bb_miiphy_bus_ops *ops,
170 		    int addr, int devad, int reg, u16 value)
171 {
172 	int j;			/* counter */
173 
174 	miiphy_pre(miidev, ops, 0, addr, reg);
175 
176 	/* send the turnaround (10) */
177 	ops->set_mdc(miidev, 0);
178 	ops->set_mdio(miidev, 1);
179 	ops->delay(miidev);
180 	ops->set_mdc(miidev, 1);
181 	ops->delay(miidev);
182 	ops->set_mdc(miidev, 0);
183 	ops->set_mdio(miidev, 0);
184 	ops->delay(miidev);
185 	ops->set_mdc(miidev, 1);
186 	ops->delay(miidev);
187 
188 	/* write 16 bits of register data, MSB first */
189 	for (j = 0; j < 16; j++) {
190 		ops->set_mdc(miidev, 0);
191 		if ((value & 0x00008000) == 0) {
192 			ops->set_mdio(miidev, 0);
193 		} else {
194 			ops->set_mdio(miidev, 1);
195 		}
196 		ops->delay(miidev);
197 		ops->set_mdc(miidev, 1);
198 		ops->delay(miidev);
199 		value <<= 1;
200 	}
201 
202 	/*
203 	 * Tri-state the MDIO line.
204 	 */
205 	ops->mdio_tristate(miidev);
206 	ops->set_mdc(miidev, 0);
207 	ops->delay(miidev);
208 	ops->set_mdc(miidev, 1);
209 	ops->delay(miidev);
210 
211 	return 0;
212 }
213