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