blob: f617e88df1aaede02ab3344dd5d3deb8ce09dc66 [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>
Marek Vasutf3f8fe22015-07-25 19:33:56 +02009#include <fdtdec.h>
10#include <libfdt.h>
Pavel Machekc7213802014-09-08 14:08:45 +020011#include <altera.h>
Pavel Machekce340e92014-07-14 14:14:17 +020012#include <miiphy.h>
13#include <netdev.h>
Stefan Roese3bfb5912014-12-19 13:49:10 +010014#include <watchdog.h>
Pavel Machek56a00ab2014-09-09 14:03:28 +020015#include <asm/arch/reset_manager.h>
Pavel Machek57d75eb2014-09-08 14:08:45 +020016#include <asm/arch/system_manager.h>
Pavel Machek529d8a12014-09-08 14:08:45 +020017#include <asm/arch/dwmmc.h>
Marek Vasut56916e42014-09-15 03:58:22 +020018#include <asm/arch/nic301.h>
Pavel Macheke918e332014-09-08 14:08:45 +020019#include <asm/arch/scu.h>
Marek Vasut56916e42014-09-15 03:58:22 +020020#include <asm/pl310.h>
Dinh Nguyenad51f7c2012-10-04 06:46:02 +000021
Marek Vasutf3f8fe22015-07-25 19:33:56 +020022#include <dt-bindings/reset/altr,rst-mgr.h>
23
Dinh Nguyenad51f7c2012-10-04 06:46:02 +000024DECLARE_GLOBAL_DATA_PTR;
25
Marek Vasut56916e42014-09-15 03:58:22 +020026static struct pl310_regs *const pl310 =
27 (struct pl310_regs *)CONFIG_SYS_PL310_BASE;
Pavel Machek57d75eb2014-09-08 14:08:45 +020028static struct socfpga_system_manager *sysmgr_regs =
29 (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS;
Marek Vasut46fbdf62014-09-08 14:08:45 +020030static struct socfpga_reset_manager *reset_manager_base =
31 (struct socfpga_reset_manager *)SOCFPGA_RSTMGR_ADDRESS;
Marek Vasut56916e42014-09-15 03:58:22 +020032static struct nic301_registers *nic301_regs =
33 (struct nic301_registers *)SOCFPGA_L3REGS_ADDRESS;
Pavel Macheke918e332014-09-08 14:08:45 +020034static struct scu_registers *scu_regs =
35 (struct scu_registers *)SOCFPGA_MPUSCU_ADDRESS;
Pavel Machek57d75eb2014-09-08 14:08:45 +020036
Dinh Nguyenad51f7c2012-10-04 06:46:02 +000037int dram_init(void)
38{
39 gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
40 return 0;
41}
Pavel Machek57d75eb2014-09-08 14:08:45 +020042
Marek Vasutd5157942014-09-21 13:57:40 +020043void enable_caches(void)
44{
45#ifndef CONFIG_SYS_ICACHE_OFF
46 icache_enable();
47#endif
48#ifndef CONFIG_SYS_DCACHE_OFF
49 dcache_enable();
50#endif
51}
52
Pavel Machek57d75eb2014-09-08 14:08:45 +020053/*
54 * DesignWare Ethernet initialization
55 */
Simon Glass6e378742015-04-05 16:07:34 -060056#ifdef CONFIG_ETH_DESIGNWARE
Marek Vasutf3f8fe22015-07-25 19:33:56 +020057static void dwmac_deassert_reset(const unsigned int of_reset_id)
Pavel Machek57d75eb2014-09-08 14:08:45 +020058{
Marek Vasutf3f8fe22015-07-25 19:33:56 +020059 u32 physhift, reset;
Pavel Machek57d75eb2014-09-08 14:08:45 +020060
Marek Vasutf3f8fe22015-07-25 19:33:56 +020061 if (of_reset_id == EMAC0_RESET) {
62 physhift = SYSMGR_EMACGRP_CTRL_PHYSEL0_LSB;
63 reset = SOCFPGA_RESET(EMAC0);
64 } else if (of_reset_id == EMAC1_RESET) {
65 physhift = SYSMGR_EMACGRP_CTRL_PHYSEL1_LSB;
66 reset = SOCFPGA_RESET(EMAC1);
67 } else {
68 printf("GMAC: Invalid reset ID (%i)!\n", of_reset_id);
69 return;
70 }
Pavel Machek57d75eb2014-09-08 14:08:45 +020071
72 /* Clearing emac0 PHY interface select to 0 */
73 clrbits_le32(&sysmgr_regs->emacgrp_ctrl,
74 SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << physhift);
75
76 /* configure to PHY interface select choosed */
77 setbits_le32(&sysmgr_regs->emacgrp_ctrl,
78 SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII << physhift);
79
80 /* Release the EMAC controller from reset */
Marek Vasut75f6b5c2015-07-09 02:51:56 +020081 socfpga_per_reset(reset, 0);
Marek Vasutf3f8fe22015-07-25 19:33:56 +020082}
83
84int cpu_eth_init(bd_t *bis)
85{
86 const void *fdt = gd->fdt_blob;
87 struct fdtdec_phandle_args args;
88 int nodes[2]; /* Max. two GMACs */
89 int ret, count;
90 int i, node;
91
92 /* Put both GMACs into RESET state. */
93 socfpga_per_reset(SOCFPGA_RESET(EMAC0), 1);
94 socfpga_per_reset(SOCFPGA_RESET(EMAC1), 1);
95
96 count = fdtdec_find_aliases_for_id(fdt, "ethernet",
97 COMPAT_ALTERA_SOCFPGA_DWMAC,
98 nodes, ARRAY_SIZE(nodes));
99 for (i = 0; i < count; i++) {
100 node = nodes[i];
101 if (node <= 0)
102 continue;
103
104 ret = fdtdec_parse_phandle_with_args(fdt, node, "resets",
105 "#reset-cells", 1, 0,
106 &args);
107 if (ret || (args.args_count != 1)) {
108 debug("GMAC%i: Failed to parse DT 'resets'!\n", i);
109 continue;
110 }
111
112 dwmac_deassert_reset(args.args[0]);
113 }
Pavel Machek57d75eb2014-09-08 14:08:45 +0200114
Marek Vasut5ca99542015-07-25 18:47:02 +0200115 return 0;
Pavel Machek57d75eb2014-09-08 14:08:45 +0200116}
117#endif
Chin Liang Seebff262c2014-06-10 02:23:45 -0500118
Pavel Machek529d8a12014-09-08 14:08:45 +0200119#ifdef CONFIG_DWMMC
120/*
121 * Initializes MMC controllers.
122 * to override, implement board_mmc_init()
123 */
124int cpu_mmc_init(bd_t *bis)
125{
Marek Vasut7b7ebdf2015-08-03 18:31:51 +0200126/*
127 * FIXME: Temporarily define CONFIG_HPS_SDMMC_BUSWIDTH to prevent breakage
128 * due to missing patches in u-boot/master . The upcoming patch will
129 * switch this to OF probing, so this whole block will go away.
130 */
131#define CONFIG_HPS_SDMMC_BUSWIDTH 8
Pavel Machek529d8a12014-09-08 14:08:45 +0200132 return socfpga_dwmmc_init(SOCFPGA_SDMMC_ADDRESS,
133 CONFIG_HPS_SDMMC_BUSWIDTH, 0);
134}
135#endif
136
Marek Vasutdc495ae2015-07-22 05:40:12 +0200137struct {
138 const char *mode;
139 const char *name;
140} bsel_str[] = {
141 { "rsvd", "Reserved", },
142 { "fpga", "FPGA (HPS2FPGA Bridge)", },
143 { "nand", "NAND Flash (1.8V)", },
144 { "nand", "NAND Flash (3.0V)", },
145 { "sd", "SD/MMC External Transceiver (1.8V)", },
146 { "sd", "SD/MMC Internal Transceiver (3.0V)", },
147 { "qspi", "QSPI Flash (1.8V)", },
148 { "qspi", "QSPI Flash (3.0V)", },
Marek Vasutf5688652015-07-21 16:10:13 +0200149};
150
Chin Liang Seebff262c2014-06-10 02:23:45 -0500151/*
152 * Print CPU information
153 */
Marek Vasutdc495ae2015-07-22 05:40:12 +0200154#if defined(CONFIG_DISPLAY_CPUINFO)
Chin Liang Seebff262c2014-06-10 02:23:45 -0500155int print_cpuinfo(void)
156{
Marek Vasutf5688652015-07-21 16:10:13 +0200157 const u32 bsel = readl(&sysmgr_regs->bootinfo) & 0x7;
Pavel Machek2f983472014-09-08 14:08:45 +0200158 puts("CPU: Altera SoCFPGA Platform\n");
Marek Vasutdc495ae2015-07-22 05:40:12 +0200159 printf("BOOT: %s\n", bsel_str[bsel].name);
160 return 0;
161}
162#endif
163
164#ifdef CONFIG_ARCH_MISC_INIT
165int arch_misc_init(void)
166{
167 const u32 bsel = readl(&sysmgr_regs->bootinfo) & 0x7;
168 setenv("bootmode", bsel_str[bsel].mode);
Chin Liang Seebff262c2014-06-10 02:23:45 -0500169 return 0;
170}
171#endif
172
173#if defined(CONFIG_SYS_CONSOLE_IS_IN_ENV) && \
174defined(CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE)
175int overwrite_console(void)
176{
177 return 0;
178}
179#endif
180
Pavel Machekc7213802014-09-08 14:08:45 +0200181#ifdef CONFIG_FPGA
182/*
183 * FPGA programming support for SoC FPGA Cyclone V
184 */
185static Altera_desc altera_fpga[] = {
186 {
187 /* Family */
188 Altera_SoCFPGA,
189 /* Interface type */
190 fast_passive_parallel,
191 /* No limitation as additional data will be ignored */
192 -1,
193 /* No device function table */
194 NULL,
195 /* Base interface address specified in driver */
196 NULL,
197 /* No cookie implementation */
198 0
199 },
200};
201
202/* add device descriptor to FPGA device table */
203static void socfpga_fpga_add(void)
204{
205 int i;
206 fpga_init();
207 for (i = 0; i < ARRAY_SIZE(altera_fpga); i++)
208 fpga_add(fpga_altera, &altera_fpga[i]);
209}
210#else
211static inline void socfpga_fpga_add(void) {}
212#endif
213
Pavel Machek56a00ab2014-09-09 14:03:28 +0200214int arch_cpu_init(void)
215{
Stefan Roese3bfb5912014-12-19 13:49:10 +0100216#ifdef CONFIG_HW_WATCHDOG
217 /*
218 * In case the watchdog is enabled, make sure to (re-)configure it
219 * so that the defined timeout is valid. Otherwise the SPL (Perloader)
220 * timeout value is still active which might too short for Linux
221 * booting.
222 */
223 hw_watchdog_init();
224#else
Pavel Machek56a00ab2014-09-09 14:03:28 +0200225 /*
226 * If the HW watchdog is NOT enabled, make sure it is not running,
227 * for example because it was enabled in the preloader. This might
228 * trigger a watchdog-triggered reboot of Linux kernel later.
Marek Vasut75f6b5c2015-07-09 02:51:56 +0200229 * Toggle watchdog reset, so watchdog in not running state.
Pavel Machek56a00ab2014-09-09 14:03:28 +0200230 */
Marek Vasut75f6b5c2015-07-09 02:51:56 +0200231 socfpga_per_reset(SOCFPGA_RESET(L4WD0), 1);
232 socfpga_per_reset(SOCFPGA_RESET(L4WD0), 0);
Pavel Machek56a00ab2014-09-09 14:03:28 +0200233#endif
Stefan Roese3bfb5912014-12-19 13:49:10 +0100234
Pavel Machek56a00ab2014-09-09 14:03:28 +0200235 return 0;
236}
237
Pavel Macheke918e332014-09-08 14:08:45 +0200238/*
239 * Convert all NIC-301 AMBA slaves from secure to non-secure
240 */
241static void socfpga_nic301_slave_ns(void)
242{
243 writel(0x1, &nic301_regs->lwhps2fpgaregs);
244 writel(0x1, &nic301_regs->hps2fpgaregs);
245 writel(0x1, &nic301_regs->acp);
246 writel(0x1, &nic301_regs->rom);
247 writel(0x1, &nic301_regs->ocram);
248 writel(0x1, &nic301_regs->sdrdata);
249}
250
Marek Vasut46fbdf62014-09-08 14:08:45 +0200251static uint32_t iswgrp_handoff[8];
252
Marek Vasut54c282e2014-10-18 03:52:36 +0200253int arch_early_init_r(void)
Chin Liang Seebff262c2014-06-10 02:23:45 -0500254{
Marek Vasut46fbdf62014-09-08 14:08:45 +0200255 int i;
Marek Vasutb7e77382015-07-12 15:11:03 +0200256
257 /*
258 * Write magic value into magic register to unlock support for
259 * issuing warm reset. The ancient kernel code expects this
260 * value to be written into the register by the bootloader, so
261 * to support that old code, we write it here instead of in the
262 * reset_cpu() function just before reseting the CPU.
263 */
264 writel(0xae9efebc, &sysmgr_regs->romcodegrp_warmramgrp_enable);
265
Marek Vasut46fbdf62014-09-08 14:08:45 +0200266 for (i = 0; i < 8; i++) /* Cache initial SW setting regs */
267 iswgrp_handoff[i] = readl(&sysmgr_regs->iswgrp_handoff[i]);
268
Pavel Macheke918e332014-09-08 14:08:45 +0200269 socfpga_bridges_reset(1);
270 socfpga_nic301_slave_ns();
271
272 /*
273 * Private components security:
274 * U-Boot : configure private timer, global timer and cpu component
275 * access as non secure for kernel stage (as required by Linux)
276 */
277 setbits_le32(&scu_regs->sacr, 0xfff);
278
Marek Vasut56916e42014-09-15 03:58:22 +0200279 /* Configure the L2 controller to make SDRAM start at 0 */
280#ifdef CONFIG_SOCFPGA_VIRTUAL_TARGET
281 writel(0x2, &nic301_regs->remap);
282#else
283 writel(0x1, &nic301_regs->remap); /* remap.mpuzero */
284 writel(0x1, &pl310->pl310_addr_filter_start);
285#endif
286
Pavel Machekc7213802014-09-08 14:08:45 +0200287 /* Add device descriptor to FPGA device table */
288 socfpga_fpga_add();
Stefan Roeseca6b8fb2014-11-07 13:50:30 +0100289
290#ifdef CONFIG_DESIGNWARE_SPI
291 /* Get Designware SPI controller out of reset */
Marek Vasut75f6b5c2015-07-09 02:51:56 +0200292 socfpga_per_reset(SOCFPGA_RESET(SPIM0), 0);
293 socfpga_per_reset(SOCFPGA_RESET(SPIM1), 0);
Stefan Roeseca6b8fb2014-11-07 13:50:30 +0100294#endif
295
Chin Liang Seebff262c2014-06-10 02:23:45 -0500296 return 0;
297}
Marek Vasut46fbdf62014-09-08 14:08:45 +0200298
299static void socfpga_sdram_apply_static_cfg(void)
300{
301 const uint32_t staticcfg = SOCFPGA_SDR_ADDRESS + 0x505c;
302 const uint32_t applymask = 0x8;
303 uint32_t val = readl(staticcfg) | applymask;
304
305 /*
306 * SDRAM staticcfg register specific:
307 * When applying the register setting, the CPU must not access
308 * SDRAM. Luckily for us, we can abuse i-cache here to help us
309 * circumvent the SDRAM access issue. The idea is to make sure
310 * that the code is in one full i-cache line by branching past
311 * it and back. Once it is in the i-cache, we execute the core
312 * of the code and apply the register settings.
313 *
314 * The code below uses 7 instructions, while the Cortex-A9 has
315 * 32-byte cachelines, thus the limit is 8 instructions total.
316 */
317 asm volatile(
318 ".align 5 \n"
319 " b 2f \n"
320 "1: str %0, [%1] \n"
321 " dsb \n"
322 " isb \n"
323 " b 3f \n"
324 "2: b 1b \n"
325 "3: nop \n"
326 : : "r"(val), "r"(staticcfg) : "memory", "cc");
327}
328
329int do_bridge(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
330{
331 if (argc != 2)
332 return CMD_RET_USAGE;
333
334 argv++;
335
336 switch (*argv[0]) {
337 case 'e': /* Enable */
338 writel(iswgrp_handoff[2], &sysmgr_regs->fpgaintfgrp_module);
339 socfpga_sdram_apply_static_cfg();
340 writel(iswgrp_handoff[3], SOCFPGA_SDR_ADDRESS + 0x5080);
341 writel(iswgrp_handoff[0], &reset_manager_base->brg_mod_reset);
342 writel(iswgrp_handoff[1], &nic301_regs->remap);
343 break;
344 case 'd': /* Disable */
345 writel(0, &sysmgr_regs->fpgaintfgrp_module);
346 writel(0, SOCFPGA_SDR_ADDRESS + 0x5080);
347 socfpga_sdram_apply_static_cfg();
348 writel(0, &reset_manager_base->brg_mod_reset);
349 writel(1, &nic301_regs->remap);
350 break;
351 default:
352 return CMD_RET_USAGE;
353 }
354
355 return 0;
356}
357
358U_BOOT_CMD(
359 bridge, 2, 1, do_bridge,
360 "SoCFPGA HPS FPGA bridge control",
361 "enable - Enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges\n"
362 "bridge disable - Enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges\n"
363 ""
364);