Tom Rini | 10e4779 | 2018-05-06 17:58:06 -0400 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 2 | /* |
Tien Fong Chee | 8ca1708 | 2021-11-07 23:08:55 +0800 | [diff] [blame] | 3 | * Copyright (C) 2016-2021 Intel Corporation |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 4 | */ |
| 5 | |
| 6 | #include <altera.h> |
Tom Rini | dec7ea0 | 2024-05-20 13:35:03 -0600 | [diff] [blame] | 7 | #include <config.h> |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 8 | #include <errno.h> |
| 9 | #include <fdtdec.h> |
Simon Glass | 9758973 | 2020-05-10 11:40:02 -0600 | [diff] [blame] | 10 | #include <init.h> |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 11 | #include <miiphy.h> |
| 12 | #include <netdev.h> |
| 13 | #include <ns16550.h> |
Tien Fong Chee | 8ca1708 | 2021-11-07 23:08:55 +0800 | [diff] [blame] | 14 | #include <spi_flash.h> |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 15 | #include <watchdog.h> |
| 16 | #include <asm/arch/misc.h> |
| 17 | #include <asm/arch/pinmux.h> |
| 18 | #include <asm/arch/reset_manager.h> |
Ley Foon Tan | 2b96352 | 2018-06-01 16:13:19 +0800 | [diff] [blame] | 19 | #include <asm/arch/reset_manager_arria10.h> |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 20 | #include <asm/arch/sdram_arria10.h> |
| 21 | #include <asm/arch/system_manager.h> |
| 22 | #include <asm/arch/nic301.h> |
| 23 | #include <asm/io.h> |
| 24 | #include <asm/pl310.h> |
Tien Fong Chee | 8ca1708 | 2021-11-07 23:08:55 +0800 | [diff] [blame] | 25 | #include <linux/sizes.h> |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 26 | |
| 27 | #define PINMUX_UART0_TX_SHARED_IO_OFFSET_Q1_3 0x08 |
| 28 | #define PINMUX_UART0_TX_SHARED_IO_OFFSET_Q2_11 0x58 |
| 29 | #define PINMUX_UART0_TX_SHARED_IO_OFFSET_Q3_3 0x68 |
| 30 | #define PINMUX_UART1_TX_SHARED_IO_OFFSET_Q1_7 0x18 |
| 31 | #define PINMUX_UART1_TX_SHARED_IO_OFFSET_Q3_7 0x78 |
| 32 | #define PINMUX_UART1_TX_SHARED_IO_OFFSET_Q4_3 0x98 |
| 33 | |
Tien Fong Chee | 8ca1708 | 2021-11-07 23:08:55 +0800 | [diff] [blame] | 34 | #define REGULAR_BOOT_MAGIC 0xd15ea5e |
Tien Fong Chee | adc079f | 2021-11-07 23:08:56 +0800 | [diff] [blame] | 35 | #define PERIPH_RBF_PROG_FORCE 0x50455249 |
Tien Fong Chee | 8ca1708 | 2021-11-07 23:08:55 +0800 | [diff] [blame] | 36 | |
| 37 | #define QSPI_S25FL_SOFT_RESET_COMMAND 0x00f0ff82 |
| 38 | #define QSPI_N25_SOFT_RESET_COMMAND 0x00000001 |
| 39 | #define QSPI_NO_SOFT_RESET 0x00000000 |
| 40 | |
Ang, Chee Hong | ff14f16 | 2018-12-19 18:35:15 -0800 | [diff] [blame] | 41 | /* |
| 42 | * FPGA programming support for SoC FPGA Arria 10 |
| 43 | */ |
| 44 | static Altera_desc altera_fpga[] = { |
| 45 | { |
| 46 | /* Family */ |
| 47 | Altera_SoCFPGA, |
| 48 | /* Interface type */ |
| 49 | fast_passive_parallel, |
| 50 | /* No limitation as additional data will be ignored */ |
| 51 | -1, |
| 52 | /* No device function table */ |
| 53 | NULL, |
| 54 | /* Base interface address specified in driver */ |
| 55 | NULL, |
| 56 | /* No cookie implementation */ |
| 57 | 0 |
| 58 | }, |
| 59 | }; |
| 60 | |
Simon Glass | 85ed77d | 2024-09-29 19:49:46 -0600 | [diff] [blame] | 61 | #if defined(CONFIG_XPL_BUILD) |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 62 | static struct pl310_regs *const pl310 = |
Tom Rini | 6a5dccc | 2022-11-16 13:10:41 -0500 | [diff] [blame] | 63 | (struct pl310_regs *)CFG_SYS_PL310_BASE; |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 64 | static const struct socfpga_noc_fw_ocram *noc_fw_ocram_base = |
| 65 | (void *)SOCFPGA_SDR_FIREWALL_OCRAM_ADDRESS; |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 66 | |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 67 | /* |
| 68 | + * This function initializes security policies to be consistent across |
| 69 | + * all logic units in the Arria 10. |
| 70 | + * |
| 71 | + * The idea is to set all security policies to be normal, nonsecure |
| 72 | + * for all units. |
| 73 | + */ |
Marek Vasut | 8fdb419 | 2018-08-18 19:11:52 +0200 | [diff] [blame] | 74 | void socfpga_init_security_policies(void) |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 75 | { |
| 76 | /* Put OCRAM in non-secure */ |
| 77 | writel(0x003f0000, &noc_fw_ocram_base->region0); |
| 78 | writel(0x1, &noc_fw_ocram_base->enable); |
Marek Vasut | 3e034a3 | 2018-07-12 15:34:23 +0200 | [diff] [blame] | 79 | |
| 80 | /* Put DDR in non-secure */ |
| 81 | writel(0xffff0000, SOCFPGA_SDR_FIREWALL_L3_ADDRESS + 0xc); |
| 82 | writel(0x1, SOCFPGA_SDR_FIREWALL_L3_ADDRESS); |
| 83 | |
| 84 | /* Enable priviledged and non-priviledged access to L4 peripherals */ |
| 85 | writel(~0, SOCFPGA_NOC_L4_PRIV_FLT_OFST); |
| 86 | |
| 87 | /* Enable secure and non-secure transactions to bridges */ |
| 88 | writel(~0, SOCFPGA_NOC_FW_H2F_SCR_OFST); |
| 89 | writel(~0, SOCFPGA_NOC_FW_H2F_SCR_OFST + 4); |
| 90 | |
Ley Foon Tan | 3d3a860 | 2019-11-08 10:38:20 +0800 | [diff] [blame] | 91 | writel(0x0007FFFF, |
| 92 | socfpga_get_sysmgr_addr() + SYSMGR_A10_ECC_INTMASK_SET); |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 93 | } |
| 94 | |
Marek Vasut | 8fdb419 | 2018-08-18 19:11:52 +0200 | [diff] [blame] | 95 | void socfpga_sdram_remap_zero(void) |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 96 | { |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 97 | /* Configure the L2 controller to make SDRAM start at 0 */ |
| 98 | writel(0x1, &pl310->pl310_addr_filter_start); |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 99 | } |
Marek Vasut | 8fdb419 | 2018-08-18 19:11:52 +0200 | [diff] [blame] | 100 | #endif |
| 101 | |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 102 | int arch_early_init_r(void) |
| 103 | { |
Marek Vasut | 8fdb419 | 2018-08-18 19:11:52 +0200 | [diff] [blame] | 104 | /* Add device descriptor to FPGA device table */ |
Ang, Chee Hong | ff14f16 | 2018-12-19 18:35:15 -0800 | [diff] [blame] | 105 | socfpga_fpga_add(&altera_fpga[0]); |
Marek Vasut | 8fdb419 | 2018-08-18 19:11:52 +0200 | [diff] [blame] | 106 | |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 107 | return 0; |
| 108 | } |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 109 | |
| 110 | /* |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 111 | * Print CPU information |
| 112 | */ |
| 113 | #if defined(CONFIG_DISPLAY_CPUINFO) |
| 114 | int print_cpuinfo(void) |
| 115 | { |
Ley Foon Tan | 3d3a860 | 2019-11-08 10:38:20 +0800 | [diff] [blame] | 116 | const u32 bootinfo = readl(socfpga_get_sysmgr_addr() + |
| 117 | SYSMGR_A10_BOOTINFO); |
| 118 | const u32 bsel = SYSMGR_GET_BOOTINFO_BSEL(bootinfo); |
Ley Foon Tan | cfd0c54 | 2017-04-26 02:44:43 +0800 | [diff] [blame] | 119 | |
| 120 | puts("CPU: Altera SoCFPGA Arria 10\n"); |
| 121 | |
| 122 | printf("BOOT: %s\n", bsel_str[bsel].name); |
| 123 | return 0; |
| 124 | } |
| 125 | #endif |
| 126 | |
Marek Vasut | 713a8a2 | 2019-04-16 22:28:08 +0200 | [diff] [blame] | 127 | void do_bridge_reset(int enable, unsigned int mask) |
Ley Foon Tan | 2b96352 | 2018-06-01 16:13:19 +0800 | [diff] [blame] | 128 | { |
| 129 | if (enable) |
| 130 | socfpga_reset_deassert_bridges_handoff(); |
| 131 | else |
| 132 | socfpga_bridges_reset(); |
| 133 | } |
Tien Fong Chee | 8ca1708 | 2021-11-07 23:08:55 +0800 | [diff] [blame] | 134 | |
| 135 | /* |
Tien Fong Chee | adc079f | 2021-11-07 23:08:56 +0800 | [diff] [blame] | 136 | * This function set/unset flag with number "0x50455249" to |
| 137 | * handoff register isw_handoff[7] - 0xffd0624c |
| 138 | * This flag is used to force periph RBF program regardless FPGA status |
| 139 | * and double periph RBF config are needed on some devices or boards to |
| 140 | * stabilize the IO config system. |
| 141 | */ |
| 142 | void force_periph_program(unsigned int status) |
| 143 | { |
| 144 | if (status) |
| 145 | writel(PERIPH_RBF_PROG_FORCE, socfpga_get_sysmgr_addr() + |
| 146 | SYSMGR_A10_ISW_HANDOFF_BASE + SYSMGR_A10_ISW_HANDOFF_7); |
| 147 | else |
| 148 | writel(0, socfpga_get_sysmgr_addr() + |
| 149 | SYSMGR_A10_ISW_HANDOFF_BASE + SYSMGR_A10_ISW_HANDOFF_7); |
| 150 | } |
| 151 | |
| 152 | /* |
| 153 | * This function is used to check whether |
| 154 | * handoff register isw_handoff[7] contains |
| 155 | * flag for forcing the periph RBF program "0x50455249". |
| 156 | */ |
| 157 | bool is_periph_program_force(void) |
| 158 | { |
| 159 | unsigned int status; |
| 160 | |
| 161 | status = readl(socfpga_get_sysmgr_addr() + |
| 162 | SYSMGR_A10_ISW_HANDOFF_BASE + SYSMGR_A10_ISW_HANDOFF_7); |
| 163 | |
| 164 | if (status == PERIPH_RBF_PROG_FORCE) |
| 165 | return true; |
| 166 | else |
| 167 | return false; |
| 168 | } |
| 169 | |
| 170 | /* |
Tien Fong Chee | 8ca1708 | 2021-11-07 23:08:55 +0800 | [diff] [blame] | 171 | * This function set/unset magic number "0xd15ea5e" to |
| 172 | * handoff register isw_handoff[7] - 0xffd0624c |
| 173 | * This magic number is part of boot progress tracking |
| 174 | * and it's required for warm reset workaround on MPFE hang issue. |
| 175 | */ |
| 176 | void set_regular_boot(unsigned int status) |
| 177 | { |
| 178 | if (status) |
| 179 | writel(REGULAR_BOOT_MAGIC, socfpga_get_sysmgr_addr() + |
| 180 | SYSMGR_A10_ISW_HANDOFF_BASE + SYSMGR_A10_ISW_HANDOFF_7); |
| 181 | else |
| 182 | writel(0, socfpga_get_sysmgr_addr() + |
| 183 | SYSMGR_A10_ISW_HANDOFF_BASE + SYSMGR_A10_ISW_HANDOFF_7); |
| 184 | } |
| 185 | |
| 186 | /* |
| 187 | * This function is used to check whether |
| 188 | * handoff register isw_handoff[7] contains |
| 189 | * magic number "0xd15ea5e". |
| 190 | */ |
| 191 | bool is_regular_boot_valid(void) |
| 192 | { |
| 193 | unsigned int status; |
| 194 | |
| 195 | status = readl(socfpga_get_sysmgr_addr() + |
| 196 | SYSMGR_A10_ISW_HANDOFF_BASE + SYSMGR_A10_ISW_HANDOFF_7); |
| 197 | |
| 198 | if (status == REGULAR_BOOT_MAGIC) |
| 199 | return true; |
| 200 | else |
| 201 | return false; |
| 202 | } |
| 203 | |
| 204 | #if IS_ENABLED(CONFIG_CADENCE_QSPI) |
| 205 | /* This function is used to trigger software reset |
| 206 | * to the QSPI flash. On some boards, the QSPI flash reset may |
| 207 | * not be connected to the HPS warm reset. |
| 208 | */ |
| 209 | int qspi_flash_software_reset(void) |
| 210 | { |
| 211 | struct udevice *flash; |
| 212 | int ret; |
| 213 | |
| 214 | /* Get the flash info */ |
| 215 | ret = spi_flash_probe_bus_cs(CONFIG_SF_DEFAULT_BUS, |
| 216 | CONFIG_SF_DEFAULT_CS, |
| 217 | CONFIG_SF_DEFAULT_SPEED, |
| 218 | CONFIG_SF_DEFAULT_MODE, |
| 219 | &flash); |
| 220 | |
| 221 | if (ret) { |
| 222 | debug("Failed to initialize SPI flash at "); |
| 223 | debug("%u:%u (error %d)\n", CONFIG_SF_DEFAULT_BUS, |
| 224 | CONFIG_SF_DEFAULT_CS, ret); |
| 225 | return -ENODEV; |
| 226 | } |
| 227 | |
| 228 | if (!flash) |
| 229 | return -EINVAL; |
| 230 | |
| 231 | /* |
| 232 | * QSPI flash software reset command, for the case where |
| 233 | * no HPS reset connected to QSPI flash reset |
| 234 | */ |
| 235 | if (!memcmp(flash->name, "N25", SZ_1 + SZ_2)) |
| 236 | writel(QSPI_N25_SOFT_RESET_COMMAND, socfpga_get_sysmgr_addr() + |
| 237 | SYSMGR_A10_ROMCODE_QSPIRESETCOMMAND); |
| 238 | else if (!memcmp(flash->name, "S25FL", SZ_1 + SZ_4)) |
| 239 | writel(QSPI_S25FL_SOFT_RESET_COMMAND, |
| 240 | socfpga_get_sysmgr_addr() + |
| 241 | SYSMGR_A10_ROMCODE_QSPIRESETCOMMAND); |
| 242 | else /* No software reset */ |
| 243 | writel(QSPI_NO_SOFT_RESET, socfpga_get_sysmgr_addr() + |
| 244 | SYSMGR_A10_ROMCODE_QSPIRESETCOMMAND); |
| 245 | |
| 246 | return 0; |
| 247 | } |
| 248 | #endif |
Paweł Anikiel | 9d4a5af | 2022-06-17 12:47:26 +0200 | [diff] [blame] | 249 | |
| 250 | void dram_bank_mmu_setup(int bank) |
| 251 | { |
| 252 | struct bd_info *bd = gd->bd; |
| 253 | u32 start, size; |
| 254 | int i; |
| 255 | |
| 256 | /* If we're still in OCRAM, don't set the XN bit on it */ |
| 257 | if (!(gd->flags & GD_FLG_RELOC)) { |
| 258 | set_section_dcache( |
Tom Rini | 6a5dccc | 2022-11-16 13:10:41 -0500 | [diff] [blame] | 259 | CFG_SYS_INIT_RAM_ADDR >> MMU_SECTION_SHIFT, |
Paweł Anikiel | 9d4a5af | 2022-06-17 12:47:26 +0200 | [diff] [blame] | 260 | DCACHE_WRITETHROUGH); |
| 261 | } |
| 262 | |
| 263 | /* |
| 264 | * The default implementation of this function allows the DRAM dcache |
| 265 | * to be enabled only after relocation. However, to speed up ECC |
| 266 | * initialization, we want to be able to enable DRAM dcache before |
| 267 | * relocation, so we don't check GD_FLG_RELOC (this assumes bd->bi_dram |
| 268 | * is set first). |
| 269 | */ |
| 270 | start = bd->bi_dram[bank].start >> MMU_SECTION_SHIFT; |
| 271 | size = bd->bi_dram[bank].size >> MMU_SECTION_SHIFT; |
| 272 | for (i = start; i < start + size; i++) |
| 273 | set_section_dcache(i, DCACHE_DEFAULT_OPTION); |
| 274 | } |