blob: 0f8b4d095d40271324cb57b548cb447a16bbe171 [file] [log] [blame]
Dinh Nguyenad51f7c2012-10-04 06:46:02 +00001/*
2 * Copyright (C) 2012 Altera Corporation <www.altera.com>
3 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02004 * SPDX-License-Identifier: GPL-2.0+
Dinh Nguyenad51f7c2012-10-04 06:46:02 +00005 */
6
7#include <common.h>
8#include <asm/io.h>
Pavel Machekc7213802014-09-08 14:08:45 +02009#include <altera.h>
Pavel Machekce340e92014-07-14 14:14:17 +020010#include <miiphy.h>
11#include <netdev.h>
Stefan Roese3bfb5912014-12-19 13:49:10 +010012#include <watchdog.h>
Pavel Machek56a00ab2014-09-09 14:03:28 +020013#include <asm/arch/reset_manager.h>
Pavel Machek57d75eb2014-09-08 14:08:45 +020014#include <asm/arch/system_manager.h>
Pavel Machek529d8a12014-09-08 14:08:45 +020015#include <asm/arch/dwmmc.h>
Marek Vasut56916e42014-09-15 03:58:22 +020016#include <asm/arch/nic301.h>
Pavel Macheke918e332014-09-08 14:08:45 +020017#include <asm/arch/scu.h>
Marek Vasut56916e42014-09-15 03:58:22 +020018#include <asm/pl310.h>
Dinh Nguyenad51f7c2012-10-04 06:46:02 +000019
20DECLARE_GLOBAL_DATA_PTR;
21
Marek Vasut56916e42014-09-15 03:58:22 +020022static struct pl310_regs *const pl310 =
23 (struct pl310_regs *)CONFIG_SYS_PL310_BASE;
Pavel Machek57d75eb2014-09-08 14:08:45 +020024static struct socfpga_system_manager *sysmgr_regs =
25 (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS;
Marek Vasut46fbdf62014-09-08 14:08:45 +020026static struct socfpga_reset_manager *reset_manager_base =
27 (struct socfpga_reset_manager *)SOCFPGA_RSTMGR_ADDRESS;
Marek Vasut56916e42014-09-15 03:58:22 +020028static struct nic301_registers *nic301_regs =
29 (struct nic301_registers *)SOCFPGA_L3REGS_ADDRESS;
Pavel Macheke918e332014-09-08 14:08:45 +020030static struct scu_registers *scu_regs =
31 (struct scu_registers *)SOCFPGA_MPUSCU_ADDRESS;
Pavel Machek57d75eb2014-09-08 14:08:45 +020032
Dinh Nguyenad51f7c2012-10-04 06:46:02 +000033int dram_init(void)
34{
35 gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
36 return 0;
37}
Pavel Machek57d75eb2014-09-08 14:08:45 +020038
Marek Vasutd5157942014-09-21 13:57:40 +020039void enable_caches(void)
40{
41#ifndef CONFIG_SYS_ICACHE_OFF
42 icache_enable();
43#endif
44#ifndef CONFIG_SYS_DCACHE_OFF
45 dcache_enable();
46#endif
47}
48
Pavel Machek57d75eb2014-09-08 14:08:45 +020049/*
50 * DesignWare Ethernet initialization
51 */
Simon Glass6e378742015-04-05 16:07:34 -060052#ifdef CONFIG_ETH_DESIGNWARE
Pavel Machek57d75eb2014-09-08 14:08:45 +020053int cpu_eth_init(bd_t *bis)
54{
55#if CONFIG_EMAC_BASE == SOCFPGA_EMAC0_ADDRESS
56 const int physhift = SYSMGR_EMACGRP_CTRL_PHYSEL0_LSB;
57#elif CONFIG_EMAC_BASE == SOCFPGA_EMAC1_ADDRESS
58 const int physhift = SYSMGR_EMACGRP_CTRL_PHYSEL1_LSB;
59#else
60#error "Incorrect CONFIG_EMAC_BASE value!"
61#endif
62
63 /* Initialize EMAC. This needs to be done at least once per boot. */
64
65 /*
66 * Putting the EMAC controller to reset when configuring the PHY
67 * interface select at System Manager
68 */
69 socfpga_emac_reset(1);
70
71 /* Clearing emac0 PHY interface select to 0 */
72 clrbits_le32(&sysmgr_regs->emacgrp_ctrl,
73 SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << physhift);
74
75 /* configure to PHY interface select choosed */
76 setbits_le32(&sysmgr_regs->emacgrp_ctrl,
77 SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII << physhift);
78
79 /* Release the EMAC controller from reset */
80 socfpga_emac_reset(0);
81
82 /* initialize and register the emac */
83 return designware_initialize(CONFIG_EMAC_BASE,
84 CONFIG_PHY_INTERFACE_MODE);
85}
86#endif
Chin Liang Seebff262c2014-06-10 02:23:45 -050087
Pavel Machek529d8a12014-09-08 14:08:45 +020088#ifdef CONFIG_DWMMC
89/*
90 * Initializes MMC controllers.
91 * to override, implement board_mmc_init()
92 */
93int cpu_mmc_init(bd_t *bis)
94{
95 return socfpga_dwmmc_init(SOCFPGA_SDMMC_ADDRESS,
96 CONFIG_HPS_SDMMC_BUSWIDTH, 0);
97}
98#endif
99
Chin Liang Seebff262c2014-06-10 02:23:45 -0500100#if defined(CONFIG_DISPLAY_CPUINFO)
101/*
102 * Print CPU information
103 */
104int print_cpuinfo(void)
105{
Pavel Machek2f983472014-09-08 14:08:45 +0200106 puts("CPU: Altera SoCFPGA Platform\n");
Chin Liang Seebff262c2014-06-10 02:23:45 -0500107 return 0;
108}
109#endif
110
111#if defined(CONFIG_SYS_CONSOLE_IS_IN_ENV) && \
112defined(CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE)
113int overwrite_console(void)
114{
115 return 0;
116}
117#endif
118
Pavel Machekc7213802014-09-08 14:08:45 +0200119#ifdef CONFIG_FPGA
120/*
121 * FPGA programming support for SoC FPGA Cyclone V
122 */
123static Altera_desc altera_fpga[] = {
124 {
125 /* Family */
126 Altera_SoCFPGA,
127 /* Interface type */
128 fast_passive_parallel,
129 /* No limitation as additional data will be ignored */
130 -1,
131 /* No device function table */
132 NULL,
133 /* Base interface address specified in driver */
134 NULL,
135 /* No cookie implementation */
136 0
137 },
138};
139
140/* add device descriptor to FPGA device table */
141static void socfpga_fpga_add(void)
142{
143 int i;
144 fpga_init();
145 for (i = 0; i < ARRAY_SIZE(altera_fpga); i++)
146 fpga_add(fpga_altera, &altera_fpga[i]);
147}
148#else
149static inline void socfpga_fpga_add(void) {}
150#endif
151
Pavel Machek56a00ab2014-09-09 14:03:28 +0200152int arch_cpu_init(void)
153{
Stefan Roese3bfb5912014-12-19 13:49:10 +0100154#ifdef CONFIG_HW_WATCHDOG
155 /*
156 * In case the watchdog is enabled, make sure to (re-)configure it
157 * so that the defined timeout is valid. Otherwise the SPL (Perloader)
158 * timeout value is still active which might too short for Linux
159 * booting.
160 */
161 hw_watchdog_init();
162#else
Pavel Machek56a00ab2014-09-09 14:03:28 +0200163 /*
164 * If the HW watchdog is NOT enabled, make sure it is not running,
165 * for example because it was enabled in the preloader. This might
166 * trigger a watchdog-triggered reboot of Linux kernel later.
167 */
Pavel Machek56a00ab2014-09-09 14:03:28 +0200168 socfpga_watchdog_reset();
169#endif
Stefan Roese3bfb5912014-12-19 13:49:10 +0100170
Pavel Machek56a00ab2014-09-09 14:03:28 +0200171 return 0;
172}
173
Pavel Macheke918e332014-09-08 14:08:45 +0200174/*
175 * Convert all NIC-301 AMBA slaves from secure to non-secure
176 */
177static void socfpga_nic301_slave_ns(void)
178{
179 writel(0x1, &nic301_regs->lwhps2fpgaregs);
180 writel(0x1, &nic301_regs->hps2fpgaregs);
181 writel(0x1, &nic301_regs->acp);
182 writel(0x1, &nic301_regs->rom);
183 writel(0x1, &nic301_regs->ocram);
184 writel(0x1, &nic301_regs->sdrdata);
185}
186
Marek Vasut46fbdf62014-09-08 14:08:45 +0200187static uint32_t iswgrp_handoff[8];
188
Marek Vasut54c282e2014-10-18 03:52:36 +0200189int arch_early_init_r(void)
Chin Liang Seebff262c2014-06-10 02:23:45 -0500190{
Marek Vasut46fbdf62014-09-08 14:08:45 +0200191 int i;
192 for (i = 0; i < 8; i++) /* Cache initial SW setting regs */
193 iswgrp_handoff[i] = readl(&sysmgr_regs->iswgrp_handoff[i]);
194
Pavel Macheke918e332014-09-08 14:08:45 +0200195 socfpga_bridges_reset(1);
196 socfpga_nic301_slave_ns();
197
198 /*
199 * Private components security:
200 * U-Boot : configure private timer, global timer and cpu component
201 * access as non secure for kernel stage (as required by Linux)
202 */
203 setbits_le32(&scu_regs->sacr, 0xfff);
204
Marek Vasut56916e42014-09-15 03:58:22 +0200205 /* Configure the L2 controller to make SDRAM start at 0 */
206#ifdef CONFIG_SOCFPGA_VIRTUAL_TARGET
207 writel(0x2, &nic301_regs->remap);
208#else
209 writel(0x1, &nic301_regs->remap); /* remap.mpuzero */
210 writel(0x1, &pl310->pl310_addr_filter_start);
211#endif
212
Pavel Machekc7213802014-09-08 14:08:45 +0200213 /* Add device descriptor to FPGA device table */
214 socfpga_fpga_add();
Stefan Roeseca6b8fb2014-11-07 13:50:30 +0100215
216#ifdef CONFIG_DESIGNWARE_SPI
217 /* Get Designware SPI controller out of reset */
218 socfpga_spim_enable();
219#endif
220
Chin Liang Seebff262c2014-06-10 02:23:45 -0500221 return 0;
222}
Marek Vasut46fbdf62014-09-08 14:08:45 +0200223
224static void socfpga_sdram_apply_static_cfg(void)
225{
226 const uint32_t staticcfg = SOCFPGA_SDR_ADDRESS + 0x505c;
227 const uint32_t applymask = 0x8;
228 uint32_t val = readl(staticcfg) | applymask;
229
230 /*
231 * SDRAM staticcfg register specific:
232 * When applying the register setting, the CPU must not access
233 * SDRAM. Luckily for us, we can abuse i-cache here to help us
234 * circumvent the SDRAM access issue. The idea is to make sure
235 * that the code is in one full i-cache line by branching past
236 * it and back. Once it is in the i-cache, we execute the core
237 * of the code and apply the register settings.
238 *
239 * The code below uses 7 instructions, while the Cortex-A9 has
240 * 32-byte cachelines, thus the limit is 8 instructions total.
241 */
242 asm volatile(
243 ".align 5 \n"
244 " b 2f \n"
245 "1: str %0, [%1] \n"
246 " dsb \n"
247 " isb \n"
248 " b 3f \n"
249 "2: b 1b \n"
250 "3: nop \n"
251 : : "r"(val), "r"(staticcfg) : "memory", "cc");
252}
253
254int do_bridge(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
255{
256 if (argc != 2)
257 return CMD_RET_USAGE;
258
259 argv++;
260
261 switch (*argv[0]) {
262 case 'e': /* Enable */
263 writel(iswgrp_handoff[2], &sysmgr_regs->fpgaintfgrp_module);
264 socfpga_sdram_apply_static_cfg();
265 writel(iswgrp_handoff[3], SOCFPGA_SDR_ADDRESS + 0x5080);
266 writel(iswgrp_handoff[0], &reset_manager_base->brg_mod_reset);
267 writel(iswgrp_handoff[1], &nic301_regs->remap);
268 break;
269 case 'd': /* Disable */
270 writel(0, &sysmgr_regs->fpgaintfgrp_module);
271 writel(0, SOCFPGA_SDR_ADDRESS + 0x5080);
272 socfpga_sdram_apply_static_cfg();
273 writel(0, &reset_manager_base->brg_mod_reset);
274 writel(1, &nic301_regs->remap);
275 break;
276 default:
277 return CMD_RET_USAGE;
278 }
279
280 return 0;
281}
282
283U_BOOT_CMD(
284 bridge, 2, 1, do_bridge,
285 "SoCFPGA HPS FPGA bridge control",
286 "enable - Enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges\n"
287 "bridge disable - Enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges\n"
288 ""
289);