arm: mvebu: turris_mox: Find DT nodes by compatible or alias instead of path
[platform/kernel/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/arch/cpu.h>
8 #include <asm/arch/soc.h>
9 #include <net.h>
10 #include <asm/global_data.h>
11 #include <asm/io.h>
12 #include <asm/gpio.h>
13 #include <button.h>
14 #include <clk.h>
15 #include <dm.h>
16 #include <env.h>
17 #include <fdt_support.h>
18 #include <init.h>
19 #include <led.h>
20 #include <linux/delay.h>
21 #include <linux/libfdt.h>
22 #include <linux/string.h>
23 #include <miiphy.h>
24 #include <mvebu/comphy.h>
25 #include <spi.h>
26
27 #include "mox_sp.h"
28
29 #define MAX_MOX_MODULES         10
30
31 #define MOX_MODULE_SFP          0x1
32 #define MOX_MODULE_PCI          0x2
33 #define MOX_MODULE_TOPAZ        0x3
34 #define MOX_MODULE_PERIDOT      0x4
35 #define MOX_MODULE_USB3         0x5
36 #define MOX_MODULE_PASSPCI      0x6
37
38 #define ARMADA_37XX_NB_GPIO_SEL (MVEBU_REGISTER(0x13830))
39 #define ARMADA_37XX_SPI_CTRL    (MVEBU_REGISTER(0x10600))
40 #define ARMADA_37XX_SPI_CFG     (MVEBU_REGISTER(0x10604))
41 #define ARMADA_37XX_SPI_DOUT    (MVEBU_REGISTER(0x10608))
42 #define ARMADA_37XX_SPI_DIN     (MVEBU_REGISTER(0x1060c))
43
44 DECLARE_GLOBAL_DATA_PTR;
45
46 #if defined(CONFIG_OF_BOARD_FIXUP)
47 int board_fix_fdt(void *blob)
48 {
49         u8 topology[MAX_MOX_MODULES];
50         enum fdt_status status;
51         int i, size, ret;
52
53         /*
54          * SPI driver is not loaded in driver model yet, but we have to find out
55          * if pcie should be enabled in U-Boot's device tree. Therefore we have
56          * to read SPI by reading/writing SPI registers directly
57          */
58
59         writel(0x10df, ARMADA_37XX_SPI_CFG);
60         /* put pin from GPIO to SPI mode */
61         clrbits_le32(ARMADA_37XX_NB_GPIO_SEL, BIT(12));
62         /* enable SPI CS1 */
63         setbits_le32(ARMADA_37XX_SPI_CTRL, BIT(17));
64
65         while (!(readl(ARMADA_37XX_SPI_CTRL) & 0x2))
66                 udelay(1);
67
68         for (i = 0; i < MAX_MOX_MODULES; ++i) {
69                 writel(0x0, ARMADA_37XX_SPI_DOUT);
70
71                 while (!(readl(ARMADA_37XX_SPI_CTRL) & 0x2))
72                         udelay(1);
73
74                 topology[i] = readl(ARMADA_37XX_SPI_DIN) & 0xff;
75                 if (topology[i] == 0xff)
76                         break;
77
78                 topology[i] &= 0xf;
79         }
80
81         size = i;
82
83         /* disable SPI CS1 */
84         clrbits_le32(ARMADA_37XX_SPI_CTRL, BIT(17));
85
86         if (size > 1 && (topology[1] == MOX_MODULE_PCI ||
87                          topology[1] == MOX_MODULE_USB3 ||
88                          topology[1] == MOX_MODULE_PASSPCI))
89                 status = FDT_STATUS_OKAY;
90         else
91                 status = FDT_STATUS_DISABLED;
92
93         ret = fdt_set_status_by_compatible(blob, "marvell,armada-3700-pcie",
94                                            status);
95         if (ret < 0) {
96                 printf("Cannot set status for PCIe in U-Boot's device tree: %s!\n",
97                        fdt_strerror(ret));
98                 return 0;
99         }
100
101         if (a3700_fdt_fix_pcie_regions(blob) < 0) {
102                 printf("Cannot fix PCIe regions in U-Boot's device tree!\n");
103                 return 0;
104         }
105
106         return 0;
107 }
108 #endif
109
110 int board_init(void)
111 {
112         /* address of boot parameters */
113         gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
114
115         return 0;
116 }
117
118 static int mox_do_spi(u8 *in, u8 *out, size_t size)
119 {
120         struct spi_slave *slave;
121         struct udevice *dev;
122         int ret;
123
124         ret = spi_get_bus_and_cs(0, 1, 1000000, SPI_CPHA | SPI_CPOL,
125                                  "spi_generic_drv", "moxtet@1", &dev,
126                                  &slave);
127         if (ret)
128                 goto fail;
129
130         ret = spi_claim_bus(slave);
131         if (ret)
132                 goto fail_free;
133
134         ret = spi_xfer(slave, size * 8, out, in, SPI_XFER_ONCE);
135
136         spi_release_bus(slave);
137 fail_free:
138         spi_free_slave(slave);
139 fail:
140         return ret;
141 }
142
143 static int mox_get_topology(const u8 **ptopology, int *psize, int *pis_sd)
144 {
145         static int is_sd;
146         static u8 topology[MAX_MOX_MODULES - 1];
147         static int size;
148         u8 din[MAX_MOX_MODULES], dout[MAX_MOX_MODULES];
149         int ret, i;
150
151         if (size) {
152                 if (ptopology)
153                         *ptopology = topology;
154                 if (psize)
155                         *psize = size;
156                 if (pis_sd)
157                         *pis_sd = is_sd;
158                 return 0;
159         }
160
161         memset(din, 0, MAX_MOX_MODULES);
162         memset(dout, 0, MAX_MOX_MODULES);
163
164         ret = mox_do_spi(din, dout, MAX_MOX_MODULES);
165         if (ret)
166                 return ret;
167
168         if (din[0] == 0x10)
169                 is_sd = 1;
170         else if (din[0] == 0x00)
171                 is_sd = 0;
172         else
173                 return -ENODEV;
174
175         for (i = 1; i < MAX_MOX_MODULES && din[i] != 0xff; ++i)
176                 topology[i - 1] = din[i] & 0xf;
177         size = i - 1;
178
179         if (ptopology)
180                 *ptopology = topology;
181         if (psize)
182                 *psize = size;
183         if (pis_sd)
184                 *pis_sd = is_sd;
185
186         return 0;
187 }
188
189 int comphy_update_map(struct comphy_map *serdes_map, int count)
190 {
191         int ret, i, size, sfpindex = -1, swindex = -1;
192         const u8 *topology;
193
194         ret = mox_get_topology(&topology, &size, NULL);
195         if (ret)
196                 return ret;
197
198         for (i = 0; i < size; ++i) {
199                 if (topology[i] == MOX_MODULE_SFP && sfpindex == -1)
200                         sfpindex = i;
201                 else if ((topology[i] == MOX_MODULE_TOPAZ ||
202                           topology[i] == MOX_MODULE_PERIDOT) &&
203                          swindex == -1)
204                         swindex = i;
205         }
206
207         if (sfpindex >= 0 && swindex >= 0) {
208                 if (sfpindex < swindex)
209                         serdes_map[0].speed = COMPHY_SPEED_1_25G;
210                 else
211                         serdes_map[0].speed = COMPHY_SPEED_3_125G;
212         } else if (sfpindex >= 0) {
213                 serdes_map[0].speed = COMPHY_SPEED_1_25G;
214         } else if (swindex >= 0) {
215                 serdes_map[0].speed = COMPHY_SPEED_3_125G;
216         }
217
218         return 0;
219 }
220
221 #define SW_SMI_CMD_R(d, r)      (0x9800 | (((d) & 0x1f) << 5) | ((r) & 0x1f))
222 #define SW_SMI_CMD_W(d, r)      (0x9400 | (((d) & 0x1f) << 5) | ((r) & 0x1f))
223
224 static int sw_multi_read(struct mii_dev *bus, int sw, int dev, int reg)
225 {
226         bus->write(bus, sw, 0, 0, SW_SMI_CMD_R(dev, reg));
227         mdelay(5);
228         return bus->read(bus, sw, 0, 1);
229 }
230
231 static void sw_multi_write(struct mii_dev *bus, int sw, int dev, int reg,
232                            u16 val)
233 {
234         bus->write(bus, sw, 0, 1, val);
235         bus->write(bus, sw, 0, 0, SW_SMI_CMD_W(dev, reg));
236         mdelay(5);
237 }
238
239 static int sw_scratch_read(struct mii_dev *bus, int sw, int reg)
240 {
241         sw_multi_write(bus, sw, 0x1c, 0x1a, (reg & 0x7f) << 8);
242         return sw_multi_read(bus, sw, 0x1c, 0x1a) & 0xff;
243 }
244
245 static void sw_led_write(struct mii_dev *bus, int sw, int port, int reg,
246                          u16 val)
247 {
248         sw_multi_write(bus, sw, port, 0x16, 0x8000 | ((reg & 7) << 12)
249                                             | (val & 0x7ff));
250 }
251
252 static void sw_blink_leds(struct mii_dev *bus, int peridot, int topaz)
253 {
254         int i, p;
255         struct {
256                 int port;
257                 u16 val;
258                 int wait;
259         } regs[] = {
260                 { 2, 0xef, 1 }, { 2, 0xfe, 1 }, { 2, 0x33, 0 },
261                 { 4, 0xef, 1 }, { 4, 0xfe, 1 }, { 4, 0x33, 0 },
262                 { 3, 0xfe, 1 }, { 3, 0xef, 1 }, { 3, 0x33, 0 },
263                 { 1, 0xfe, 1 }, { 1, 0xef, 1 }, { 1, 0x33, 0 }
264         };
265
266         for (i = 0; i < 12; ++i) {
267                 for (p = 0; p < peridot; ++p) {
268                         sw_led_write(bus, 0x10 + p, regs[i].port, 0,
269                                      regs[i].val);
270                         sw_led_write(bus, 0x10 + p, regs[i].port + 4, 0,
271                                      regs[i].val);
272                 }
273                 if (topaz) {
274                         sw_led_write(bus, 0x2, 0x10 + regs[i].port, 0,
275                                      regs[i].val);
276                 }
277
278                 if (regs[i].wait)
279                         mdelay(75);
280         }
281 }
282
283 static void check_switch_address(struct mii_dev *bus, int addr)
284 {
285         if (sw_scratch_read(bus, addr, 0x70) >> 3 != addr)
286                 printf("Check of switch MDIO address failed for 0x%02x\n",
287                        addr);
288 }
289
290 static int sfp, pci, topaz, peridot, usb, passpci;
291 static int sfp_pos, peridot_pos[3];
292 static int module_count;
293
294 static int configure_peridots(struct gpio_desc *reset_gpio)
295 {
296         int i, ret;
297         u8 dout[MAX_MOX_MODULES];
298
299         memset(dout, 0, MAX_MOX_MODULES);
300
301         /* set addresses of Peridot modules */
302         for (i = 0; i < peridot; ++i)
303                 dout[module_count - peridot_pos[i]] = (~i) & 3;
304
305         /*
306          * if there is a SFP module connected to the last Peridot module, set
307          * the P10_SMODE to 1 for the Peridot module
308          */
309         if (sfp)
310                 dout[module_count - peridot_pos[i - 1]] |= 1 << 3;
311
312         dm_gpio_set_value(reset_gpio, 1);
313         mdelay(10);
314
315         ret = mox_do_spi(NULL, dout, module_count + 1);
316
317         mdelay(10);
318         dm_gpio_set_value(reset_gpio, 0);
319
320         mdelay(50);
321
322         return ret;
323 }
324
325 static int get_reset_gpio(struct gpio_desc *reset_gpio)
326 {
327         int node;
328
329         node = fdt_node_offset_by_compatible(gd->fdt_blob, 0, "cznic,moxtet");
330         if (node < 0) {
331                 printf("Cannot find Moxtet bus device node!\n");
332                 return -1;
333         }
334
335         gpio_request_by_name_nodev(offset_to_ofnode(node), "reset-gpios", 0,
336                                    reset_gpio, GPIOD_IS_OUT);
337
338         if (!dm_gpio_is_valid(reset_gpio)) {
339                 printf("Cannot find reset GPIO for Moxtet bus!\n");
340                 return -1;
341         }
342
343         return 0;
344 }
345
346 int misc_init_r(void)
347 {
348         u8 mac[2][6];
349         int i, ret;
350
351         ret = mbox_sp_get_board_info(NULL, mac[0], mac[1], NULL, NULL);
352         if (ret < 0) {
353                 printf("Cannot read data from OTP!\n");
354                 return 0;
355         }
356
357         for (i = 0; i < 2; ++i) {
358                 u8 oldmac[6];
359
360                 if (is_valid_ethaddr(mac[i]) &&
361                     !eth_env_get_enetaddr_by_index("eth", i, oldmac))
362                         eth_env_set_enetaddr_by_index("eth", i, mac[i]);
363         }
364
365         return 0;
366 }
367
368 static void mox_phy_modify(struct phy_device *phydev, int page, int reg,
369                            u16 mask, u16 set)
370 {
371         int val;
372
373         val = phydev->drv->readext(phydev, MDIO_DEVAD_NONE, page, reg);
374         val &= ~mask;
375         val |= set;
376         phydev->drv->writeext(phydev, MDIO_DEVAD_NONE, page, reg, val);
377 }
378
379 static void mox_phy_leds_start_blinking(void)
380 {
381         struct phy_device *phydev;
382         struct mii_dev *bus;
383
384         bus = miiphy_get_dev_by_name("neta@30000");
385         if (!bus) {
386                 printf("Cannot get MDIO bus device!\n");
387                 return;
388         }
389
390         phydev = phy_find_by_mask(bus, BIT(1), PHY_INTERFACE_MODE_RGMII);
391         if (!phydev) {
392                 printf("Cannot get ethernet PHY!\n");
393                 return;
394         }
395
396         mox_phy_modify(phydev, 3, 0x12, 0x700, 0x400);
397         mox_phy_modify(phydev, 3, 0x10, 0xff, 0xbb);
398 }
399
400 static bool read_reset_button(void)
401 {
402         struct udevice *button, *led;
403         int i;
404
405         if (device_get_global_by_ofnode(
406                         ofnode_first_subnode(ofnode_by_compatible(ofnode_null(),
407                                                                   "gpio-keys")),
408                         &button)) {
409                 printf("Cannot find reset button!\n");
410                 return false;
411         }
412
413         if (device_get_global_by_ofnode(
414                         ofnode_first_subnode(ofnode_by_compatible(ofnode_null(),
415                                                                   "gpio-leds")),
416                         &led)) {
417                 printf("Cannot find status LED!\n");
418                 return false;
419         }
420
421         led_set_state(led, LEDST_ON);
422
423         for (i = 0; i < 21; ++i) {
424                 if (button_get_state(button) != BUTTON_ON)
425                         return false;
426                 if (i < 20)
427                         mdelay(50);
428         }
429
430         led_set_state(led, LEDST_OFF);
431
432         return true;
433 }
434
435 static void handle_reset_button(void)
436 {
437         const char * const vars[1] = { "bootcmd_rescue", };
438
439         /*
440          * Ensure that bootcmd_rescue has always stock value, so that running
441          *   run bootcmd_rescue
442          * always works correctly.
443          */
444         env_set_default_vars(1, (char * const *)vars, 0);
445
446         if (read_reset_button()) {
447                 const char * const vars[2] = {
448                         "bootcmd",
449                         "distro_bootcmd",
450                 };
451
452                 /*
453                  * Set the above envs to their default values, in case the user
454                  * managed to break them.
455                  */
456                 env_set_default_vars(2, (char * const *)vars, 0);
457
458                 /* Ensure bootcmd_rescue is used by distroboot */
459                 env_set("boot_targets", "rescue");
460
461                 /* start blinking PHY LEDs */
462                 mox_phy_leds_start_blinking();
463
464                 printf("RESET button was pressed, overwriting boot_targets!\n");
465         } else {
466                 /*
467                  * In case the user somehow managed to save environment with
468                  * boot_targets=rescue, reset boot_targets to default value.
469                  * This could happen in subsequent commands if bootcmd_rescue
470                  * failed.
471                  */
472                 if (!strcmp(env_get("boot_targets"), "rescue")) {
473                         const char * const vars[1] = {
474                                 "boot_targets",
475                         };
476
477                         env_set_default_vars(1, (char * const *)vars, 0);
478                 }
479         }
480 }
481
482 int show_board_info(void)
483 {
484         int i, ret, board_version, ram_size, is_sd;
485         const char *pub_key;
486         const u8 *topology;
487         u64 serial_number;
488
489         printf("Model: CZ.NIC Turris Mox Board\n");
490
491         ret = mbox_sp_get_board_info(&serial_number, NULL, NULL, &board_version,
492                                      &ram_size);
493         if (ret < 0) {
494                 printf("  Cannot read board info: %i\n", ret);
495         } else {
496                 printf("  Board version: %i\n", board_version);
497                 printf("  RAM size: %i MiB\n", ram_size);
498                 printf("  Serial Number: %016llX\n", serial_number);
499         }
500
501         pub_key = mox_sp_get_ecdsa_public_key();
502         if (pub_key)
503                 printf("  ECDSA Public Key: %s\n", pub_key);
504         else
505                 printf("  Cannot read ECDSA Public Key\n");
506
507         ret = mox_get_topology(&topology, &module_count, &is_sd);
508         if (ret)
509                 printf("Cannot read module topology!\n");
510
511         printf("  SD/eMMC version: %s\n", is_sd ? "SD" : "eMMC");
512
513         if (module_count)
514                 printf("Module Topology:\n");
515
516         for (i = 0; i < module_count; ++i) {
517                 switch (topology[i]) {
518                 case MOX_MODULE_SFP:
519                         printf("% 4i: SFP Module\n", i + 1);
520                         break;
521                 case MOX_MODULE_PCI:
522                         printf("% 4i: Mini-PCIe Module\n", i + 1);
523                         break;
524                 case MOX_MODULE_TOPAZ:
525                         printf("% 4i: Topaz Switch Module (4-port)\n", i + 1);
526                         break;
527                 case MOX_MODULE_PERIDOT:
528                         printf("% 4i: Peridot Switch Module (8-port)\n", i + 1);
529                         break;
530                 case MOX_MODULE_USB3:
531                         printf("% 4i: USB 3.0 Module (4 ports)\n", i + 1);
532                         break;
533                 case MOX_MODULE_PASSPCI:
534                         printf("% 4i: Passthrough Mini-PCIe Module\n", i + 1);
535                         break;
536                 default:
537                         printf("% 4i: unknown (ID %i)\n", i + 1, topology[i]);
538                 }
539         }
540
541         /* check if modules are connected in supported mode */
542         for (i = 0; i < module_count; ++i) {
543                 switch (topology[i]) {
544                 case MOX_MODULE_SFP:
545                         if (sfp) {
546                                 printf("Error: Only one SFP module is supported!\n");
547                         } else if (topaz) {
548                                 printf("Error: SFP module cannot be connected after Topaz Switch module!\n");
549                         } else {
550                                 sfp_pos = i;
551                                 ++sfp;
552                         }
553                         break;
554                 case MOX_MODULE_PCI:
555                         if (pci)
556                                 printf("Error: Only one Mini-PCIe module is supported!\n");
557                         else if (usb)
558                                 printf("Error: Mini-PCIe module cannot come after USB 3.0 module!\n");
559                         else if (i && (i != 1 || !passpci))
560                                 printf("Error: Mini-PCIe module should be the first connected module or come right after Passthrough Mini-PCIe module!\n");
561                         else
562                                 ++pci;
563                         break;
564                 case MOX_MODULE_TOPAZ:
565                         if (topaz)
566                                 printf("Error: Only one Topaz module is supported!\n");
567                         else if (peridot >= 3)
568                                 printf("Error: At most two Peridot modules can come before Topaz module!\n");
569                         else
570                                 ++topaz;
571                         break;
572                 case MOX_MODULE_PERIDOT:
573                         if (sfp || topaz) {
574                                 printf("Error: Peridot module must come before SFP or Topaz module!\n");
575                         } else if (peridot >= 3) {
576                                 printf("Error: At most three Peridot modules are supported!\n");
577                         } else {
578                                 peridot_pos[peridot] = i;
579                                 ++peridot;
580                         }
581                         break;
582                 case MOX_MODULE_USB3:
583                         if (pci)
584                                 printf("Error: USB 3.0 module cannot come after Mini-PCIe module!\n");
585                         else if (usb)
586                                 printf("Error: Only one USB 3.0 module is supported!\n");
587                         else if (i && (i != 1 || !passpci))
588                                 printf("Error: USB 3.0 module should be the first connected module or come right after Passthrough Mini-PCIe module!\n");
589                         else
590                                 ++usb;
591                         break;
592                 case MOX_MODULE_PASSPCI:
593                         if (passpci)
594                                 printf("Error: Only one Passthrough Mini-PCIe module is supported!\n");
595                         else if (i != 0)
596                                 printf("Error: Passthrough Mini-PCIe module should be the first connected module!\n");
597                         else
598                                 ++passpci;
599                 }
600         }
601
602         if (module_count)
603                 printf("\n");
604
605         return 0;
606 }
607
608 int last_stage_init(void)
609 {
610         struct gpio_desc reset_gpio = {};
611
612         /* configure modules */
613         if (get_reset_gpio(&reset_gpio) < 0)
614                 goto handle_reset_btn;
615
616         if (peridot > 0) {
617                 if (configure_peridots(&reset_gpio) < 0) {
618                         printf("Cannot configure Peridot modules!\n");
619                         peridot = 0;
620                 }
621         } else {
622                 dm_gpio_set_value(&reset_gpio, 1);
623                 mdelay(50);
624                 dm_gpio_set_value(&reset_gpio, 0);
625                 mdelay(50);
626         }
627
628         /*
629          * check if the addresses are set by reading Scratch & Misc register
630          * 0x70 of Peridot (and potentially Topaz) modules
631          */
632         if (peridot || topaz) {
633                 struct mii_dev *bus;
634
635                 bus = miiphy_get_dev_by_name("neta@30000");
636                 if (!bus) {
637                         printf("Cannot get MDIO bus device!\n");
638                 } else {
639                         int i;
640
641                         for (i = 0; i < peridot; ++i)
642                                 check_switch_address(bus, 0x10 + i);
643
644                         if (topaz)
645                                 check_switch_address(bus, 0x2);
646
647                         sw_blink_leds(bus, peridot, topaz);
648                 }
649         }
650
651 handle_reset_btn:
652         handle_reset_button();
653
654         return 0;
655 }
656
657 #if defined(CONFIG_OF_BOARD_SETUP)
658
659 static bool is_topaz(int id)
660 {
661         return topaz && id == peridot + topaz - 1;
662 }
663
664 static int switch_addr(int id)
665 {
666         return is_topaz(id) ? 0x2 : 0x10 + id;
667 }
668
669 static int setup_switch(void *blob, int id)
670 {
671         int res, addr, i, node;
672         char mdio_path[64];
673
674         node = fdt_node_offset_by_compatible(blob, -1, "marvell,orion-mdio");
675         if (node < 0)
676                 return node;
677
678         res = fdt_get_path(blob, node, mdio_path, sizeof(mdio_path));
679         if (res < 0)
680                 return res;
681
682         addr = switch_addr(id);
683
684         /* first enable the switch by setting status = "okay" */
685         res = fdt_status_okay_by_pathf(blob, "%s/switch%i@%x", mdio_path, id,
686                                        addr);
687         if (res < 0)
688                 return res;
689
690         /*
691          * now if there are more switches or a SFP module coming after,
692          * enable corresponding ports
693          */
694         if (id < peridot + topaz - 1) {
695                 res = fdt_status_okay_by_pathf(blob,
696                                                "%s/switch%i@%x/ports/port@a",
697                                                mdio_path, id, addr);
698         } else if (id == peridot - 1 && !topaz && sfp) {
699                 res = fdt_status_okay_by_pathf(blob,
700                                                "%s/switch%i@%x/ports/port-sfp@a",
701                                                mdio_path, id, addr);
702         } else {
703                 res = 0;
704         }
705         if (res < 0)
706                 return res;
707
708         if (id >= peridot + topaz - 1)
709                 return 0;
710
711         /* finally change link property if needed */
712         node = fdt_node_offset_by_pathf(blob, "%s/switch%i@%x/ports/port@a",
713                                         mdio_path, id, addr);
714         if (node < 0)
715                 return node;
716
717         for (i = id + 1; i < peridot + topaz; ++i) {
718                 unsigned int phandle;
719
720                 phandle = fdt_create_phandle_by_pathf(blob,
721                                                       "%s/switch%i@%x/ports/port@%x",
722                                                       mdio_path, i,
723                                                       switch_addr(i),
724                                                       is_topaz(i) ? 5 : 9);
725                 if (!phandle)
726                         return -FDT_ERR_NOPHANDLES;
727
728                 if (i == id + 1)
729                         res = fdt_setprop_u32(blob, node, "link", phandle);
730                 else
731                         res = fdt_appendprop_u32(blob, node, "link", phandle);
732                 if (res < 0)
733                         return res;
734         }
735
736         return 0;
737 }
738
739 static int remove_disabled_nodes(void *blob)
740 {
741         while (1) {
742                 int res, offset;
743
744                 offset = fdt_node_offset_by_prop_value(blob, -1, "status",
745                                                        "disabled", 9);
746                 if (offset < 0)
747                         break;
748
749                 res = fdt_del_node(blob, offset);
750                 if (res < 0)
751                         return res;
752         }
753
754         return 0;
755 }
756
757 int ft_board_setup(void *blob, struct bd_info *bd)
758 {
759         int res;
760
761         /*
762          * If MOX B (PCI), MOX F (USB) or MOX G (Passthrough PCI) modules are
763          * connected, enable the PCIe node.
764          */
765         if (pci || usb || passpci) {
766                 res = fdt_status_okay_by_compatible(blob,
767                                                     "marvell,armada-3700-pcie");
768                 if (res < 0)
769                         return res;
770
771                 /* Fix PCIe regions for devices with 4 GB RAM */
772                 res = a3700_fdt_fix_pcie_regions(blob);
773                 if (res < 0)
774                         return res;
775         }
776
777         /*
778          * If MOX C (Topaz switch) and/or MOX E (Peridot switch) are connected,
779          * enable the eth1 node and setup the switches.
780          */
781         if (peridot || topaz) {
782                 int i;
783
784                 res = fdt_status_okay_by_alias(blob, "ethernet1");
785                 if (res < 0)
786                         return res;
787
788                 for (i = 0; i < peridot + topaz; ++i) {
789                         res = setup_switch(blob, i);
790                         if (res < 0)
791                                 return res;
792                 }
793         }
794
795         /*
796          * If MOX D (SFP cage module) is connected, enable the SFP node and eth1
797          * node. If there is no Peridot switch between MOX A and MOX D, add link
798          * to the SFP node to eth1 node.
799          * Also enable and configure SFP GPIO controller node.
800          */
801         if (sfp) {
802                 int node;
803
804                 res = fdt_status_okay_by_compatible(blob, "sff,sfp");
805                 if (res < 0)
806                         return res;
807
808                 res = fdt_status_okay_by_alias(blob, "ethernet1");
809                 if (res < 0)
810                         return res;
811
812                 if (!peridot) {
813                         unsigned int phandle;
814
815                         phandle = fdt_create_phandle_by_compatible(blob,
816                                                                    "sff,sfp");
817                         if (!phandle)
818                                 return -FDT_ERR_NOPHANDLES;
819
820                         node = fdt_path_offset(blob, "ethernet1");
821                         if (node < 0)
822                                 return node;
823
824                         res = fdt_setprop_u32(blob, node, "sfp", phandle);
825                         if (res < 0)
826                                 return res;
827
828                         res = fdt_setprop_string(blob, node, "phy-mode",
829                                                  "sgmii");
830                         if (res < 0)
831                                 return res;
832                 }
833
834                 res = fdt_status_okay_by_compatible(blob, "cznic,moxtet-gpio");
835                 if (res < 0)
836                         return res;
837
838                 if (sfp_pos) {
839                         char newname[16];
840
841                         /* moxtet-sfp is on non-zero position, change default */
842                         node = fdt_node_offset_by_compatible(blob, -1,
843                                                              "cznic,moxtet-gpio");
844                         if (node < 0)
845                                 return node;
846
847                         res = fdt_setprop_u32(blob, node, "reg", sfp_pos);
848                         if (res < 0)
849                                 return res;
850
851                         sprintf(newname, "gpio@%x", sfp_pos);
852
853                         res = fdt_set_name(blob, node, newname);
854                         if (res < 0)
855                                 return res;
856                 }
857         }
858
859         fdt_fixup_ethernet(blob);
860
861         /* Finally remove disabled nodes, as per Rob Herring's request. */
862         remove_disabled_nodes(blob);
863
864         return 0;
865 }
866
867 #endif