Merge git://git.denx.de/u-boot-imx
[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/io.h>
8 #include <dm.h>
9 #include <clk.h>
10 #include <spi.h>
11 #include <linux/string.h>
12 #include <linux/libfdt.h>
13 #include <fdt_support.h>
14
15 #ifdef CONFIG_WDT_ARMADA_37XX
16 #include <wdt.h>
17 #endif
18
19 #define MAX_MOX_MODULES         10
20
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
27
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
33
34 #define PCIE_PATH       "/soc/pcie@d0070000"
35
36 DECLARE_GLOBAL_DATA_PTR;
37
38 #if defined(CONFIG_OF_BOARD_FIXUP)
39 int board_fix_fdt(void *blob)
40 {
41         u8 topology[MAX_MOX_MODULES];
42         int i, size, node;
43         bool enable;
44
45         /*
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
49          */
50
51         writel(0x563fa, ARMADA_37XX_NB_GPIO_SEL);
52         writel(0x10df, ARMADA_37XX_SPI_CFG);
53         writel(0x2005b, ARMADA_37XX_SPI_CTRL);
54
55         while (!(readl(ARMADA_37XX_SPI_CTRL) & 0x2))
56                 udelay(1);
57
58         for (i = 0; i < MAX_MOX_MODULES; ++i) {
59                 writel(0x0, ARMADA_37XX_SPI_DOUT);
60
61                 while (!(readl(ARMADA_37XX_SPI_CTRL) & 0x2))
62                         udelay(1);
63
64                 topology[i] = readl(ARMADA_37XX_SPI_DIN) & 0xff;
65                 if (topology[i] == 0xff)
66                         break;
67
68                 topology[i] &= 0xf;
69         }
70
71         size = i;
72
73         writel(0x5b, ARMADA_37XX_SPI_CTRL);
74
75         if (size > 1 && (topology[1] == MOX_MODULE_PCI ||
76                          topology[1] == MOX_MODULE_USB3 ||
77                          topology[1] == MOX_MODULE_PASSPCI))
78                 enable = true;
79         else
80                 enable = false;
81
82         node = fdt_path_offset(blob, PCIE_PATH);
83
84         if (node < 0) {
85                 printf("Cannot find PCIe node in U-Boot's device tree!\n");
86                 return 0;
87         }
88
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");
93                 return 0;
94         }
95
96         return 0;
97 }
98 #endif
99
100 #ifdef CONFIG_WDT_ARMADA_37XX
101 static struct udevice *watchdog_dev;
102
103 void watchdog_reset(void)
104 {
105         static ulong next_reset;
106         ulong now;
107
108         if (!watchdog_dev)
109                 return;
110
111         now = timer_get_us();
112
113         /* Do not reset the watchdog too often */
114         if (now > next_reset) {
115                 wdt_reset(watchdog_dev);
116                 next_reset = now + 100000;
117         }
118 }
119 #endif
120
121 int board_init(void)
122 {
123         /* address of boot parameters */
124         gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
125
126 #ifdef CONFIG_WDT_ARMADA_37XX
127         if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) {
128                 printf("Cannot find Armada 3720 watchdog!\n");
129         } else {
130                 printf("Enabling Armada 3720 watchdog (3 minutes timeout).\n");
131                 wdt_start(watchdog_dev, 180000, 0);
132         }
133 #endif
134
135         return 0;
136 }
137
138 int last_stage_init(void)
139 {
140         struct spi_slave *slave;
141         struct udevice *dev;
142         u8 din[10], dout[10];
143         int ret, i;
144         size_t len = 0;
145         char module_topology[128];
146
147         ret = spi_get_bus_and_cs(0, 1, 20000000, SPI_CPHA, "spi_generic_drv",
148                                  "mox-modules@1", &dev, &slave);
149         if (ret)
150                 goto fail;
151
152         ret = spi_claim_bus(slave);
153         if (ret)
154                 goto fail_free;
155
156         memset(din, 0, 10);
157         memset(dout, 0, 10);
158
159         ret = spi_xfer(slave, 80, dout, din, SPI_XFER_ONCE);
160         if (ret)
161                 goto fail_release;
162
163         if (din[0] != 0x00 && din[0] != 0xff)
164                 goto fail_release;
165
166         printf("Module Topology:\n");
167         for (i = 1; i < 10 && din[i] != 0xff; ++i) {
168                 u8 mid = din[i] & 0xf;
169                 size_t mlen;
170                 const char *mname = "";
171
172                 switch (mid) {
173                 case 0x1:
174                         mname = "sfp-";
175                         printf("% 4i: SFP Module\n", i);
176                         break;
177                 case 0x2:
178                         mname = "pci-";
179                         printf("% 4i: Mini-PCIe Module\n", i);
180                         break;
181                 case 0x3:
182                         mname = "topaz-";
183                         printf("% 4i: Topaz Switch Module\n", i);
184                         break;
185                 default:
186                         printf("% 4i: unknown (ID %i)\n", i, mid);
187                 }
188
189                 mlen = strlen(mname);
190                 if (len + mlen < sizeof(module_topology)) {
191                         strcpy(module_topology + len, mname);
192                         len += mlen;
193                 }
194         }
195         printf("\n");
196
197         module_topology[len > 0 ? len - 1 : 0] = '\0';
198
199         env_set("module_topology", module_topology);
200
201 fail_release:
202         spi_release_bus(slave);
203 fail_free:
204         spi_free_slave(slave);
205 fail:
206         if (ret)
207                 printf("Cannot read module topology!\n");
208         return ret;
209 }