1 /* 2 * Copyright (C) 2012-2017 Altera Corporation <www.altera.com> 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <asm/io.h> 9 #include <errno.h> 10 #include <fdtdec.h> 11 #include <libfdt.h> 12 #include <altera.h> 13 #include <miiphy.h> 14 #include <netdev.h> 15 #include <watchdog.h> 16 #include <asm/arch/misc.h> 17 #include <asm/arch/reset_manager.h> 18 #include <asm/arch/scan_manager.h> 19 #include <asm/arch/sdram.h> 20 #include <asm/arch/system_manager.h> 21 #include <asm/arch/nic301.h> 22 #include <asm/arch/scu.h> 23 #include <asm/pl310.h> 24 25 #include <dt-bindings/reset/altr,rst-mgr.h> 26 27 DECLARE_GLOBAL_DATA_PTR; 28 29 static struct pl310_regs *const pl310 = 30 (struct pl310_regs *)CONFIG_SYS_PL310_BASE; 31 static struct socfpga_system_manager *sysmgr_regs = 32 (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS; 33 static struct socfpga_reset_manager *reset_manager_base = 34 (struct socfpga_reset_manager *)SOCFPGA_RSTMGR_ADDRESS; 35 static struct nic301_registers *nic301_regs = 36 (struct nic301_registers *)SOCFPGA_L3REGS_ADDRESS; 37 static struct scu_registers *scu_regs = 38 (struct scu_registers *)SOCFPGA_MPUSCU_ADDRESS; 39 static struct socfpga_sdr_ctrl *sdr_ctrl = 40 (struct socfpga_sdr_ctrl *)SDR_CTRLGRP_ADDRESS; 41 42 /* 43 * DesignWare Ethernet initialization 44 */ 45 #ifdef CONFIG_ETH_DESIGNWARE 46 void dwmac_deassert_reset(const unsigned int of_reset_id, 47 const u32 phymode) 48 { 49 u32 physhift, reset; 50 51 if (of_reset_id == EMAC0_RESET) { 52 physhift = SYSMGR_EMACGRP_CTRL_PHYSEL0_LSB; 53 reset = SOCFPGA_RESET(EMAC0); 54 } else if (of_reset_id == EMAC1_RESET) { 55 physhift = SYSMGR_EMACGRP_CTRL_PHYSEL1_LSB; 56 reset = SOCFPGA_RESET(EMAC1); 57 } else { 58 printf("GMAC: Invalid reset ID (%i)!\n", of_reset_id); 59 return; 60 } 61 62 /* configure to PHY interface select choosed */ 63 clrsetbits_le32(&sysmgr_regs->emacgrp_ctrl, 64 SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << physhift, 65 phymode << physhift); 66 67 /* Release the EMAC controller from reset */ 68 socfpga_per_reset(reset, 0); 69 } 70 71 static u32 dwmac_phymode_to_modereg(const char *phymode, u32 *modereg) 72 { 73 if (!phymode) 74 return -EINVAL; 75 76 if (!strcmp(phymode, "mii") || !strcmp(phymode, "gmii")) { 77 *modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; 78 return 0; 79 } 80 81 if (!strcmp(phymode, "rgmii")) { 82 *modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII; 83 return 0; 84 } 85 86 if (!strcmp(phymode, "rmii")) { 87 *modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII; 88 return 0; 89 } 90 91 return -EINVAL; 92 } 93 94 static int socfpga_eth_reset(void) 95 { 96 const void *fdt = gd->fdt_blob; 97 struct fdtdec_phandle_args args; 98 const char *phy_mode; 99 u32 phy_modereg; 100 int nodes[2]; /* Max. two GMACs */ 101 int ret, count; 102 int i, node; 103 104 /* Put both GMACs into RESET state. */ 105 socfpga_per_reset(SOCFPGA_RESET(EMAC0), 1); 106 socfpga_per_reset(SOCFPGA_RESET(EMAC1), 1); 107 108 count = fdtdec_find_aliases_for_id(fdt, "ethernet", 109 COMPAT_ALTERA_SOCFPGA_DWMAC, 110 nodes, ARRAY_SIZE(nodes)); 111 for (i = 0; i < count; i++) { 112 node = nodes[i]; 113 if (node <= 0) 114 continue; 115 116 ret = fdtdec_parse_phandle_with_args(fdt, node, "resets", 117 "#reset-cells", 1, 0, 118 &args); 119 if (ret || (args.args_count != 1)) { 120 debug("GMAC%i: Failed to parse DT 'resets'!\n", i); 121 continue; 122 } 123 124 phy_mode = fdt_getprop(fdt, node, "phy-mode", NULL); 125 ret = dwmac_phymode_to_modereg(phy_mode, &phy_modereg); 126 if (ret) { 127 debug("GMAC%i: Failed to parse DT 'phy-mode'!\n", i); 128 continue; 129 } 130 131 dwmac_deassert_reset(args.args[0], phy_modereg); 132 } 133 134 return 0; 135 } 136 #else 137 static int socfpga_eth_reset(void) 138 { 139 return 0; 140 }; 141 #endif 142 143 static const struct { 144 const u16 pn; 145 const char *name; 146 const char *var; 147 } const socfpga_fpga_model[] = { 148 /* Cyclone V E */ 149 { 0x2b15, "Cyclone V, E/A2", "cv_e_a2" }, 150 { 0x2b05, "Cyclone V, E/A4", "cv_e_a4" }, 151 { 0x2b22, "Cyclone V, E/A5", "cv_e_a5" }, 152 { 0x2b13, "Cyclone V, E/A7", "cv_e_a7" }, 153 { 0x2b14, "Cyclone V, E/A9", "cv_e_a9" }, 154 /* Cyclone V GX/GT */ 155 { 0x2b01, "Cyclone V, GX/C3", "cv_gx_c3" }, 156 { 0x2b12, "Cyclone V, GX/C4", "cv_gx_c4" }, 157 { 0x2b02, "Cyclone V, GX/C5 or GT/D5", "cv_gx_c5" }, 158 { 0x2b03, "Cyclone V, GX/C7 or GT/D7", "cv_gx_c7" }, 159 { 0x2b04, "Cyclone V, GX/C9 or GT/D9", "cv_gx_c9" }, 160 /* Cyclone V SE/SX/ST */ 161 { 0x2d11, "Cyclone V, SE/A2 or SX/C2", "cv_se_a2" }, 162 { 0x2d01, "Cyclone V, SE/A4 or SX/C4", "cv_se_a4" }, 163 { 0x2d12, "Cyclone V, SE/A5 or SX/C5 or ST/D5", "cv_se_a5" }, 164 { 0x2d02, "Cyclone V, SE/A6 or SX/C6 or ST/D6", "cv_se_a6" }, 165 /* Arria V */ 166 { 0x2d03, "Arria V, D5", "av_d5" }, 167 }; 168 169 static int socfpga_fpga_id(const bool print_id) 170 { 171 const u32 altera_mi = 0x6e; 172 const u32 id = scan_mgr_get_fpga_id(); 173 174 const u32 lsb = id & 0x00000001; 175 const u32 mi = (id >> 1) & 0x000007ff; 176 const u32 pn = (id >> 12) & 0x0000ffff; 177 const u32 version = (id >> 28) & 0x0000000f; 178 int i; 179 180 if ((mi != altera_mi) || (lsb != 1)) { 181 printf("FPGA: Not Altera chip ID\n"); 182 return -EINVAL; 183 } 184 185 for (i = 0; i < ARRAY_SIZE(socfpga_fpga_model); i++) 186 if (pn == socfpga_fpga_model[i].pn) 187 break; 188 189 if (i == ARRAY_SIZE(socfpga_fpga_model)) { 190 printf("FPGA: Unknown Altera chip, ID 0x%08x\n", id); 191 return -EINVAL; 192 } 193 194 if (print_id) 195 printf("FPGA: Altera %s, version 0x%01x\n", 196 socfpga_fpga_model[i].name, version); 197 return i; 198 } 199 200 /* 201 * Print CPU information 202 */ 203 #if defined(CONFIG_DISPLAY_CPUINFO) 204 int print_cpuinfo(void) 205 { 206 const u32 bsel = 207 SYSMGR_GET_BOOTINFO_BSEL(readl(&sysmgr_regs->bootinfo)); 208 209 puts("CPU: Altera SoCFPGA Platform\n"); 210 socfpga_fpga_id(1); 211 212 printf("BOOT: %s\n", bsel_str[bsel].name); 213 return 0; 214 } 215 #endif 216 217 #ifdef CONFIG_ARCH_MISC_INIT 218 int arch_misc_init(void) 219 { 220 const u32 bsel = readl(&sysmgr_regs->bootinfo) & 0x7; 221 const int fpga_id = socfpga_fpga_id(0); 222 env_set("bootmode", bsel_str[bsel].mode); 223 if (fpga_id >= 0) 224 env_set("fpgatype", socfpga_fpga_model[fpga_id].var); 225 return socfpga_eth_reset(); 226 } 227 #endif 228 229 /* 230 * Convert all NIC-301 AMBA slaves from secure to non-secure 231 */ 232 static void socfpga_nic301_slave_ns(void) 233 { 234 writel(0x1, &nic301_regs->lwhps2fpgaregs); 235 writel(0x1, &nic301_regs->hps2fpgaregs); 236 writel(0x1, &nic301_regs->acp); 237 writel(0x1, &nic301_regs->rom); 238 writel(0x1, &nic301_regs->ocram); 239 writel(0x1, &nic301_regs->sdrdata); 240 } 241 242 static u32 iswgrp_handoff[8]; 243 244 int arch_early_init_r(void) 245 { 246 int i; 247 248 /* 249 * Write magic value into magic register to unlock support for 250 * issuing warm reset. The ancient kernel code expects this 251 * value to be written into the register by the bootloader, so 252 * to support that old code, we write it here instead of in the 253 * reset_cpu() function just before resetting the CPU. 254 */ 255 writel(0xae9efebc, &sysmgr_regs->romcodegrp_warmramgrp_enable); 256 257 for (i = 0; i < 8; i++) /* Cache initial SW setting regs */ 258 iswgrp_handoff[i] = readl(&sysmgr_regs->iswgrp_handoff[i]); 259 260 socfpga_bridges_reset(1); 261 262 socfpga_nic301_slave_ns(); 263 264 /* 265 * Private components security: 266 * U-Boot : configure private timer, global timer and cpu component 267 * access as non secure for kernel stage (as required by Linux) 268 */ 269 setbits_le32(&scu_regs->sacr, 0xfff); 270 271 /* Configure the L2 controller to make SDRAM start at 0 */ 272 #ifdef CONFIG_SOCFPGA_VIRTUAL_TARGET 273 writel(0x2, &nic301_regs->remap); 274 #else 275 writel(0x1, &nic301_regs->remap); /* remap.mpuzero */ 276 writel(0x1, &pl310->pl310_addr_filter_start); 277 #endif 278 279 /* Add device descriptor to FPGA device table */ 280 socfpga_fpga_add(); 281 282 #ifdef CONFIG_DESIGNWARE_SPI 283 /* Get Designware SPI controller out of reset */ 284 socfpga_per_reset(SOCFPGA_RESET(SPIM0), 0); 285 socfpga_per_reset(SOCFPGA_RESET(SPIM1), 0); 286 #endif 287 288 #ifdef CONFIG_NAND_DENALI 289 socfpga_per_reset(SOCFPGA_RESET(NAND), 0); 290 #endif 291 292 return 0; 293 } 294 295 static void socfpga_sdram_apply_static_cfg(void) 296 { 297 const u32 applymask = 0x8; 298 u32 val = readl(&sdr_ctrl->static_cfg) | applymask; 299 300 /* 301 * SDRAM staticcfg register specific: 302 * When applying the register setting, the CPU must not access 303 * SDRAM. Luckily for us, we can abuse i-cache here to help us 304 * circumvent the SDRAM access issue. The idea is to make sure 305 * that the code is in one full i-cache line by branching past 306 * it and back. Once it is in the i-cache, we execute the core 307 * of the code and apply the register settings. 308 * 309 * The code below uses 7 instructions, while the Cortex-A9 has 310 * 32-byte cachelines, thus the limit is 8 instructions total. 311 */ 312 asm volatile( 313 ".align 5 \n" 314 " b 2f \n" 315 "1: str %0, [%1] \n" 316 " dsb \n" 317 " isb \n" 318 " b 3f \n" 319 "2: b 1b \n" 320 "3: nop \n" 321 : : "r"(val), "r"(&sdr_ctrl->static_cfg) : "memory", "cc"); 322 } 323 324 int do_bridge(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 325 { 326 if (argc != 2) 327 return CMD_RET_USAGE; 328 329 argv++; 330 331 switch (*argv[0]) { 332 case 'e': /* Enable */ 333 writel(iswgrp_handoff[2], &sysmgr_regs->fpgaintfgrp_module); 334 socfpga_sdram_apply_static_cfg(); 335 writel(iswgrp_handoff[3], &sdr_ctrl->fpgaport_rst); 336 writel(iswgrp_handoff[0], &reset_manager_base->brg_mod_reset); 337 writel(iswgrp_handoff[1], &nic301_regs->remap); 338 break; 339 case 'd': /* Disable */ 340 writel(0, &sysmgr_regs->fpgaintfgrp_module); 341 writel(0, &sdr_ctrl->fpgaport_rst); 342 socfpga_sdram_apply_static_cfg(); 343 writel(0, &reset_manager_base->brg_mod_reset); 344 writel(1, &nic301_regs->remap); 345 break; 346 default: 347 return CMD_RET_USAGE; 348 } 349 350 return 0; 351 } 352 353 U_BOOT_CMD( 354 bridge, 2, 1, do_bridge, 355 "SoCFPGA HPS FPGA bridge control", 356 "enable - Enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges\n" 357 "bridge disable - Enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges\n" 358 "" 359 ); 360