1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2018 Marek Behun <marek.behun@nic.cz>
11 #include <linux/string.h>
12 #include <linux/libfdt.h>
13 #include <fdt_support.h>
15 #ifdef CONFIG_WDT_ARMADA_37XX
19 #define MAX_MOX_MODULES 10
21 #define MOX_MODULE_SFP 0x1
22 #define MOX_MODULE_PCI 0x2
23 #define MOX_MODULE_TOPAZ 0x3
24 #define MOX_MODULE_PERIDOT 0x4
25 #define MOX_MODULE_USB3 0x5
26 #define MOX_MODULE_PASSPCI 0x6
28 #define ARMADA_37XX_NB_GPIO_SEL 0xd0013830
29 #define ARMADA_37XX_SPI_CTRL 0xd0010600
30 #define ARMADA_37XX_SPI_CFG 0xd0010604
31 #define ARMADA_37XX_SPI_DOUT 0xd0010608
32 #define ARMADA_37XX_SPI_DIN 0xd001060c
34 #define PCIE_PATH "/soc/pcie@d0070000"
36 DECLARE_GLOBAL_DATA_PTR;
38 #if defined(CONFIG_OF_BOARD_FIXUP)
39 int board_fix_fdt(void *blob)
41 u8 topology[MAX_MOX_MODULES];
46 * SPI driver is not loaded in driver model yet, but we have to find out
47 * if pcie should be enabled in U-Boot's device tree. Therefore we have
48 * to read SPI by reading/writing SPI registers directly
51 writel(0x563fa, ARMADA_37XX_NB_GPIO_SEL);
52 writel(0x10df, ARMADA_37XX_SPI_CFG);
53 writel(0x2005b, ARMADA_37XX_SPI_CTRL);
55 while (!(readl(ARMADA_37XX_SPI_CTRL) & 0x2))
58 for (i = 0; i < MAX_MOX_MODULES; ++i) {
59 writel(0x0, ARMADA_37XX_SPI_DOUT);
61 while (!(readl(ARMADA_37XX_SPI_CTRL) & 0x2))
64 topology[i] = readl(ARMADA_37XX_SPI_DIN) & 0xff;
65 if (topology[i] == 0xff)
73 writel(0x5b, ARMADA_37XX_SPI_CTRL);
75 if (size > 1 && (topology[1] == MOX_MODULE_PCI ||
76 topology[1] == MOX_MODULE_USB3 ||
77 topology[1] == MOX_MODULE_PASSPCI))
82 node = fdt_path_offset(blob, PCIE_PATH);
85 printf("Cannot find PCIe node in U-Boot's device tree!\n");
89 if (fdt_setprop_string(blob, node, "status",
90 enable ? "okay" : "disabled") < 0) {
91 printf("Cannot %s PCIe in U-Boot's device tree!\n",
92 enable ? "enable" : "disable");
100 #ifdef CONFIG_WDT_ARMADA_37XX
101 static struct udevice *watchdog_dev;
103 void watchdog_reset(void)
105 static ulong next_reset;
111 now = timer_get_us();
113 /* Do not reset the watchdog too often */
114 if (now > next_reset) {
115 wdt_reset(watchdog_dev);
116 next_reset = now + 100000;
123 /* address of boot parameters */
124 gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
126 #ifdef CONFIG_WDT_ARMADA_37XX
127 if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) {
128 printf("Cannot find Armada 3720 watchdog!\n");
130 printf("Enabling Armada 3720 watchdog (3 minutes timeout).\n");
131 wdt_start(watchdog_dev, 180000, 0);
138 static int mox_do_spi(u8 *in, u8 *out, size_t size)
140 struct spi_slave *slave;
144 ret = spi_get_bus_and_cs(0, 1, 1000000, SPI_CPHA | SPI_CPOL,
145 "spi_generic_drv", "moxtet@1", &dev,
150 ret = spi_claim_bus(slave);
154 ret = spi_xfer(slave, size * 8, out, in, SPI_XFER_ONCE);
156 spi_release_bus(slave);
158 spi_free_slave(slave);
163 static int mox_get_topology(const u8 **ptopology, int *psize, int *pis_sd)
166 static u8 topology[MAX_MOX_MODULES - 1];
168 u8 din[MAX_MOX_MODULES], dout[MAX_MOX_MODULES];
173 *ptopology = topology;
181 memset(din, 0, MAX_MOX_MODULES);
182 memset(dout, 0, MAX_MOX_MODULES);
184 ret = mox_do_spi(din, dout, MAX_MOX_MODULES);
190 else if (din[0] == 0x00)
195 for (i = 1; i < MAX_MOX_MODULES && din[i] != 0xff; ++i)
196 topology[i - 1] = din[i] & 0xf;
200 *ptopology = topology;
209 int last_stage_init(void)
213 int module_count, is_sd;
215 ret = mox_get_topology(&topology, &module_count, &is_sd);
217 printf("Cannot read module topology!\n");
221 printf("Found Turris Mox %s version\n", is_sd ? "SD" : "eMMC");
222 printf("Module Topology:\n");
223 for (i = 0; i < module_count; ++i) {
224 switch (topology[i]) {
226 printf("% 4i: SFP Module\n", i + 1);
229 printf("% 4i: Mini-PCIe Module\n", i + 1);
231 case MOX_MODULE_TOPAZ:
232 printf("% 4i: Topaz Switch Module (4-port)\n", i + 1);
234 case MOX_MODULE_PERIDOT:
235 printf("% 4i: Peridot Switch Module (8-port)\n", i + 1);
237 case MOX_MODULE_USB3:
238 printf("% 4i: USB 3.0 Module (4 ports)\n", i + 1);
240 case MOX_MODULE_PASSPCI:
241 printf("% 4i: Passthrough Mini-PCIe Module\n", i + 1);
244 printf("% 4i: unknown (ID %i)\n", i + 1, topology[i]);