blob: c4622a49c2e47759d6aa0ff22a15793ba99012eb [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ún9602a8c2018-08-21 12:22:09 +02007#include <asm/io.h>
Marek Behúnf835bed2018-04-24 17:21:31 +02008#include <dm.h>
9#include <clk.h>
10#include <spi.h>
11#include <linux/string.h>
Marek Behún9602a8c2018-08-21 12:22:09 +020012#include <linux/libfdt.h>
13#include <fdt_support.h>
Marek Behúnf835bed2018-04-24 17:21:31 +020014
Marek Behúnceb05932018-08-17 12:58:53 +020015#ifdef CONFIG_WDT_ARMADA_37XX
Marek Behúnf835bed2018-04-24 17:21:31 +020016#include <wdt.h>
17#endif
18
Marek Behún9602a8c2018-08-21 12:22:09 +020019#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
Marek Behúnf835bed2018-04-24 17:21:31 +020036DECLARE_GLOBAL_DATA_PTR;
37
Marek Behún9602a8c2018-08-21 12:22:09 +020038#if defined(CONFIG_OF_BOARD_FIXUP)
39int 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
Marek Behúnceb05932018-08-17 12:58:53 +0200100#ifdef CONFIG_WDT_ARMADA_37XX
Marek Behúnf835bed2018-04-24 17:21:31 +0200101static struct udevice *watchdog_dev;
102
103void 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
121int board_init(void)
122{
123 /* address of boot parameters */
124 gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
125
Marek Behúnceb05932018-08-17 12:58:53 +0200126#ifdef CONFIG_WDT_ARMADA_37XX
Marek Behúnf835bed2018-04-24 17:21:31 +0200127 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
138int 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
201fail_release:
202 spi_release_bus(slave);
203fail_free:
204 spi_free_slave(slave);
205fail:
206 if (ret)
207 printf("Cannot read module topology!\n");
208 return ret;
209}