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