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