blob: 5bb53b126025e220d8d1fc5b64510d6971601d59 [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ún1055ce12020-04-08 12:02:07 +02007#include <asm/arch/soc.h>
Marek Behún9602a8c2018-08-21 12:22:09 +02008#include <asm/io.h>
Marek Behún28e935f2020-04-08 12:02:08 +02009#include <asm/gpio.h>
Marek Behúnf835bed2018-04-24 17:21:31 +020010#include <clk.h>
Marek Behún28e935f2020-04-08 12:02:08 +020011#include <dm.h>
Simon Glass5e6201b2019-08-01 09:46:51 -060012#include <env.h>
Marek Behún9602a8c2018-08-21 12:22:09 +020013#include <fdt_support.h>
Marek Behún28e935f2020-04-08 12:02:08 +020014#include <init.h>
15#include <linux/libfdt.h>
16#include <linux/string.h>
17#include <miiphy.h>
18#include <mvebu/comphy.h>
19#include <spi.h>
Marek Behúnf835bed2018-04-24 17:21:31 +020020
Marek Behún35572c92018-12-17 16:10:08 +010021#include "mox_sp.h"
22
Marek Behún9602a8c2018-08-21 12:22:09 +020023#define MAX_MOX_MODULES 10
24
25#define MOX_MODULE_SFP 0x1
26#define MOX_MODULE_PCI 0x2
27#define MOX_MODULE_TOPAZ 0x3
28#define MOX_MODULE_PERIDOT 0x4
29#define MOX_MODULE_USB3 0x5
30#define MOX_MODULE_PASSPCI 0x6
31
Marek Behún1055ce12020-04-08 12:02:07 +020032#define ARMADA_37XX_NB_GPIO_SEL (MVEBU_REGISTER(0x13830))
33#define ARMADA_37XX_SPI_CTRL (MVEBU_REGISTER(0x10600))
34#define ARMADA_37XX_SPI_CFG (MVEBU_REGISTER(0x10604))
35#define ARMADA_37XX_SPI_DOUT (MVEBU_REGISTER(0x10608))
36#define ARMADA_37XX_SPI_DIN (MVEBU_REGISTER(0x1060c))
Marek Behún9602a8c2018-08-21 12:22:09 +020037
Marek Behún4529fce2020-04-08 12:02:05 +020038#define ETH1_PATH "/soc/internal-regs@d0000000/ethernet@40000"
39#define MDIO_PATH "/soc/internal-regs@d0000000/mdio@32004"
40#define SFP_GPIO_PATH "/soc/internal-regs@d0000000/spi@10600/moxtet@1/gpio@0"
Marek Behún9602a8c2018-08-21 12:22:09 +020041#define PCIE_PATH "/soc/pcie@d0070000"
Marek Behún4529fce2020-04-08 12:02:05 +020042#define SFP_PATH "/sfp"
Marek Behún9602a8c2018-08-21 12:22:09 +020043
Marek Behúnf835bed2018-04-24 17:21:31 +020044DECLARE_GLOBAL_DATA_PTR;
45
Marek Behún22a0ce32018-12-17 16:10:09 +010046int dram_init(void)
47{
48 gd->ram_base = 0;
49 gd->ram_size = (phys_size_t)get_ram_size(0, 0x40000000);
50
51 return 0;
52}
53
54int dram_init_banksize(void)
55{
56 gd->bd->bi_dram[0].start = (phys_addr_t)0;
57 gd->bd->bi_dram[0].size = gd->ram_size;
58
59 return 0;
60}
61
Marek Behún9602a8c2018-08-21 12:22:09 +020062#if defined(CONFIG_OF_BOARD_FIXUP)
63int board_fix_fdt(void *blob)
64{
65 u8 topology[MAX_MOX_MODULES];
66 int i, size, node;
67 bool enable;
68
69 /*
70 * SPI driver is not loaded in driver model yet, but we have to find out
71 * if pcie should be enabled in U-Boot's device tree. Therefore we have
72 * to read SPI by reading/writing SPI registers directly
73 */
74
Marek Behún9602a8c2018-08-21 12:22:09 +020075 writel(0x10df, ARMADA_37XX_SPI_CFG);
Marek Behúna4e697f2020-04-08 12:02:03 +020076 /* put pin from GPIO to SPI mode */
77 clrbits_le32(ARMADA_37XX_NB_GPIO_SEL, BIT(12));
78 /* enable SPI CS1 */
79 setbits_le32(ARMADA_37XX_SPI_CTRL, BIT(17));
Marek Behún9602a8c2018-08-21 12:22:09 +020080
81 while (!(readl(ARMADA_37XX_SPI_CTRL) & 0x2))
82 udelay(1);
83
84 for (i = 0; i < MAX_MOX_MODULES; ++i) {
85 writel(0x0, ARMADA_37XX_SPI_DOUT);
86
87 while (!(readl(ARMADA_37XX_SPI_CTRL) & 0x2))
88 udelay(1);
89
90 topology[i] = readl(ARMADA_37XX_SPI_DIN) & 0xff;
91 if (topology[i] == 0xff)
92 break;
93
94 topology[i] &= 0xf;
95 }
96
97 size = i;
98
Marek Behúna4e697f2020-04-08 12:02:03 +020099 /* disable SPI CS1 */
100 clrbits_le32(ARMADA_37XX_SPI_CTRL, BIT(17));
Marek Behún9602a8c2018-08-21 12:22:09 +0200101
102 if (size > 1 && (topology[1] == MOX_MODULE_PCI ||
103 topology[1] == MOX_MODULE_USB3 ||
104 topology[1] == MOX_MODULE_PASSPCI))
105 enable = true;
106 else
107 enable = false;
108
109 node = fdt_path_offset(blob, PCIE_PATH);
110
111 if (node < 0) {
112 printf("Cannot find PCIe node in U-Boot's device tree!\n");
113 return 0;
114 }
115
116 if (fdt_setprop_string(blob, node, "status",
117 enable ? "okay" : "disabled") < 0) {
118 printf("Cannot %s PCIe in U-Boot's device tree!\n",
119 enable ? "enable" : "disable");
120 return 0;
121 }
122
123 return 0;
124}
125#endif
126
Marek Behúnf835bed2018-04-24 17:21:31 +0200127int board_init(void)
128{
129 /* address of boot parameters */
130 gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
131
Marek Behúnf835bed2018-04-24 17:21:31 +0200132 return 0;
133}
134
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100135static int mox_do_spi(u8 *in, u8 *out, size_t size)
Marek Behúnf835bed2018-04-24 17:21:31 +0200136{
137 struct spi_slave *slave;
138 struct udevice *dev;
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100139 int ret;
Marek Behúnf835bed2018-04-24 17:21:31 +0200140
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100141 ret = spi_get_bus_and_cs(0, 1, 1000000, SPI_CPHA | SPI_CPOL,
142 "spi_generic_drv", "moxtet@1", &dev,
143 &slave);
Marek Behúnf835bed2018-04-24 17:21:31 +0200144 if (ret)
145 goto fail;
146
147 ret = spi_claim_bus(slave);
148 if (ret)
149 goto fail_free;
150
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100151 ret = spi_xfer(slave, size * 8, out, in, SPI_XFER_ONCE);
152
153 spi_release_bus(slave);
154fail_free:
155 spi_free_slave(slave);
156fail:
157 return ret;
158}
159
160static int mox_get_topology(const u8 **ptopology, int *psize, int *pis_sd)
161{
162 static int is_sd;
163 static u8 topology[MAX_MOX_MODULES - 1];
164 static int size;
165 u8 din[MAX_MOX_MODULES], dout[MAX_MOX_MODULES];
166 int ret, i;
167
168 if (size) {
169 if (ptopology)
170 *ptopology = topology;
171 if (psize)
172 *psize = size;
173 if (pis_sd)
174 *pis_sd = is_sd;
175 return 0;
176 }
Marek Behúnf835bed2018-04-24 17:21:31 +0200177
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100178 memset(din, 0, MAX_MOX_MODULES);
179 memset(dout, 0, MAX_MOX_MODULES);
180
181 ret = mox_do_spi(din, dout, MAX_MOX_MODULES);
Marek Behúnf835bed2018-04-24 17:21:31 +0200182 if (ret)
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100183 return ret;
Marek Behúnf835bed2018-04-24 17:21:31 +0200184
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100185 if (din[0] == 0x10)
186 is_sd = 1;
187 else if (din[0] == 0x00)
188 is_sd = 0;
189 else
190 return -ENODEV;
Marek Behúnf835bed2018-04-24 17:21:31 +0200191
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100192 for (i = 1; i < MAX_MOX_MODULES && din[i] != 0xff; ++i)
193 topology[i - 1] = din[i] & 0xf;
194 size = i - 1;
195
196 if (ptopology)
197 *ptopology = topology;
198 if (psize)
199 *psize = size;
200 if (pis_sd)
201 *pis_sd = is_sd;
202
203 return 0;
204}
205
Marek Behúna261d132018-12-17 16:10:02 +0100206int comphy_update_map(struct comphy_map *serdes_map, int count)
207{
208 int ret, i, size, sfpindex = -1, swindex = -1;
209 const u8 *topology;
210
211 ret = mox_get_topology(&topology, &size, NULL);
212 if (ret)
213 return ret;
214
215 for (i = 0; i < size; ++i) {
216 if (topology[i] == MOX_MODULE_SFP && sfpindex == -1)
217 sfpindex = i;
218 else if ((topology[i] == MOX_MODULE_TOPAZ ||
219 topology[i] == MOX_MODULE_PERIDOT) &&
220 swindex == -1)
221 swindex = i;
222 }
223
224 if (sfpindex >= 0 && swindex >= 0) {
225 if (sfpindex < swindex)
226 serdes_map[0].speed = PHY_SPEED_1_25G;
227 else
228 serdes_map[0].speed = PHY_SPEED_3_125G;
229 } else if (sfpindex >= 0) {
230 serdes_map[0].speed = PHY_SPEED_1_25G;
231 } else if (swindex >= 0) {
232 serdes_map[0].speed = PHY_SPEED_3_125G;
233 }
234
235 return 0;
236}
237
Marek Behún35b35132018-12-17 16:10:03 +0100238#define SW_SMI_CMD_R(d, r) (0x9800 | (((d) & 0x1f) << 5) | ((r) & 0x1f))
239#define SW_SMI_CMD_W(d, r) (0x9400 | (((d) & 0x1f) << 5) | ((r) & 0x1f))
240
241static int sw_multi_read(struct mii_dev *bus, int sw, int dev, int reg)
242{
243 bus->write(bus, sw, 0, 0, SW_SMI_CMD_R(dev, reg));
244 mdelay(5);
245 return bus->read(bus, sw, 0, 1);
246}
247
248static void sw_multi_write(struct mii_dev *bus, int sw, int dev, int reg,
249 u16 val)
250{
251 bus->write(bus, sw, 0, 1, val);
252 bus->write(bus, sw, 0, 0, SW_SMI_CMD_W(dev, reg));
253 mdelay(5);
254}
255
256static int sw_scratch_read(struct mii_dev *bus, int sw, int reg)
257{
258 sw_multi_write(bus, sw, 0x1c, 0x1a, (reg & 0x7f) << 8);
259 return sw_multi_read(bus, sw, 0x1c, 0x1a) & 0xff;
260}
261
262static void sw_led_write(struct mii_dev *bus, int sw, int port, int reg,
263 u16 val)
264{
265 sw_multi_write(bus, sw, port, 0x16, 0x8000 | ((reg & 7) << 12)
266 | (val & 0x7ff));
267}
268
269static void sw_blink_leds(struct mii_dev *bus, int peridot, int topaz)
270{
271 int i, p;
272 struct {
273 int port;
274 u16 val;
275 int wait;
276 } regs[] = {
277 { 2, 0xef, 1 }, { 2, 0xfe, 1 }, { 2, 0x33, 0 },
278 { 4, 0xef, 1 }, { 4, 0xfe, 1 }, { 4, 0x33, 0 },
279 { 3, 0xfe, 1 }, { 3, 0xef, 1 }, { 3, 0x33, 0 },
280 { 1, 0xfe, 1 }, { 1, 0xef, 1 }, { 1, 0x33, 0 }
281 };
282
283 for (i = 0; i < 12; ++i) {
284 for (p = 0; p < peridot; ++p) {
285 sw_led_write(bus, 0x10 + p, regs[i].port, 0,
286 regs[i].val);
287 sw_led_write(bus, 0x10 + p, regs[i].port + 4, 0,
288 regs[i].val);
289 }
290 if (topaz) {
291 sw_led_write(bus, 0x2, 0x10 + regs[i].port, 0,
292 regs[i].val);
293 }
294
295 if (regs[i].wait)
296 mdelay(75);
297 }
298}
299
300static void check_switch_address(struct mii_dev *bus, int addr)
301{
302 if (sw_scratch_read(bus, addr, 0x70) >> 3 != addr)
303 printf("Check of switch MDIO address failed for 0x%02x\n",
304 addr);
305}
306
307static int sfp, pci, topaz, peridot, usb, passpci;
308static int sfp_pos, peridot_pos[3];
309static int module_count;
310
311static int configure_peridots(struct gpio_desc *reset_gpio)
312{
313 int i, ret;
314 u8 dout[MAX_MOX_MODULES];
315
316 memset(dout, 0, MAX_MOX_MODULES);
317
318 /* set addresses of Peridot modules */
319 for (i = 0; i < peridot; ++i)
320 dout[module_count - peridot_pos[i]] = (~i) & 3;
321
322 /*
323 * if there is a SFP module connected to the last Peridot module, set
324 * the P10_SMODE to 1 for the Peridot module
325 */
326 if (sfp)
327 dout[module_count - peridot_pos[i - 1]] |= 1 << 3;
328
329 dm_gpio_set_value(reset_gpio, 1);
330 mdelay(10);
331
332 ret = mox_do_spi(NULL, dout, module_count + 1);
333
334 mdelay(10);
335 dm_gpio_set_value(reset_gpio, 0);
336
337 mdelay(50);
338
339 return ret;
340}
341
342static int get_reset_gpio(struct gpio_desc *reset_gpio)
343{
344 int node;
345
346 node = fdt_node_offset_by_compatible(gd->fdt_blob, 0, "cznic,moxtet");
347 if (node < 0) {
348 printf("Cannot find Moxtet bus device node!\n");
349 return -1;
350 }
351
352 gpio_request_by_name_nodev(offset_to_ofnode(node), "reset-gpios", 0,
353 reset_gpio, GPIOD_IS_OUT);
354
355 if (!dm_gpio_is_valid(reset_gpio)) {
356 printf("Cannot find reset GPIO for Moxtet bus!\n");
357 return -1;
358 }
359
Marek Behún35572c92018-12-17 16:10:08 +0100360 return 0;
361}
362
363int misc_init_r(void)
364{
365 int ret;
366 u8 mac1[6], mac2[6];
367
368 ret = mbox_sp_get_board_info(NULL, mac1, mac2, NULL, NULL);
369 if (ret < 0) {
370 printf("Cannot read data from OTP!\n");
371 return 0;
372 }
373
374 if (is_valid_ethaddr(mac1) && !env_get("ethaddr"))
375 eth_env_set_enetaddr("ethaddr", mac1);
376
377 if (is_valid_ethaddr(mac2) && !env_get("eth1addr"))
378 eth_env_set_enetaddr("eth1addr", mac2);
379
Marek Behún35b35132018-12-17 16:10:03 +0100380 return 0;
381}
382
Marek Behún35572c92018-12-17 16:10:08 +0100383static void mox_print_info(void)
384{
385 int ret, board_version, ram_size;
386 u64 serial_number;
387 const char *pub_key;
388
389 ret = mbox_sp_get_board_info(&serial_number, NULL, NULL, &board_version,
390 &ram_size);
391 if (ret < 0)
392 return;
393
394 printf("Turris Mox:\n");
395 printf(" Board version: %i\n", board_version);
396 printf(" RAM size: %i MiB\n", ram_size);
397 printf(" Serial Number: %016llX\n", serial_number);
398
399 pub_key = mox_sp_get_ecdsa_public_key();
400 if (pub_key)
401 printf(" ECDSA Public Key: %s\n", pub_key);
402 else
403 printf("Cannot read ECDSA Public Key\n");
404}
405
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100406int last_stage_init(void)
407{
408 int ret, i;
409 const u8 *topology;
Marek Behún35b35132018-12-17 16:10:03 +0100410 int is_sd;
411 struct mii_dev *bus;
412 struct gpio_desc reset_gpio = {};
Marek Behúnf835bed2018-04-24 17:21:31 +0200413
Marek Behún35572c92018-12-17 16:10:08 +0100414 mox_print_info();
415
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100416 ret = mox_get_topology(&topology, &module_count, &is_sd);
417 if (ret) {
418 printf("Cannot read module topology!\n");
419 return 0;
420 }
421
Marek Behún35572c92018-12-17 16:10:08 +0100422 printf(" SD/eMMC version: %s\n", is_sd ? "SD" : "eMMC");
423
424 if (module_count)
425 printf("Module Topology:\n");
426
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100427 for (i = 0; i < module_count; ++i) {
428 switch (topology[i]) {
429 case MOX_MODULE_SFP:
430 printf("% 4i: SFP Module\n", i + 1);
Marek Behúnf835bed2018-04-24 17:21:31 +0200431 break;
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100432 case MOX_MODULE_PCI:
433 printf("% 4i: Mini-PCIe Module\n", i + 1);
Marek Behúnf835bed2018-04-24 17:21:31 +0200434 break;
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100435 case MOX_MODULE_TOPAZ:
436 printf("% 4i: Topaz Switch Module (4-port)\n", i + 1);
437 break;
438 case MOX_MODULE_PERIDOT:
439 printf("% 4i: Peridot Switch Module (8-port)\n", i + 1);
440 break;
441 case MOX_MODULE_USB3:
442 printf("% 4i: USB 3.0 Module (4 ports)\n", i + 1);
443 break;
444 case MOX_MODULE_PASSPCI:
445 printf("% 4i: Passthrough Mini-PCIe Module\n", i + 1);
Marek Behúnf835bed2018-04-24 17:21:31 +0200446 break;
447 default:
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100448 printf("% 4i: unknown (ID %i)\n", i + 1, topology[i]);
Marek Behúnf835bed2018-04-24 17:21:31 +0200449 }
450 }
Marek Behúnf835bed2018-04-24 17:21:31 +0200451
Marek Behún35b35132018-12-17 16:10:03 +0100452 /* now check if modules are connected in supported mode */
453
454 for (i = 0; i < module_count; ++i) {
455 switch (topology[i]) {
456 case MOX_MODULE_SFP:
457 if (sfp) {
458 printf("Error: Only one SFP module is supported!\n");
459 } else if (topaz) {
460 printf("Error: SFP module cannot be connected after Topaz Switch module!\n");
461 } else {
462 sfp_pos = i;
463 ++sfp;
464 }
465 break;
466 case MOX_MODULE_PCI:
Marek Behún4529fce2020-04-08 12:02:05 +0200467 if (pci)
Marek Behún35b35132018-12-17 16:10:03 +0100468 printf("Error: Only one Mini-PCIe module is supported!\n");
Marek Behún4529fce2020-04-08 12:02:05 +0200469 else if (usb)
Marek Behún35b35132018-12-17 16:10:03 +0100470 printf("Error: Mini-PCIe module cannot come after USB 3.0 module!\n");
Marek Behún4529fce2020-04-08 12:02:05 +0200471 else if (i && (i != 1 || !passpci))
Marek Behún35b35132018-12-17 16:10:03 +0100472 printf("Error: Mini-PCIe module should be the first connected module or come right after Passthrough Mini-PCIe module!\n");
Marek Behún4529fce2020-04-08 12:02:05 +0200473 else
Marek Behún35b35132018-12-17 16:10:03 +0100474 ++pci;
Marek Behún35b35132018-12-17 16:10:03 +0100475 break;
476 case MOX_MODULE_TOPAZ:
Marek Behún4529fce2020-04-08 12:02:05 +0200477 if (topaz)
Marek Behún35b35132018-12-17 16:10:03 +0100478 printf("Error: Only one Topaz module is supported!\n");
Marek Behún4529fce2020-04-08 12:02:05 +0200479 else if (peridot >= 3)
Marek Behún35b35132018-12-17 16:10:03 +0100480 printf("Error: At most two Peridot modules can come before Topaz module!\n");
Marek Behún4529fce2020-04-08 12:02:05 +0200481 else
Marek Behún35b35132018-12-17 16:10:03 +0100482 ++topaz;
Marek Behún35b35132018-12-17 16:10:03 +0100483 break;
484 case MOX_MODULE_PERIDOT:
485 if (sfp || topaz) {
486 printf("Error: Peridot module must come before SFP or Topaz module!\n");
487 } else if (peridot >= 3) {
488 printf("Error: At most three Peridot modules are supported!\n");
489 } else {
490 peridot_pos[peridot] = i;
491 ++peridot;
492 }
493 break;
494 case MOX_MODULE_USB3:
Marek Behún4529fce2020-04-08 12:02:05 +0200495 if (pci)
Marek Behún35b35132018-12-17 16:10:03 +0100496 printf("Error: USB 3.0 module cannot come after Mini-PCIe module!\n");
Marek Behún4529fce2020-04-08 12:02:05 +0200497 else if (usb)
Marek Behún35b35132018-12-17 16:10:03 +0100498 printf("Error: Only one USB 3.0 module is supported!\n");
Marek Behún4529fce2020-04-08 12:02:05 +0200499 else if (i && (i != 1 || !passpci))
Marek Behún35b35132018-12-17 16:10:03 +0100500 printf("Error: USB 3.0 module should be the first connected module or come right after Passthrough Mini-PCIe module!\n");
Marek Behún4529fce2020-04-08 12:02:05 +0200501 else
Marek Behún35b35132018-12-17 16:10:03 +0100502 ++usb;
Marek Behún35b35132018-12-17 16:10:03 +0100503 break;
504 case MOX_MODULE_PASSPCI:
Marek Behún4529fce2020-04-08 12:02:05 +0200505 if (passpci)
Marek Behún35b35132018-12-17 16:10:03 +0100506 printf("Error: Only one Passthrough Mini-PCIe module is supported!\n");
Marek Behún4529fce2020-04-08 12:02:05 +0200507 else if (i != 0)
Marek Behún35b35132018-12-17 16:10:03 +0100508 printf("Error: Passthrough Mini-PCIe module should be the first connected module!\n");
Marek Behún4529fce2020-04-08 12:02:05 +0200509 else
Marek Behún35b35132018-12-17 16:10:03 +0100510 ++passpci;
Marek Behún35b35132018-12-17 16:10:03 +0100511 }
512 }
513
514 /* now configure modules */
515
516 if (get_reset_gpio(&reset_gpio) < 0)
517 return 0;
518
519 if (peridot > 0) {
520 if (configure_peridots(&reset_gpio) < 0) {
521 printf("Cannot configure Peridot modules!\n");
522 peridot = 0;
523 }
524 } else {
525 dm_gpio_set_value(&reset_gpio, 1);
526 mdelay(50);
527 dm_gpio_set_value(&reset_gpio, 0);
528 mdelay(50);
529 }
530
531 if (peridot || topaz) {
532 /*
533 * now check if the addresses are set by reading Scratch & Misc
534 * register 0x70 of Peridot (and potentially Topaz) modules
535 */
536
537 bus = miiphy_get_dev_by_name("neta@30000");
538 if (!bus) {
539 printf("Cannot get MDIO bus device!\n");
540 } else {
541 for (i = 0; i < peridot; ++i)
542 check_switch_address(bus, 0x10 + i);
543
544 if (topaz)
545 check_switch_address(bus, 0x2);
546
547 sw_blink_leds(bus, peridot, topaz);
548 }
549 }
550
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100551 printf("\n");
Marek Behúnf835bed2018-04-24 17:21:31 +0200552
Marek Behúnf68ed8b2018-12-17 16:10:01 +0100553 return 0;
Marek Behúnf835bed2018-04-24 17:21:31 +0200554}
Marek Behún4529fce2020-04-08 12:02:05 +0200555
556#if defined(CONFIG_OF_BOARD_SETUP)
557
558static int vnode_by_path(void *blob, const char *fmt, va_list ap)
559{
560 char path[128];
561
562 vsnprintf(path, 128, fmt, ap);
563 return fdt_path_offset(blob, path);
564}
565
566static int node_by_path(void *blob, const char *fmt, ...)
567{
568 va_list ap;
569 int res;
570
571 va_start(ap, fmt);
572 res = vnode_by_path(blob, fmt, ap);
573 va_end(ap);
574
575 return res;
576}
577
578static int phandle_by_path(void *blob, const char *fmt, ...)
579{
580 va_list ap;
581 int node, phandle, res;
582
583 va_start(ap, fmt);
584 node = vnode_by_path(blob, fmt, ap);
585 va_end(ap);
586
587 if (node < 0)
588 return node;
589
590 phandle = fdt_get_phandle(blob, node);
591 if (phandle > 0)
592 return phandle;
593
594 phandle = fdt_get_max_phandle(blob);
595 if (phandle < 0)
596 return phandle;
597
598 phandle += 1;
599
600 res = fdt_setprop_u32(blob, node, "linux,phandle", phandle);
601 if (res < 0)
602 return res;
603
604 res = fdt_setprop_u32(blob, node, "phandle", phandle);
605 if (res < 0)
606 return res;
607
608 return phandle;
609}
610
611static int enable_by_path(void *blob, const char *fmt, ...)
612{
613 va_list ap;
614 int node;
615
616 va_start(ap, fmt);
617 node = vnode_by_path(blob, fmt, ap);
618 va_end(ap);
619
620 if (node < 0)
621 return node;
622
623 return fdt_setprop_string(blob, node, "status", "okay");
624}
625
626static bool is_topaz(int id)
627{
628 return topaz && id == peridot + topaz - 1;
629}
630
631static int switch_addr(int id)
632{
633 return is_topaz(id) ? 0x2 : 0x10 + id;
634}
635
636static int setup_switch(void *blob, int id)
637{
638 int res, addr, i, node, phandle;
639
640 addr = switch_addr(id);
641
642 /* first enable the switch by setting status = "okay" */
643 res = enable_by_path(blob, MDIO_PATH "/switch%i@%x", id, addr);
644 if (res < 0)
645 return res;
646
647 /*
648 * now if there are more switches or a SFP module coming after,
649 * enable corresponding ports
650 */
651 if (id < peridot + topaz - 1) {
652 res = enable_by_path(blob,
653 MDIO_PATH "/switch%i@%x/ports/port@a",
654 id, addr);
655 } else if (id == peridot - 1 && !topaz && sfp) {
656 res = enable_by_path(blob,
657 MDIO_PATH "/switch%i@%x/ports/port-sfp@a",
658 id, addr);
659 } else {
660 res = 0;
661 }
662 if (res < 0)
663 return res;
664
665 if (id >= peridot + topaz - 1)
666 return 0;
667
668 /* finally change link property if needed */
669 node = node_by_path(blob, MDIO_PATH "/switch%i@%x/ports/port@a", id,
670 addr);
671 if (node < 0)
672 return node;
673
674 for (i = id + 1; i < peridot + topaz; ++i) {
675 phandle = phandle_by_path(blob,
676 MDIO_PATH "/switch%i@%x/ports/port@%x",
677 i, switch_addr(i),
678 is_topaz(i) ? 5 : 9);
679 if (phandle < 0)
680 return phandle;
681
682 if (i == id + 1)
683 res = fdt_setprop_u32(blob, node, "link", phandle);
684 else
685 res = fdt_appendprop_u32(blob, node, "link", phandle);
686 if (res < 0)
687 return res;
688 }
689
690 return 0;
691}
692
693static int remove_disabled_nodes(void *blob)
694{
695 while (1) {
696 int res, offset;
697
698 offset = fdt_node_offset_by_prop_value(blob, -1, "status",
699 "disabled", 9);
700 if (offset < 0)
701 break;
702
703 res = fdt_del_node(blob, offset);
704 if (res < 0)
705 return res;
706 }
707
708 return 0;
709}
710
711int ft_board_setup(void *blob, bd_t *bd)
712{
713 int node, phandle, res;
714
715 /*
716 * If MOX B (PCI), MOX F (USB) or MOX G (Passthrough PCI) modules are
717 * connected, enable the PCIe node.
718 */
719 if (pci || usb || passpci) {
720 node = fdt_path_offset(blob, PCIE_PATH);
721 if (node < 0)
722 return node;
723
724 res = fdt_setprop_string(blob, node, "status", "okay");
725 if (res < 0)
726 return res;
727 }
728
729 /*
730 * If MOX C (Topaz switch) and/or MOX E (Peridot switch) are connected,
731 * enable the eth1 node and setup the switches.
732 */
733 if (peridot || topaz) {
734 int i;
735
736 res = enable_by_path(blob, ETH1_PATH);
737 if (res < 0)
738 return res;
739
740 for (i = 0; i < peridot + topaz; ++i) {
741 res = setup_switch(blob, i);
742 if (res < 0)
743 return res;
744 }
745 }
746
747 /*
748 * If MOX D (SFP cage module) is connected, enable the SFP node and eth1
749 * node. If there is no Peridot switch between MOX A and MOX D, add link
750 * to the SFP node to eth1 node.
751 * Also enable and configure SFP GPIO controller node.
752 */
753 if (sfp) {
754 res = enable_by_path(blob, SFP_PATH);
755 if (res < 0)
756 return res;
757
758 res = enable_by_path(blob, ETH1_PATH);
759 if (res < 0)
760 return res;
761
762 if (!peridot) {
763 phandle = phandle_by_path(blob, SFP_PATH);
764 if (phandle < 0)
765 return res;
766
767 node = node_by_path(blob, ETH1_PATH);
768 if (node < 0)
769 return node;
770
771 res = fdt_setprop_u32(blob, node, "sfp", phandle);
772 if (res < 0)
773 return res;
774
775 res = fdt_setprop_string(blob, node, "phy-mode",
776 "sgmii");
777 if (res < 0)
778 return res;
779 }
780
781 res = enable_by_path(blob, SFP_GPIO_PATH);
782 if (res < 0)
783 return res;
784
785 if (sfp_pos) {
786 char newname[16];
787
788 /* moxtet-sfp is on non-zero position, change default */
789 node = node_by_path(blob, SFP_GPIO_PATH);
790 if (node < 0)
791 return node;
792
793 res = fdt_setprop_u32(blob, node, "reg", sfp_pos);
794 if (res < 0)
795 return res;
796
797 sprintf(newname, "gpio@%x", sfp_pos);
798
799 res = fdt_set_name(blob, node, newname);
800 if (res < 0)
801 return res;
802 }
803 }
804
805 fdt_fixup_ethernet(blob);
806
807 /* Finally remove disabled nodes, as per Rob Herring's request. */
808 remove_disabled_nodes(blob);
809
810 return 0;
811}
812
813#endif