blob: 65d50a92ddfe7b5a898d3757b8726943653b5488 [file] [log] [blame]
Marek Behúnf835bed2018-04-24 17:21:31 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2018 Marek Behun <marek.behun@nic.cz>
4 */
5
6#include <common.h>
Marek Behún35b35132018-12-17 16:10:03 +01007#include <asm/gpio.h>
Marek Behún9602a8c2018-08-21 12:22:09 +02008#include <asm/io.h>
Marek Behúnf835bed2018-04-24 17:21:31 +02009#include <dm.h>
10#include <clk.h>
11#include <spi.h>
Marek Behúna261d132018-12-17 16:10:02 +010012#include <mvebu/comphy.h>
Marek Behún35b35132018-12-17 16:10:03 +010013#include <miiphy.h>
Marek Behúnf835bed2018-04-24 17:21:31 +020014#include <linux/string.h>
Marek Behún9602a8c2018-08-21 12:22:09 +020015#include <linux/libfdt.h>
16#include <fdt_support.h>
Marek Behún35572c92018-12-17 16:10:08 +010017#include <environment.h>
Marek Behúnf835bed2018-04-24 17:21:31 +020018
Marek Behúnceb05932018-08-17 12:58:53 +020019#ifdef CONFIG_WDT_ARMADA_37XX
Marek Behúnf835bed2018-04-24 17:21:31 +020020#include <wdt.h>
21#endif
22
Marek Behún35572c92018-12-17 16:10:08 +010023#include "mox_sp.h"
24
Marek Behún9602a8c2018-08-21 12:22:09 +020025#define MAX_MOX_MODULES 10
26
27#define MOX_MODULE_SFP 0x1
28#define MOX_MODULE_PCI 0x2
29#define MOX_MODULE_TOPAZ 0x3
30#define MOX_MODULE_PERIDOT 0x4
31#define MOX_MODULE_USB3 0x5
32#define MOX_MODULE_PASSPCI 0x6
33
34#define ARMADA_37XX_NB_GPIO_SEL 0xd0013830
35#define ARMADA_37XX_SPI_CTRL 0xd0010600
36#define ARMADA_37XX_SPI_CFG 0xd0010604
37#define ARMADA_37XX_SPI_DOUT 0xd0010608
38#define ARMADA_37XX_SPI_DIN 0xd001060c
39
40#define PCIE_PATH "/soc/pcie@d0070000"
41
Marek Behúnf835bed2018-04-24 17:21:31 +020042DECLARE_GLOBAL_DATA_PTR;
43
Marek Behún22a0ce32018-12-17 16:10:09 +010044int dram_init(void)
45{
46 gd->ram_base = 0;
47 gd->ram_size = (phys_size_t)get_ram_size(0, 0x40000000);
48
49 return 0;
50}
51
52int dram_init_banksize(void)
53{
54 gd->bd->bi_dram[0].start = (phys_addr_t)0;
55 gd->bd->bi_dram[0].size = gd->ram_size;
56
57 return 0;
58}
59
Marek Behún9602a8c2018-08-21 12:22:09 +020060#if defined(CONFIG_OF_BOARD_FIXUP)
61int board_fix_fdt(void *blob)
62{
63 u8 topology[MAX_MOX_MODULES];
64 int i, size, node;
65 bool enable;
66
67 /*
68 * SPI driver is not loaded in driver model yet, but we have to find out
69 * if pcie should be enabled in U-Boot's device tree. Therefore we have
70 * to read SPI by reading/writing SPI registers directly
71 */
72
73 writel(0x563fa, ARMADA_37XX_NB_GPIO_SEL);
74 writel(0x10df, ARMADA_37XX_SPI_CFG);
75 writel(0x2005b, ARMADA_37XX_SPI_CTRL);
76
77 while (!(readl(ARMADA_37XX_SPI_CTRL) & 0x2))
78 udelay(1);
79
80 for (i = 0; i < MAX_MOX_MODULES; ++i) {
81 writel(0x0, ARMADA_37XX_SPI_DOUT);
82
83 while (!(readl(ARMADA_37XX_SPI_CTRL) & 0x2))
84 udelay(1);
85
86 topology[i] = readl(ARMADA_37XX_SPI_DIN) & 0xff;
87 if (topology[i] == 0xff)
88 break;
89
90 topology[i] &= 0xf;
91 }
92
93 size = i;
94
95 writel(0x5b, ARMADA_37XX_SPI_CTRL);
96
97 if (size > 1 && (topology[1] == MOX_MODULE_PCI ||
98 topology[1] == MOX_MODULE_USB3 ||
99 topology[1] == MOX_MODULE_PASSPCI))
100 enable = true;
101 else
102 enable = false;
103
104 node = fdt_path_offset(blob, PCIE_PATH);
105
106 if (node < 0) {
107 printf("Cannot find PCIe node in U-Boot's device tree!\n");
108 return 0;
109 }
110
111 if (fdt_setprop_string(blob, node, "status",
112 enable ? "okay" : "disabled") < 0) {
113 printf("Cannot %s PCIe in U-Boot's device tree!\n",
114 enable ? "enable" : "disable");
115 return 0;
116 }
117
118 return 0;
119}
120#endif
121
Marek Behúnceb05932018-08-17 12:58:53 +0200122#ifdef CONFIG_WDT_ARMADA_37XX
Marek Behúnf835bed2018-04-24 17:21:31 +0200123static struct udevice *watchdog_dev;
124
125void watchdog_reset(void)
126{
127 static ulong next_reset;
128 ulong now;
129
130 if (!watchdog_dev)
131 return;
132
133 now = timer_get_us();
134
135 /* Do not reset the watchdog too often */
136 if (now > next_reset) {
137 wdt_reset(watchdog_dev);
138 next_reset = now + 100000;
139 }
140}
141#endif
142
143int board_init(void)
144{
145 /* address of boot parameters */
146 gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
147
Marek Behúnceb05932018-08-17 12:58:53 +0200148#ifdef CONFIG_WDT_ARMADA_37XX
Marek Behúnf835bed2018-04-24 17:21:31 +0200149 if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) {
150 printf("Cannot find Armada 3720 watchdog!\n");
151 } else {
152 printf("Enabling Armada 3720 watchdog (3 minutes timeout).\n");
153 wdt_start(watchdog_dev, 180000, 0);
154 }
155#endif
156
157 return 0;
158}
159
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100160static int mox_do_spi(u8 *in, u8 *out, size_t size)
Marek Behúnf835bed2018-04-24 17:21:31 +0200161{
162 struct spi_slave *slave;
163 struct udevice *dev;
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100164 int ret;
Marek Behúnf835bed2018-04-24 17:21:31 +0200165
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100166 ret = spi_get_bus_and_cs(0, 1, 1000000, SPI_CPHA | SPI_CPOL,
167 "spi_generic_drv", "moxtet@1", &dev,
168 &slave);
Marek Behúnf835bed2018-04-24 17:21:31 +0200169 if (ret)
170 goto fail;
171
172 ret = spi_claim_bus(slave);
173 if (ret)
174 goto fail_free;
175
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100176 ret = spi_xfer(slave, size * 8, out, in, SPI_XFER_ONCE);
177
178 spi_release_bus(slave);
179fail_free:
180 spi_free_slave(slave);
181fail:
182 return ret;
183}
184
185static int mox_get_topology(const u8 **ptopology, int *psize, int *pis_sd)
186{
187 static int is_sd;
188 static u8 topology[MAX_MOX_MODULES - 1];
189 static int size;
190 u8 din[MAX_MOX_MODULES], dout[MAX_MOX_MODULES];
191 int ret, i;
192
193 if (size) {
194 if (ptopology)
195 *ptopology = topology;
196 if (psize)
197 *psize = size;
198 if (pis_sd)
199 *pis_sd = is_sd;
200 return 0;
201 }
Marek Behúnf835bed2018-04-24 17:21:31 +0200202
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100203 memset(din, 0, MAX_MOX_MODULES);
204 memset(dout, 0, MAX_MOX_MODULES);
205
206 ret = mox_do_spi(din, dout, MAX_MOX_MODULES);
Marek Behúnf835bed2018-04-24 17:21:31 +0200207 if (ret)
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100208 return ret;
Marek Behúnf835bed2018-04-24 17:21:31 +0200209
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100210 if (din[0] == 0x10)
211 is_sd = 1;
212 else if (din[0] == 0x00)
213 is_sd = 0;
214 else
215 return -ENODEV;
Marek Behúnf835bed2018-04-24 17:21:31 +0200216
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100217 for (i = 1; i < MAX_MOX_MODULES && din[i] != 0xff; ++i)
218 topology[i - 1] = din[i] & 0xf;
219 size = i - 1;
220
221 if (ptopology)
222 *ptopology = topology;
223 if (psize)
224 *psize = size;
225 if (pis_sd)
226 *pis_sd = is_sd;
227
228 return 0;
229}
230
Marek Behúna261d132018-12-17 16:10:02 +0100231int comphy_update_map(struct comphy_map *serdes_map, int count)
232{
233 int ret, i, size, sfpindex = -1, swindex = -1;
234 const u8 *topology;
235
236 ret = mox_get_topology(&topology, &size, NULL);
237 if (ret)
238 return ret;
239
240 for (i = 0; i < size; ++i) {
241 if (topology[i] == MOX_MODULE_SFP && sfpindex == -1)
242 sfpindex = i;
243 else if ((topology[i] == MOX_MODULE_TOPAZ ||
244 topology[i] == MOX_MODULE_PERIDOT) &&
245 swindex == -1)
246 swindex = i;
247 }
248
249 if (sfpindex >= 0 && swindex >= 0) {
250 if (sfpindex < swindex)
251 serdes_map[0].speed = PHY_SPEED_1_25G;
252 else
253 serdes_map[0].speed = PHY_SPEED_3_125G;
254 } else if (sfpindex >= 0) {
255 serdes_map[0].speed = PHY_SPEED_1_25G;
256 } else if (swindex >= 0) {
257 serdes_map[0].speed = PHY_SPEED_3_125G;
258 }
259
260 return 0;
261}
262
Marek Behún35b35132018-12-17 16:10:03 +0100263#define SW_SMI_CMD_R(d, r) (0x9800 | (((d) & 0x1f) << 5) | ((r) & 0x1f))
264#define SW_SMI_CMD_W(d, r) (0x9400 | (((d) & 0x1f) << 5) | ((r) & 0x1f))
265
266static int sw_multi_read(struct mii_dev *bus, int sw, int dev, int reg)
267{
268 bus->write(bus, sw, 0, 0, SW_SMI_CMD_R(dev, reg));
269 mdelay(5);
270 return bus->read(bus, sw, 0, 1);
271}
272
273static void sw_multi_write(struct mii_dev *bus, int sw, int dev, int reg,
274 u16 val)
275{
276 bus->write(bus, sw, 0, 1, val);
277 bus->write(bus, sw, 0, 0, SW_SMI_CMD_W(dev, reg));
278 mdelay(5);
279}
280
281static int sw_scratch_read(struct mii_dev *bus, int sw, int reg)
282{
283 sw_multi_write(bus, sw, 0x1c, 0x1a, (reg & 0x7f) << 8);
284 return sw_multi_read(bus, sw, 0x1c, 0x1a) & 0xff;
285}
286
287static void sw_led_write(struct mii_dev *bus, int sw, int port, int reg,
288 u16 val)
289{
290 sw_multi_write(bus, sw, port, 0x16, 0x8000 | ((reg & 7) << 12)
291 | (val & 0x7ff));
292}
293
294static void sw_blink_leds(struct mii_dev *bus, int peridot, int topaz)
295{
296 int i, p;
297 struct {
298 int port;
299 u16 val;
300 int wait;
301 } regs[] = {
302 { 2, 0xef, 1 }, { 2, 0xfe, 1 }, { 2, 0x33, 0 },
303 { 4, 0xef, 1 }, { 4, 0xfe, 1 }, { 4, 0x33, 0 },
304 { 3, 0xfe, 1 }, { 3, 0xef, 1 }, { 3, 0x33, 0 },
305 { 1, 0xfe, 1 }, { 1, 0xef, 1 }, { 1, 0x33, 0 }
306 };
307
308 for (i = 0; i < 12; ++i) {
309 for (p = 0; p < peridot; ++p) {
310 sw_led_write(bus, 0x10 + p, regs[i].port, 0,
311 regs[i].val);
312 sw_led_write(bus, 0x10 + p, regs[i].port + 4, 0,
313 regs[i].val);
314 }
315 if (topaz) {
316 sw_led_write(bus, 0x2, 0x10 + regs[i].port, 0,
317 regs[i].val);
318 }
319
320 if (regs[i].wait)
321 mdelay(75);
322 }
323}
324
325static void check_switch_address(struct mii_dev *bus, int addr)
326{
327 if (sw_scratch_read(bus, addr, 0x70) >> 3 != addr)
328 printf("Check of switch MDIO address failed for 0x%02x\n",
329 addr);
330}
331
332static int sfp, pci, topaz, peridot, usb, passpci;
333static int sfp_pos, peridot_pos[3];
334static int module_count;
335
336static int configure_peridots(struct gpio_desc *reset_gpio)
337{
338 int i, ret;
339 u8 dout[MAX_MOX_MODULES];
340
341 memset(dout, 0, MAX_MOX_MODULES);
342
343 /* set addresses of Peridot modules */
344 for (i = 0; i < peridot; ++i)
345 dout[module_count - peridot_pos[i]] = (~i) & 3;
346
347 /*
348 * if there is a SFP module connected to the last Peridot module, set
349 * the P10_SMODE to 1 for the Peridot module
350 */
351 if (sfp)
352 dout[module_count - peridot_pos[i - 1]] |= 1 << 3;
353
354 dm_gpio_set_value(reset_gpio, 1);
355 mdelay(10);
356
357 ret = mox_do_spi(NULL, dout, module_count + 1);
358
359 mdelay(10);
360 dm_gpio_set_value(reset_gpio, 0);
361
362 mdelay(50);
363
364 return ret;
365}
366
367static int get_reset_gpio(struct gpio_desc *reset_gpio)
368{
369 int node;
370
371 node = fdt_node_offset_by_compatible(gd->fdt_blob, 0, "cznic,moxtet");
372 if (node < 0) {
373 printf("Cannot find Moxtet bus device node!\n");
374 return -1;
375 }
376
377 gpio_request_by_name_nodev(offset_to_ofnode(node), "reset-gpios", 0,
378 reset_gpio, GPIOD_IS_OUT);
379
380 if (!dm_gpio_is_valid(reset_gpio)) {
381 printf("Cannot find reset GPIO for Moxtet bus!\n");
382 return -1;
383 }
384
Marek Behún35572c92018-12-17 16:10:08 +0100385 return 0;
386}
387
388int misc_init_r(void)
389{
390 int ret;
391 u8 mac1[6], mac2[6];
392
393 ret = mbox_sp_get_board_info(NULL, mac1, mac2, NULL, NULL);
394 if (ret < 0) {
395 printf("Cannot read data from OTP!\n");
396 return 0;
397 }
398
399 if (is_valid_ethaddr(mac1) && !env_get("ethaddr"))
400 eth_env_set_enetaddr("ethaddr", mac1);
401
402 if (is_valid_ethaddr(mac2) && !env_get("eth1addr"))
403 eth_env_set_enetaddr("eth1addr", mac2);
404
Marek Behún35b35132018-12-17 16:10:03 +0100405 return 0;
406}
407
Marek Behún35572c92018-12-17 16:10:08 +0100408static void mox_print_info(void)
409{
410 int ret, board_version, ram_size;
411 u64 serial_number;
412 const char *pub_key;
413
414 ret = mbox_sp_get_board_info(&serial_number, NULL, NULL, &board_version,
415 &ram_size);
416 if (ret < 0)
417 return;
418
419 printf("Turris Mox:\n");
420 printf(" Board version: %i\n", board_version);
421 printf(" RAM size: %i MiB\n", ram_size);
422 printf(" Serial Number: %016llX\n", serial_number);
423
424 pub_key = mox_sp_get_ecdsa_public_key();
425 if (pub_key)
426 printf(" ECDSA Public Key: %s\n", pub_key);
427 else
428 printf("Cannot read ECDSA Public Key\n");
429}
430
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100431int last_stage_init(void)
432{
433 int ret, i;
434 const u8 *topology;
Marek Behún35b35132018-12-17 16:10:03 +0100435 int is_sd;
436 struct mii_dev *bus;
437 struct gpio_desc reset_gpio = {};
Marek Behúnf835bed2018-04-24 17:21:31 +0200438
Marek Behún35572c92018-12-17 16:10:08 +0100439 mox_print_info();
440
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100441 ret = mox_get_topology(&topology, &module_count, &is_sd);
442 if (ret) {
443 printf("Cannot read module topology!\n");
444 return 0;
445 }
446
Marek Behún35572c92018-12-17 16:10:08 +0100447 printf(" SD/eMMC version: %s\n", is_sd ? "SD" : "eMMC");
448
449 if (module_count)
450 printf("Module Topology:\n");
451
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100452 for (i = 0; i < module_count; ++i) {
453 switch (topology[i]) {
454 case MOX_MODULE_SFP:
455 printf("% 4i: SFP Module\n", i + 1);
Marek Behúnf835bed2018-04-24 17:21:31 +0200456 break;
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100457 case MOX_MODULE_PCI:
458 printf("% 4i: Mini-PCIe Module\n", i + 1);
Marek Behúnf835bed2018-04-24 17:21:31 +0200459 break;
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100460 case MOX_MODULE_TOPAZ:
461 printf("% 4i: Topaz Switch Module (4-port)\n", i + 1);
462 break;
463 case MOX_MODULE_PERIDOT:
464 printf("% 4i: Peridot Switch Module (8-port)\n", i + 1);
465 break;
466 case MOX_MODULE_USB3:
467 printf("% 4i: USB 3.0 Module (4 ports)\n", i + 1);
468 break;
469 case MOX_MODULE_PASSPCI:
470 printf("% 4i: Passthrough Mini-PCIe Module\n", i + 1);
Marek Behúnf835bed2018-04-24 17:21:31 +0200471 break;
472 default:
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100473 printf("% 4i: unknown (ID %i)\n", i + 1, topology[i]);
Marek Behúnf835bed2018-04-24 17:21:31 +0200474 }
475 }
Marek Behúnf835bed2018-04-24 17:21:31 +0200476
Marek Behún35b35132018-12-17 16:10:03 +0100477 /* now check if modules are connected in supported mode */
478
479 for (i = 0; i < module_count; ++i) {
480 switch (topology[i]) {
481 case MOX_MODULE_SFP:
482 if (sfp) {
483 printf("Error: Only one SFP module is supported!\n");
484 } else if (topaz) {
485 printf("Error: SFP module cannot be connected after Topaz Switch module!\n");
486 } else {
487 sfp_pos = i;
488 ++sfp;
489 }
490 break;
491 case MOX_MODULE_PCI:
492 if (pci) {
493 printf("Error: Only one Mini-PCIe module is supported!\n");
494 } else if (usb) {
495 printf("Error: Mini-PCIe module cannot come after USB 3.0 module!\n");
496 } else if (i && (i != 1 || !passpci)) {
497 printf("Error: Mini-PCIe module should be the first connected module or come right after Passthrough Mini-PCIe module!\n");
498 } else {
499 ++pci;
500 }
501 break;
502 case MOX_MODULE_TOPAZ:
503 if (topaz) {
504 printf("Error: Only one Topaz module is supported!\n");
505 } else if (peridot >= 3) {
506 printf("Error: At most two Peridot modules can come before Topaz module!\n");
507 } else {
508 ++topaz;
509 }
510 break;
511 case MOX_MODULE_PERIDOT:
512 if (sfp || topaz) {
513 printf("Error: Peridot module must come before SFP or Topaz module!\n");
514 } else if (peridot >= 3) {
515 printf("Error: At most three Peridot modules are supported!\n");
516 } else {
517 peridot_pos[peridot] = i;
518 ++peridot;
519 }
520 break;
521 case MOX_MODULE_USB3:
522 if (pci) {
523 printf("Error: USB 3.0 module cannot come after Mini-PCIe module!\n");
524 } else if (usb) {
525 printf("Error: Only one USB 3.0 module is supported!\n");
526 } else if (i && (i != 1 || !passpci)) {
527 printf("Error: USB 3.0 module should be the first connected module or come right after Passthrough Mini-PCIe module!\n");
528 } else {
529 ++usb;
530 }
531 break;
532 case MOX_MODULE_PASSPCI:
533 if (passpci) {
534 printf("Error: Only one Passthrough Mini-PCIe module is supported!\n");
535 } else if (i != 0) {
536 printf("Error: Passthrough Mini-PCIe module should be the first connected module!\n");
537 } else {
538 ++passpci;
539 }
540 }
541 }
542
543 /* now configure modules */
544
545 if (get_reset_gpio(&reset_gpio) < 0)
546 return 0;
547
548 if (peridot > 0) {
549 if (configure_peridots(&reset_gpio) < 0) {
550 printf("Cannot configure Peridot modules!\n");
551 peridot = 0;
552 }
553 } else {
554 dm_gpio_set_value(&reset_gpio, 1);
555 mdelay(50);
556 dm_gpio_set_value(&reset_gpio, 0);
557 mdelay(50);
558 }
559
560 if (peridot || topaz) {
561 /*
562 * now check if the addresses are set by reading Scratch & Misc
563 * register 0x70 of Peridot (and potentially Topaz) modules
564 */
565
566 bus = miiphy_get_dev_by_name("neta@30000");
567 if (!bus) {
568 printf("Cannot get MDIO bus device!\n");
569 } else {
570 for (i = 0; i < peridot; ++i)
571 check_switch_address(bus, 0x10 + i);
572
573 if (topaz)
574 check_switch_address(bus, 0x2);
575
576 sw_blink_leds(bus, peridot, topaz);
577 }
578 }
579
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100580 printf("\n");
Marek Behúnf835bed2018-04-24 17:21:31 +0200581
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100582 return 0;
Marek Behúnf835bed2018-04-24 17:21:31 +0200583}