net: phy: cortina: Use block layer to read from mmc
[oweals/u-boot.git] / drivers / net / phy / miiphybb.c
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 <common.h>
16 #include <ioports.h>
17 #include <ppc_asm.tmpl>
18 #include <miiphy.h>
19
20 #define BB_MII_RELOCATE(v,off) (v += (v?off:0))
21
22 DECLARE_GLOBAL_DATA_PTR;
23
24 #ifndef CONFIG_BITBANGMII_MULTI
25
26 /*
27  * If CONFIG_BITBANGMII_MULTI is not defined we use a
28  * compatibility layer with the previous miiphybb implementation
29  * based on macros usage.
30  *
31  */
32 static int bb_mii_init_wrap(struct bb_miiphy_bus *bus)
33 {
34 #ifdef MII_INIT
35         MII_INIT;
36 #endif
37         return 0;
38 }
39
40 static int bb_mdio_active_wrap(struct bb_miiphy_bus *bus)
41 {
42 #ifdef MDIO_DECLARE
43         MDIO_DECLARE;
44 #endif
45         MDIO_ACTIVE;
46         return 0;
47 }
48
49 static int bb_mdio_tristate_wrap(struct bb_miiphy_bus *bus)
50 {
51 #ifdef MDIO_DECLARE
52         MDIO_DECLARE;
53 #endif
54         MDIO_TRISTATE;
55         return 0;
56 }
57
58 static int bb_set_mdio_wrap(struct bb_miiphy_bus *bus, int v)
59 {
60 #ifdef MDIO_DECLARE
61         MDIO_DECLARE;
62 #endif
63         MDIO(v);
64         return 0;
65 }
66
67 static int bb_get_mdio_wrap(struct bb_miiphy_bus *bus, int *v)
68 {
69 #ifdef MDIO_DECLARE
70         MDIO_DECLARE;
71 #endif
72         *v = MDIO_READ;
73         return 0;
74 }
75
76 static int bb_set_mdc_wrap(struct bb_miiphy_bus *bus, int v)
77 {
78 #ifdef MDC_DECLARE
79         MDC_DECLARE;
80 #endif
81         MDC(v);
82         return 0;
83 }
84
85 static int bb_delay_wrap(struct bb_miiphy_bus *bus)
86 {
87         MIIDELAY;
88         return 0;
89 }
90
91 struct bb_miiphy_bus bb_miiphy_buses[] = {
92         {
93                 .name = BB_MII_DEVNAME,
94                 .init = bb_mii_init_wrap,
95                 .mdio_active = bb_mdio_active_wrap,
96                 .mdio_tristate = bb_mdio_tristate_wrap,
97                 .set_mdio = bb_set_mdio_wrap,
98                 .get_mdio = bb_get_mdio_wrap,
99                 .set_mdc = bb_set_mdc_wrap,
100                 .delay = bb_delay_wrap,
101         }
102 };
103
104 int bb_miiphy_buses_num = sizeof(bb_miiphy_buses) /
105                           sizeof(bb_miiphy_buses[0]);
106 #endif
107
108 void bb_miiphy_init(void)
109 {
110         int i;
111
112         for (i = 0; i < bb_miiphy_buses_num; i++) {
113 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
114                 /* Relocate the hook pointers*/
115                 BB_MII_RELOCATE(bb_miiphy_buses[i].init, gd->reloc_off);
116                 BB_MII_RELOCATE(bb_miiphy_buses[i].mdio_active, gd->reloc_off);
117                 BB_MII_RELOCATE(bb_miiphy_buses[i].mdio_tristate, gd->reloc_off);
118                 BB_MII_RELOCATE(bb_miiphy_buses[i].set_mdio, gd->reloc_off);
119                 BB_MII_RELOCATE(bb_miiphy_buses[i].get_mdio, gd->reloc_off);
120                 BB_MII_RELOCATE(bb_miiphy_buses[i].set_mdc, gd->reloc_off);
121                 BB_MII_RELOCATE(bb_miiphy_buses[i].delay, gd->reloc_off);
122 #endif
123                 if (bb_miiphy_buses[i].init != NULL) {
124                         bb_miiphy_buses[i].init(&bb_miiphy_buses[i]);
125                 }
126         }
127 }
128
129 static inline struct bb_miiphy_bus *bb_miiphy_getbus(const char *devname)
130 {
131 #ifdef CONFIG_BITBANGMII_MULTI
132         int i;
133
134         /* Search the correct bus */
135         for (i = 0; i < bb_miiphy_buses_num; i++) {
136                 if (!strcmp(bb_miiphy_buses[i].name, devname)) {
137                         return &bb_miiphy_buses[i];
138                 }
139         }
140         return NULL;
141 #else
142         /* We have just one bitbanging bus */
143         return &bb_miiphy_buses[0];
144 #endif
145 }
146
147 /*****************************************************************************
148  *
149  * Utility to send the preamble, address, and register (common to read
150  * and write).
151  */
152 static void miiphy_pre(struct bb_miiphy_bus *bus, char read,
153                        unsigned char addr, unsigned char reg)
154 {
155         int j;
156
157         /*
158          * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure.
159          * The IEEE spec says this is a PHY optional requirement.  The AMD
160          * 79C874 requires one after power up and one after a MII communications
161          * error.  This means that we are doing more preambles than we need,
162          * but it is safer and will be much more robust.
163          */
164
165         bus->mdio_active(bus);
166         bus->set_mdio(bus, 1);
167         for (j = 0; j < 32; j++) {
168                 bus->set_mdc(bus, 0);
169                 bus->delay(bus);
170                 bus->set_mdc(bus, 1);
171                 bus->delay(bus);
172         }
173
174         /* send the start bit (01) and the read opcode (10) or write (10) */
175         bus->set_mdc(bus, 0);
176         bus->set_mdio(bus, 0);
177         bus->delay(bus);
178         bus->set_mdc(bus, 1);
179         bus->delay(bus);
180         bus->set_mdc(bus, 0);
181         bus->set_mdio(bus, 1);
182         bus->delay(bus);
183         bus->set_mdc(bus, 1);
184         bus->delay(bus);
185         bus->set_mdc(bus, 0);
186         bus->set_mdio(bus, read);
187         bus->delay(bus);
188         bus->set_mdc(bus, 1);
189         bus->delay(bus);
190         bus->set_mdc(bus, 0);
191         bus->set_mdio(bus, !read);
192         bus->delay(bus);
193         bus->set_mdc(bus, 1);
194         bus->delay(bus);
195
196         /* send the PHY address */
197         for (j = 0; j < 5; j++) {
198                 bus->set_mdc(bus, 0);
199                 if ((addr & 0x10) == 0) {
200                         bus->set_mdio(bus, 0);
201                 } else {
202                         bus->set_mdio(bus, 1);
203                 }
204                 bus->delay(bus);
205                 bus->set_mdc(bus, 1);
206                 bus->delay(bus);
207                 addr <<= 1;
208         }
209
210         /* send the register address */
211         for (j = 0; j < 5; j++) {
212                 bus->set_mdc(bus, 0);
213                 if ((reg & 0x10) == 0) {
214                         bus->set_mdio(bus, 0);
215                 } else {
216                         bus->set_mdio(bus, 1);
217                 }
218                 bus->delay(bus);
219                 bus->set_mdc(bus, 1);
220                 bus->delay(bus);
221                 reg <<= 1;
222         }
223 }
224
225 /*****************************************************************************
226  *
227  * Read a MII PHY register.
228  *
229  * Returns:
230  *   0 on success
231  */
232 int bb_miiphy_read(struct mii_dev *miidev, int addr, int devad, int reg)
233 {
234         unsigned short rdreg; /* register working value */
235         int v;
236         int j; /* counter */
237         struct bb_miiphy_bus *bus;
238
239         bus = bb_miiphy_getbus(miidev->name);
240         if (bus == NULL) {
241                 return -1;
242         }
243
244         miiphy_pre (bus, 1, addr, reg);
245
246         /* tri-state our MDIO I/O pin so we can read */
247         bus->set_mdc(bus, 0);
248         bus->mdio_tristate(bus);
249         bus->delay(bus);
250         bus->set_mdc(bus, 1);
251         bus->delay(bus);
252
253         /* check the turnaround bit: the PHY should be driving it to zero */
254         bus->get_mdio(bus, &v);
255         if (v != 0) {
256                 /* puts ("PHY didn't drive TA low\n"); */
257                 for (j = 0; j < 32; j++) {
258                         bus->set_mdc(bus, 0);
259                         bus->delay(bus);
260                         bus->set_mdc(bus, 1);
261                         bus->delay(bus);
262                 }
263                 /* There is no PHY, return */
264                 return -1;
265         }
266
267         bus->set_mdc(bus, 0);
268         bus->delay(bus);
269
270         /* read 16 bits of register data, MSB first */
271         rdreg = 0;
272         for (j = 0; j < 16; j++) {
273                 bus->set_mdc(bus, 1);
274                 bus->delay(bus);
275                 rdreg <<= 1;
276                 bus->get_mdio(bus, &v);
277                 rdreg |= (v & 0x1);
278                 bus->set_mdc(bus, 0);
279                 bus->delay(bus);
280         }
281
282         bus->set_mdc(bus, 1);
283         bus->delay(bus);
284         bus->set_mdc(bus, 0);
285         bus->delay(bus);
286         bus->set_mdc(bus, 1);
287         bus->delay(bus);
288
289 #ifdef DEBUG
290         printf("miiphy_read(0x%x) @ 0x%x = 0x%04x\n", reg, addr, rdreg);
291 #endif
292
293         return rdreg;
294 }
295
296
297 /*****************************************************************************
298  *
299  * Write a MII PHY register.
300  *
301  * Returns:
302  *   0 on success
303  */
304 int bb_miiphy_write(struct mii_dev *miidev, int addr, int devad, int reg,
305                     u16 value)
306 {
307         struct bb_miiphy_bus *bus;
308         int j;                  /* counter */
309
310         bus = bb_miiphy_getbus(miidev->name);
311         if (bus == NULL) {
312                 /* Bus not found! */
313                 return -1;
314         }
315
316         miiphy_pre (bus, 0, addr, reg);
317
318         /* send the turnaround (10) */
319         bus->set_mdc(bus, 0);
320         bus->set_mdio(bus, 1);
321         bus->delay(bus);
322         bus->set_mdc(bus, 1);
323         bus->delay(bus);
324         bus->set_mdc(bus, 0);
325         bus->set_mdio(bus, 0);
326         bus->delay(bus);
327         bus->set_mdc(bus, 1);
328         bus->delay(bus);
329
330         /* write 16 bits of register data, MSB first */
331         for (j = 0; j < 16; j++) {
332                 bus->set_mdc(bus, 0);
333                 if ((value & 0x00008000) == 0) {
334                         bus->set_mdio(bus, 0);
335                 } else {
336                         bus->set_mdio(bus, 1);
337                 }
338                 bus->delay(bus);
339                 bus->set_mdc(bus, 1);
340                 bus->delay(bus);
341                 value <<= 1;
342         }
343
344         /*
345          * Tri-state the MDIO line.
346          */
347         bus->mdio_tristate(bus);
348         bus->set_mdc(bus, 0);
349         bus->delay(bus);
350         bus->set_mdc(bus, 1);
351         bus->delay(bus);
352
353         return 0;
354 }