common: Drop linux/delay.h from common header
[oweals/u-boot.git] / board / gdsys / a38x / ihs_phys.c
1 #include <common.h>
2 #include <dm.h>
3 #include <miiphy.h>
4 #include <asm-generic/gpio.h>
5 #include <linux/delay.h>
6
7 #include "ihs_phys.h"
8 #include "dt_helpers.h"
9
10 enum {
11         PORTTYPE_MAIN_CAT,
12         PORTTYPE_TOP_CAT,
13         PORTTYPE_16C_16F,
14         PORTTYPE_UNKNOWN
15 };
16
17 static struct porttype {
18         bool phy_invert_in_pol;
19         bool phy_invert_out_pol;
20 } porttypes[] = {
21         { true, false },
22         { false, true },
23         { false, false },
24 };
25
26 static void ihs_phy_config(struct phy_device *phydev, bool qinpn, bool qoutpn)
27 {
28         u16 reg;
29
30         phy_config(phydev);
31
32         /* enable QSGMII autonegotiation with flow control */
33         phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0004);
34         reg = phy_read(phydev, MDIO_DEVAD_NONE, 16);
35         reg |= (3 << 6);
36         phy_write(phydev, MDIO_DEVAD_NONE, 16, reg);
37
38         /*
39          * invert QSGMII Q_INP/N and Q_OUTP/N if required
40          * and perform global reset
41          */
42         reg = phy_read(phydev, MDIO_DEVAD_NONE, 26);
43         if (qinpn)
44                 reg |= (1 << 13);
45         if (qoutpn)
46                 reg |= (1 << 12);
47         reg |= (1 << 15);
48         phy_write(phydev, MDIO_DEVAD_NONE, 26, reg);
49
50         /* advertise 1000BASE-T full-duplex only  */
51         phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0000);
52         reg = phy_read(phydev, MDIO_DEVAD_NONE, 4);
53         reg &= ~0x1e0;
54         phy_write(phydev, MDIO_DEVAD_NONE, 4, reg);
55         reg = phy_read(phydev, MDIO_DEVAD_NONE, 9);
56         reg = (reg & ~0x300) | 0x200;
57         phy_write(phydev, MDIO_DEVAD_NONE, 9, reg);
58
59         /* copper power up */
60         reg = phy_read(phydev, MDIO_DEVAD_NONE, 16);
61         reg &= ~0x0004;
62         phy_write(phydev, MDIO_DEVAD_NONE, 16, reg);
63 }
64
65 uint calculate_octo_phy_mask(void)
66 {
67         uint k;
68         uint octo_phy_mask = 0;
69         struct gpio_desc gpio = {};
70         char gpio_name[64];
71         static const char * const dev_name[] = {"pca9698@23", "pca9698@21",
72                                                 "pca9698@24", "pca9698@25",
73                                                 "pca9698@26"};
74
75         /* mark all octo phys that should be present */
76         for (k = 0; k < 5; ++k) {
77                 snprintf(gpio_name, 64, "cat-gpio-%u", k);
78
79                 if (request_gpio_by_name(&gpio, dev_name[k], 0x20, gpio_name))
80                         continue;
81
82                 /* check CAT flag */
83                 if (dm_gpio_get_value(&gpio))
84                         octo_phy_mask |= (1 << (k * 2));
85                 else
86                         /* If CAT == 0, there's no second octo phy -> skip */
87                         continue;
88
89                 snprintf(gpio_name, 64, "second-octo-gpio-%u", k);
90
91                 if (request_gpio_by_name(&gpio, dev_name[k], 0x27, gpio_name)) {
92                         /* default: second octo phy is present */
93                         octo_phy_mask |= (1 << (k * 2 + 1));
94                         continue;
95                 }
96
97                 if (dm_gpio_get_value(&gpio) == 0)
98                         octo_phy_mask |= (1 << (k * 2 + 1));
99         }
100
101         return octo_phy_mask;
102 }
103
104 int register_miiphy_bus(uint k, struct mii_dev **bus)
105 {
106         int retval;
107         struct mii_dev *mdiodev = mdio_alloc();
108         char *name = bb_miiphy_buses[k].name;
109
110         if (!mdiodev)
111                 return -ENOMEM;
112         strncpy(mdiodev->name,
113                 name,
114                 MDIO_NAME_LEN);
115         mdiodev->read = bb_miiphy_read;
116         mdiodev->write = bb_miiphy_write;
117
118         retval = mdio_register(mdiodev);
119         if (retval < 0)
120                 return retval;
121         *bus = miiphy_get_dev_by_name(name);
122
123         return 0;
124 }
125
126 struct porttype *get_porttype(uint octo_phy_mask, uint k)
127 {
128         uint octo_index = k * 4;
129
130         if (!k) {
131                 if (octo_phy_mask & 0x01)
132                         return &porttypes[PORTTYPE_MAIN_CAT];
133                 else if (!(octo_phy_mask & 0x03))
134                         return &porttypes[PORTTYPE_16C_16F];
135         } else {
136                 if (octo_phy_mask & (1 << octo_index))
137                         return &porttypes[PORTTYPE_TOP_CAT];
138         }
139
140         return NULL;
141 }
142
143 int init_single_phy(struct porttype *porttype, struct mii_dev *bus,
144                     uint bus_idx, uint m, uint phy_idx)
145 {
146         struct phy_device *phydev = phy_find_by_mask(
147                 bus, 1 << (m * 8 + phy_idx),
148                 PHY_INTERFACE_MODE_MII);
149
150         printf(" %u", bus_idx * 32 + m * 8 + phy_idx);
151
152         if (!phydev)
153                 puts("!");
154         else
155                 ihs_phy_config(phydev, porttype->phy_invert_in_pol,
156                                porttype->phy_invert_out_pol);
157
158         return 0;
159 }
160
161 int init_octo_phys(uint octo_phy_mask)
162 {
163         uint bus_idx;
164
165         /* there are up to four octo-phys on each mdio bus */
166         for (bus_idx = 0; bus_idx < bb_miiphy_buses_num; ++bus_idx) {
167                 uint m;
168                 uint octo_index = bus_idx * 4;
169                 struct mii_dev *bus = NULL;
170                 struct porttype *porttype = NULL;
171                 int ret;
172
173                 porttype = get_porttype(octo_phy_mask, bus_idx);
174
175                 if (!porttype)
176                         continue;
177
178                 for (m = 0; m < 4; ++m) {
179                         uint phy_idx;
180
181                         /**
182                          * Register a bus device if there is at least one phy
183                          * on the current bus
184                          */
185                         if (!m && octo_phy_mask & (0xf << octo_index)) {
186                                 ret = register_miiphy_bus(bus_idx, &bus);
187                                 if (ret)
188                                         return ret;
189                         }
190
191                         if (!(octo_phy_mask & BIT(octo_index + m)))
192                                 continue;
193
194                         for (phy_idx = 0; phy_idx < 8; ++phy_idx)
195                                 init_single_phy(porttype, bus, bus_idx, m,
196                                                 phy_idx);
197                 }
198         }
199
200         return 0;
201 }
202
203 /*
204  * MII GPIO bitbang implementation
205  * MDC MDIO bus
206  * 13  14   PHY1-4
207  * 25  45   PHY5-8
208  * 46  24   PHY9-10
209  */
210
211 struct gpio_mii {
212         int index;
213         struct gpio_desc mdc_gpio;
214         struct gpio_desc mdio_gpio;
215         int mdc_num;
216         int mdio_num;
217         int mdio_value;
218 } gpio_mii_set[] = {
219         { 0, {}, {}, 13, 14, 1 },
220         { 1, {}, {}, 25, 45, 1 },
221         { 2, {}, {}, 46, 24, 1 },
222 };
223
224 static int mii_mdio_init(struct bb_miiphy_bus *bus)
225 {
226         struct gpio_mii *gpio_mii = bus->priv;
227         char name[32] = {};
228         struct udevice *gpio_dev1 = NULL;
229         struct udevice *gpio_dev2 = NULL;
230
231         if (uclass_get_device_by_name(UCLASS_GPIO, "gpio@18100", &gpio_dev1) ||
232             uclass_get_device_by_name(UCLASS_GPIO, "gpio@18140", &gpio_dev2)) {
233                 printf("Could not get GPIO device.\n");
234                 return 1;
235         }
236
237         if (gpio_mii->mdc_num > 31) {
238                 gpio_mii->mdc_gpio.dev = gpio_dev2;
239                 gpio_mii->mdc_gpio.offset = gpio_mii->mdc_num - 32;
240         } else {
241                 gpio_mii->mdc_gpio.dev = gpio_dev1;
242                 gpio_mii->mdc_gpio.offset = gpio_mii->mdc_num;
243         }
244         gpio_mii->mdc_gpio.flags = 0;
245         snprintf(name, 32, "bb_miiphy_bus-%d-mdc", gpio_mii->index);
246         dm_gpio_request(&gpio_mii->mdc_gpio, name);
247
248         if (gpio_mii->mdio_num > 31) {
249                 gpio_mii->mdio_gpio.dev = gpio_dev2;
250                 gpio_mii->mdio_gpio.offset = gpio_mii->mdio_num - 32;
251         } else {
252                 gpio_mii->mdio_gpio.dev = gpio_dev1;
253                 gpio_mii->mdio_gpio.offset = gpio_mii->mdio_num;
254         }
255         gpio_mii->mdio_gpio.flags = 0;
256         snprintf(name, 32, "bb_miiphy_bus-%d-mdio", gpio_mii->index);
257         dm_gpio_request(&gpio_mii->mdio_gpio, name);
258
259         dm_gpio_set_dir_flags(&gpio_mii->mdc_gpio, GPIOD_IS_OUT);
260         dm_gpio_set_value(&gpio_mii->mdc_gpio, 1);
261
262         return 0;
263 }
264
265 static int mii_mdio_active(struct bb_miiphy_bus *bus)
266 {
267         struct gpio_mii *gpio_mii = bus->priv;
268
269         dm_gpio_set_value(&gpio_mii->mdc_gpio, gpio_mii->mdio_value);
270
271         return 0;
272 }
273
274 static int mii_mdio_tristate(struct bb_miiphy_bus *bus)
275 {
276         struct gpio_mii *gpio_mii = bus->priv;
277
278         dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_IN);
279
280         return 0;
281 }
282
283 static int mii_set_mdio(struct bb_miiphy_bus *bus, int v)
284 {
285         struct gpio_mii *gpio_mii = bus->priv;
286
287         dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_OUT);
288         dm_gpio_set_value(&gpio_mii->mdio_gpio, v);
289         gpio_mii->mdio_value = v;
290
291         return 0;
292 }
293
294 static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v)
295 {
296         struct gpio_mii *gpio_mii = bus->priv;
297
298         dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_IN);
299         *v = (dm_gpio_get_value(&gpio_mii->mdio_gpio));
300
301         return 0;
302 }
303
304 static int mii_set_mdc(struct bb_miiphy_bus *bus, int v)
305 {
306         struct gpio_mii *gpio_mii = bus->priv;
307
308         dm_gpio_set_value(&gpio_mii->mdc_gpio, v);
309
310         return 0;
311 }
312
313 static int mii_delay(struct bb_miiphy_bus *bus)
314 {
315         udelay(1);
316
317         return 0;
318 }
319
320 struct bb_miiphy_bus bb_miiphy_buses[] = {
321         {
322                 .name = "ihs0",
323                 .init = mii_mdio_init,
324                 .mdio_active = mii_mdio_active,
325                 .mdio_tristate = mii_mdio_tristate,
326                 .set_mdio = mii_set_mdio,
327                 .get_mdio = mii_get_mdio,
328                 .set_mdc = mii_set_mdc,
329                 .delay = mii_delay,
330                 .priv = &gpio_mii_set[0],
331         },
332         {
333                 .name = "ihs1",
334                 .init = mii_mdio_init,
335                 .mdio_active = mii_mdio_active,
336                 .mdio_tristate = mii_mdio_tristate,
337                 .set_mdio = mii_set_mdio,
338                 .get_mdio = mii_get_mdio,
339                 .set_mdc = mii_set_mdc,
340                 .delay = mii_delay,
341                 .priv = &gpio_mii_set[1],
342         },
343         {
344                 .name = "ihs2",
345                 .init = mii_mdio_init,
346                 .mdio_active = mii_mdio_active,
347                 .mdio_tristate = mii_mdio_tristate,
348                 .set_mdio = mii_set_mdio,
349                 .get_mdio = mii_get_mdio,
350                 .set_mdc = mii_set_mdc,
351                 .delay = mii_delay,
352                 .priv = &gpio_mii_set[2],
353         },
354 };
355
356 int bb_miiphy_buses_num = ARRAY_SIZE(bb_miiphy_buses);