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