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 }
210