arm: mvebu: turris_mox: Check and configure modules
[project/bcm63xx/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 }