arm: mvebu: turris_mox: Check and configure modules
[oweals/u-boot.git] / board / CZ.NIC / turris_mox / turris_mox.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2018 Marek Behun <marek.behun@nic.cz>
4  */
5
6 #include <common.h>
7 #include <asm/gpio.h>
8 #include <asm/io.h>
9 #include <dm.h>
10 #include <clk.h>
11 #include <spi.h>
12 #include <mvebu/comphy.h>
13 #include <miiphy.h>
14 #include <linux/string.h>
15 #include <linux/libfdt.h>
16 #include <fdt_support.h>
17
18 #ifdef CONFIG_WDT_ARMADA_37XX
19 #include <wdt.h>
20 #endif
21
22 #define MAX_MOX_MODULES         10
23
24 #define MOX_MODULE_SFP          0x1
25 #define MOX_MODULE_PCI          0x2
26 #define MOX_MODULE_TOPAZ        0x3
27 #define MOX_MODULE_PERIDOT      0x4
28 #define MOX_MODULE_USB3         0x5
29 #define MOX_MODULE_PASSPCI      0x6
30
31 #define ARMADA_37XX_NB_GPIO_SEL 0xd0013830
32 #define ARMADA_37XX_SPI_CTRL    0xd0010600
33 #define ARMADA_37XX_SPI_CFG     0xd0010604
34 #define ARMADA_37XX_SPI_DOUT    0xd0010608
35 #define ARMADA_37XX_SPI_DIN     0xd001060c
36
37 #define PCIE_PATH       "/soc/pcie@d0070000"
38
39 DECLARE_GLOBAL_DATA_PTR;
40
41 #if defined(CONFIG_OF_BOARD_FIXUP)
42 int board_fix_fdt(void *blob)
43 {
44         u8 topology[MAX_MOX_MODULES];
45         int i, size, node;
46         bool enable;
47
48         /*
49          * SPI driver is not loaded in driver model yet, but we have to find out
50          * if pcie should be enabled in U-Boot's device tree. Therefore we have
51          * to read SPI by reading/writing SPI registers directly
52          */
53
54         writel(0x563fa, ARMADA_37XX_NB_GPIO_SEL);
55         writel(0x10df, ARMADA_37XX_SPI_CFG);
56         writel(0x2005b, ARMADA_37XX_SPI_CTRL);
57
58         while (!(readl(ARMADA_37XX_SPI_CTRL) & 0x2))
59                 udelay(1);
60
61         for (i = 0; i < MAX_MOX_MODULES; ++i) {
62                 writel(0x0, ARMADA_37XX_SPI_DOUT);
63
64                 while (!(readl(ARMADA_37XX_SPI_CTRL) & 0x2))
65                         udelay(1);
66
67                 topology[i] = readl(ARMADA_37XX_SPI_DIN) & 0xff;
68                 if (topology[i] == 0xff)
69                         break;
70
71                 topology[i] &= 0xf;
72         }
73
74         size = i;
75
76         writel(0x5b, ARMADA_37XX_SPI_CTRL);
77
78         if (size > 1 && (topology[1] == MOX_MODULE_PCI ||
79                          topology[1] == MOX_MODULE_USB3 ||
80                          topology[1] == MOX_MODULE_PASSPCI))
81                 enable = true;
82         else
83                 enable = false;
84
85         node = fdt_path_offset(blob, PCIE_PATH);
86
87         if (node < 0) {
88                 printf("Cannot find PCIe node in U-Boot's device tree!\n");
89                 return 0;
90         }
91
92         if (fdt_setprop_string(blob, node, "status",
93                                enable ? "okay" : "disabled") < 0) {
94                 printf("Cannot %s PCIe in U-Boot's device tree!\n",
95                        enable ? "enable" : "disable");
96                 return 0;
97         }
98
99         return 0;
100 }
101 #endif
102
103 #ifdef CONFIG_WDT_ARMADA_37XX
104 static struct udevice *watchdog_dev;
105
106 void watchdog_reset(void)
107 {
108         static ulong next_reset;
109         ulong now;
110
111         if (!watchdog_dev)
112                 return;
113
114         now = timer_get_us();
115
116         /* Do not reset the watchdog too often */
117         if (now > next_reset) {
118                 wdt_reset(watchdog_dev);
119                 next_reset = now + 100000;
120         }
121 }
122 #endif
123
124 int board_init(void)
125 {
126         /* address of boot parameters */
127         gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
128
129 #ifdef CONFIG_WDT_ARMADA_37XX
130         if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) {
131                 printf("Cannot find Armada 3720 watchdog!\n");
132         } else {
133                 printf("Enabling Armada 3720 watchdog (3 minutes timeout).\n");
134                 wdt_start(watchdog_dev, 180000, 0);
135         }
136 #endif
137
138         return 0;
139 }
140
141 static int mox_do_spi(u8 *in, u8 *out, size_t size)
142 {
143         struct spi_slave *slave;
144         struct udevice *dev;
145         int ret;
146
147         ret = spi_get_bus_and_cs(0, 1, 1000000, SPI_CPHA | SPI_CPOL,
148                                  "spi_generic_drv", "moxtet@1", &dev,
149                                  &slave);
150         if (ret)
151                 goto fail;
152
153         ret = spi_claim_bus(slave);
154         if (ret)
155                 goto fail_free;
156
157         ret = spi_xfer(slave, size * 8, out, in, SPI_XFER_ONCE);
158
159         spi_release_bus(slave);
160 fail_free:
161         spi_free_slave(slave);
162 fail:
163         return ret;
164 }
165
166 static int mox_get_topology(const u8 **ptopology, int *psize, int *pis_sd)
167 {
168         static int is_sd;
169         static u8 topology[MAX_MOX_MODULES - 1];
170         static int size;
171         u8 din[MAX_MOX_MODULES], dout[MAX_MOX_MODULES];
172         int ret, i;
173
174         if (size) {
175                 if (ptopology)
176                         *ptopology = topology;
177                 if (psize)
178                         *psize = size;
179                 if (pis_sd)
180                         *pis_sd = is_sd;
181                 return 0;
182         }
183
184         memset(din, 0, MAX_MOX_MODULES);
185         memset(dout, 0, MAX_MOX_MODULES);
186
187         ret = mox_do_spi(din, dout, MAX_MOX_MODULES);
188         if (ret)
189                 return ret;
190
191         if (din[0] == 0x10)
192                 is_sd = 1;
193         else if (din[0] == 0x00)
194                 is_sd = 0;
195         else
196                 return -ENODEV;
197
198         for (i = 1; i < MAX_MOX_MODULES && din[i] != 0xff; ++i)
199                 topology[i - 1] = din[i] & 0xf;
200         size = i - 1;
201
202         if (ptopology)
203                 *ptopology = topology;
204         if (psize)
205                 *psize = size;
206         if (pis_sd)
207                 *pis_sd = is_sd;
208
209         return 0;
210 }
211
212 int comphy_update_map(struct comphy_map *serdes_map, int count)
213 {
214         int ret, i, size, sfpindex = -1, swindex = -1;
215         const u8 *topology;
216
217         ret = mox_get_topology(&topology, &size, NULL);
218         if (ret)
219                 return ret;
220
221         for (i = 0; i < size; ++i) {
222                 if (topology[i] == MOX_MODULE_SFP && sfpindex == -1)
223                         sfpindex = i;
224                 else if ((topology[i] == MOX_MODULE_TOPAZ ||
225                           topology[i] == MOX_MODULE_PERIDOT) &&
226                          swindex == -1)
227                         swindex = i;
228         }
229
230         if (sfpindex >= 0 && swindex >= 0) {
231                 if (sfpindex < swindex)
232                         serdes_map[0].speed = PHY_SPEED_1_25G;
233                 else
234                         serdes_map[0].speed = PHY_SPEED_3_125G;
235         } else if (sfpindex >= 0) {
236                 serdes_map[0].speed = PHY_SPEED_1_25G;
237         } else if (swindex >= 0) {
238                 serdes_map[0].speed = PHY_SPEED_3_125G;
239         }
240
241         return 0;
242 }
243
244 #define SW_SMI_CMD_R(d, r)      (0x9800 | (((d) & 0x1f) << 5) | ((r) & 0x1f))
245 #define SW_SMI_CMD_W(d, r)      (0x9400 | (((d) & 0x1f) << 5) | ((r) & 0x1f))
246
247 static int sw_multi_read(struct mii_dev *bus, int sw, int dev, int reg)
248 {
249         bus->write(bus, sw, 0, 0, SW_SMI_CMD_R(dev, reg));
250         mdelay(5);
251         return bus->read(bus, sw, 0, 1);
252 }
253
254 static void sw_multi_write(struct mii_dev *bus, int sw, int dev, int reg,
255                            u16 val)
256 {
257         bus->write(bus, sw, 0, 1, val);
258         bus->write(bus, sw, 0, 0, SW_SMI_CMD_W(dev, reg));
259         mdelay(5);
260 }
261
262 static int sw_scratch_read(struct mii_dev *bus, int sw, int reg)
263 {
264         sw_multi_write(bus, sw, 0x1c, 0x1a, (reg & 0x7f) << 8);
265         return sw_multi_read(bus, sw, 0x1c, 0x1a) & 0xff;
266 }
267
268 static void sw_led_write(struct mii_dev *bus, int sw, int port, int reg,
269                          u16 val)
270 {
271         sw_multi_write(bus, sw, port, 0x16, 0x8000 | ((reg & 7) << 12)
272                                             | (val & 0x7ff));
273 }
274
275 static void sw_blink_leds(struct mii_dev *bus, int peridot, int topaz)
276 {
277         int i, p;
278         struct {
279                 int port;
280                 u16 val;
281                 int wait;
282         } regs[] = {
283                 { 2, 0xef, 1 }, { 2, 0xfe, 1 }, { 2, 0x33, 0 },
284                 { 4, 0xef, 1 }, { 4, 0xfe, 1 }, { 4, 0x33, 0 },
285                 { 3, 0xfe, 1 }, { 3, 0xef, 1 }, { 3, 0x33, 0 },
286                 { 1, 0xfe, 1 }, { 1, 0xef, 1 }, { 1, 0x33, 0 }
287         };
288
289         for (i = 0; i < 12; ++i) {
290                 for (p = 0; p < peridot; ++p) {
291                         sw_led_write(bus, 0x10 + p, regs[i].port, 0,
292                                      regs[i].val);
293                         sw_led_write(bus, 0x10 + p, regs[i].port + 4, 0,
294                                      regs[i].val);
295                 }
296                 if (topaz) {
297                         sw_led_write(bus, 0x2, 0x10 + regs[i].port, 0,
298                                      regs[i].val);
299                 }
300
301                 if (regs[i].wait)
302                         mdelay(75);
303         }
304 }
305
306 static void check_switch_address(struct mii_dev *bus, int addr)
307 {
308         if (sw_scratch_read(bus, addr, 0x70) >> 3 != addr)
309                 printf("Check of switch MDIO address failed for 0x%02x\n",
310                        addr);
311 }
312
313 static int sfp, pci, topaz, peridot, usb, passpci;
314 static int sfp_pos, peridot_pos[3];
315 static int module_count;
316
317 static int configure_peridots(struct gpio_desc *reset_gpio)
318 {
319         int i, ret;
320         u8 dout[MAX_MOX_MODULES];
321
322         memset(dout, 0, MAX_MOX_MODULES);
323
324         /* set addresses of Peridot modules */
325         for (i = 0; i < peridot; ++i)
326                 dout[module_count - peridot_pos[i]] = (~i) & 3;
327
328         /*
329          * if there is a SFP module connected to the last Peridot module, set
330          * the P10_SMODE to 1 for the Peridot module
331          */
332         if (sfp)
333                 dout[module_count - peridot_pos[i - 1]] |= 1 << 3;
334
335         dm_gpio_set_value(reset_gpio, 1);
336         mdelay(10);
337
338         ret = mox_do_spi(NULL, dout, module_count + 1);
339
340         mdelay(10);
341         dm_gpio_set_value(reset_gpio, 0);
342
343         mdelay(50);
344
345         return ret;
346 }
347
348 static int get_reset_gpio(struct gpio_desc *reset_gpio)
349 {
350         int node;
351
352         node = fdt_node_offset_by_compatible(gd->fdt_blob, 0, "cznic,moxtet");
353         if (node < 0) {
354                 printf("Cannot find Moxtet bus device node!\n");
355                 return -1;
356         }
357
358         gpio_request_by_name_nodev(offset_to_ofnode(node), "reset-gpios", 0,
359                                    reset_gpio, GPIOD_IS_OUT);
360
361         if (!dm_gpio_is_valid(reset_gpio)) {
362                 printf("Cannot find reset GPIO for Moxtet bus!\n");
363                 return -1;
364         }
365
366         return 0;
367 }
368
369 int last_stage_init(void)
370 {
371         int ret, i;
372         const u8 *topology;
373         int is_sd;
374         struct mii_dev *bus;
375         struct gpio_desc reset_gpio = {};
376
377         ret = mox_get_topology(&topology, &module_count, &is_sd);
378         if (ret) {
379                 printf("Cannot read module topology!\n");
380                 return 0;
381         }
382
383         printf("Found Turris Mox %s version\n", is_sd ? "SD" : "eMMC");
384         printf("Module Topology:\n");
385         for (i = 0; i < module_count; ++i) {
386                 switch (topology[i]) {
387                 case MOX_MODULE_SFP:
388                         printf("% 4i: SFP Module\n", i + 1);
389                         break;
390                 case MOX_MODULE_PCI:
391                         printf("% 4i: Mini-PCIe Module\n", i + 1);
392                         break;
393                 case MOX_MODULE_TOPAZ:
394                         printf("% 4i: Topaz Switch Module (4-port)\n", i + 1);
395                         break;
396                 case MOX_MODULE_PERIDOT:
397                         printf("% 4i: Peridot Switch Module (8-port)\n", i + 1);
398                         break;
399                 case MOX_MODULE_USB3:
400                         printf("% 4i: USB 3.0 Module (4 ports)\n", i + 1);
401                         break;
402                 case MOX_MODULE_PASSPCI:
403                         printf("% 4i: Passthrough Mini-PCIe Module\n", i + 1);
404                         break;
405                 default:
406                         printf("% 4i: unknown (ID %i)\n", i + 1, topology[i]);
407                 }
408         }
409
410         /* now check if modules are connected in supported mode */
411
412         for (i = 0; i < module_count; ++i) {
413                 switch (topology[i]) {
414                 case MOX_MODULE_SFP:
415                         if (sfp) {
416                                 printf("Error: Only one SFP module is supported!\n");
417                         } else if (topaz) {
418                                 printf("Error: SFP module cannot be connected after Topaz Switch module!\n");
419                         } else {
420                                 sfp_pos = i;
421                                 ++sfp;
422                         }
423                         break;
424                 case MOX_MODULE_PCI:
425                         if (pci) {
426                                 printf("Error: Only one Mini-PCIe module is supported!\n");
427                         } else if (usb) {
428                                 printf("Error: Mini-PCIe module cannot come after USB 3.0 module!\n");
429                         } else if (i && (i != 1 || !passpci)) {
430                                 printf("Error: Mini-PCIe module should be the first connected module or come right after Passthrough Mini-PCIe module!\n");
431                         } else {
432                                 ++pci;
433                         }
434                         break;
435                 case MOX_MODULE_TOPAZ:
436                         if (topaz) {
437                                 printf("Error: Only one Topaz module is supported!\n");
438                         } else if (peridot >= 3) {
439                                 printf("Error: At most two Peridot modules can come before Topaz module!\n");
440                         } else {
441                                 ++topaz;
442                         }
443                         break;
444                 case MOX_MODULE_PERIDOT:
445                         if (sfp || topaz) {
446                                 printf("Error: Peridot module must come before SFP or Topaz module!\n");
447                         } else if (peridot >= 3) {
448                                 printf("Error: At most three Peridot modules are supported!\n");
449                         } else {
450                                 peridot_pos[peridot] = i;
451                                 ++peridot;
452                         }
453                         break;
454                 case MOX_MODULE_USB3:
455                         if (pci) {
456                                 printf("Error: USB 3.0 module cannot come after Mini-PCIe module!\n");
457                         } else if (usb) {
458                                 printf("Error: Only one USB 3.0 module is supported!\n");
459                         } else if (i && (i != 1 || !passpci)) {
460                                 printf("Error: USB 3.0 module should be the first connected module or come right after Passthrough Mini-PCIe module!\n");
461                         } else {
462                                 ++usb;
463                         }
464                         break;
465                 case MOX_MODULE_PASSPCI:
466                         if (passpci) {
467                                 printf("Error: Only one Passthrough Mini-PCIe module is supported!\n");
468                         } else if (i != 0) {
469                                 printf("Error: Passthrough Mini-PCIe module should be the first connected module!\n");
470                         } else {
471                                 ++passpci;
472                         }
473                 }
474         }
475
476         /* now configure modules */
477
478         if (get_reset_gpio(&reset_gpio) < 0)
479                 return 0;
480
481         if (peridot > 0) {
482                 if (configure_peridots(&reset_gpio) < 0) {
483                         printf("Cannot configure Peridot modules!\n");
484                         peridot = 0;
485                 }
486         } else {
487                 dm_gpio_set_value(&reset_gpio, 1);
488                 mdelay(50);
489                 dm_gpio_set_value(&reset_gpio, 0);
490                 mdelay(50);
491         }
492
493         if (peridot || topaz) {
494                 /*
495                  * now check if the addresses are set by reading Scratch & Misc
496                  * register 0x70 of Peridot (and potentially Topaz) modules
497                  */
498
499                 bus = miiphy_get_dev_by_name("neta@30000");
500                 if (!bus) {
501                         printf("Cannot get MDIO bus device!\n");
502                 } else {
503                         for (i = 0; i < peridot; ++i)
504                                 check_switch_address(bus, 0x10 + i);
505
506                         if (topaz)
507                                 check_switch_address(bus, 0x2);
508
509                         sw_blink_leds(bus, peridot, topaz);
510                 }
511         }
512
513         printf("\n");
514
515         return 0;
516 }