blob: 97e01140513aa3267bde70135cb12bef32aeb7a5 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Dinh Nguyenad51f7c2012-10-04 06:46:02 +00002/*
Alif Zakuan Yuslaimi73300f62025-02-18 16:34:47 +08003 * Copyright (C) 2012-2025 Altera Corporation <www.altera.com>
Dinh Nguyenad51f7c2012-10-04 06:46:02 +00004 */
5
Tom Rinidec7ea02024-05-20 13:35:03 -06006#include <config.h>
Simon Glassed38aef2020-05-10 11:40:03 -06007#include <command.h>
Dinh Nguyen8ed66612015-08-01 03:42:10 +02008#include <errno.h>
Tingting Menga1a24f12025-02-21 21:49:41 +08009#include <init.h>
10#include <handoff.h>
11#include <hang.h>
12#include <watchdog.h>
Marek Vasutf3f8fe22015-07-25 19:33:56 +020013#include <fdtdec.h>
Masahiro Yamada75f82d02018-03-05 01:20:11 +090014#include <linux/libfdt.h>
Tingting Menga1a24f12025-02-21 21:49:41 +080015#include <linux/printk.h>
Pavel Machekce340e92014-07-14 14:14:17 +020016#include <miiphy.h>
17#include <netdev.h>
Tingting Menga1a24f12025-02-21 21:49:41 +080018#include <asm/global_data.h>
19#include <asm/io.h>
20#include <asm/cache.h>
21#include <asm/pl310.h>
Ley Foon Tanb149f2b2017-04-26 02:44:36 +080022#include <asm/arch/misc.h>
Tingting Menga1a24f12025-02-21 21:49:41 +080023#include <asm/arch/nic301.h>
Pavel Machek56a00ab2014-09-09 14:03:28 +020024#include <asm/arch/reset_manager.h>
Dinh Nguyen8ed66612015-08-01 03:42:10 +020025#include <asm/arch/scan_manager.h>
Pavel Macheke918e332014-09-08 14:08:45 +020026#include <asm/arch/scu.h>
Tingting Menga1a24f12025-02-21 21:49:41 +080027#include <asm/arch/system_manager.h>
28#include <altera.h>
29#include <bloblist.h>
30#include <cpu_func.h>
Dinh Nguyenad51f7c2012-10-04 06:46:02 +000031
32DECLARE_GLOBAL_DATA_PTR;
33
Ley Foon Tan26695912019-11-08 10:38:21 +080034phys_addr_t socfpga_clkmgr_base __section(".data");
Ley Foon Tanfed4c952019-11-08 10:38:19 +080035phys_addr_t socfpga_rstmgr_base __section(".data");
Ley Foon Tan3d3a8602019-11-08 10:38:20 +080036phys_addr_t socfpga_sysmgr_base __section(".data");
Ley Foon Tanfed4c952019-11-08 10:38:19 +080037
Ley Foon Tan6fa091d2018-05-18 22:05:25 +080038#ifdef CONFIG_SYS_L2_PL310
Ley Foon Tanb149f2b2017-04-26 02:44:36 +080039static const struct pl310_regs *const pl310 =
Tom Rini6a5dccc2022-11-16 13:10:41 -050040 (struct pl310_regs *)CFG_SYS_PL310_BASE;
Ley Foon Tan6fa091d2018-05-18 22:05:25 +080041#endif
Ley Foon Tanb149f2b2017-04-26 02:44:36 +080042
43struct bsel bsel_str[] = {
44 { "rsvd", "Reserved", },
45 { "fpga", "FPGA (HPS2FPGA Bridge)", },
46 { "nand", "NAND Flash (1.8V)", },
47 { "nand", "NAND Flash (3.0V)", },
48 { "sd", "SD/MMC External Transceiver (1.8V)", },
49 { "sd", "SD/MMC Internal Transceiver (3.0V)", },
50 { "qspi", "QSPI Flash (1.8V)", },
51 { "qspi", "QSPI Flash (3.0V)", },
52};
Pavel Machek57d75eb2014-09-08 14:08:45 +020053
Dinh Nguyenad51f7c2012-10-04 06:46:02 +000054int dram_init(void)
55{
Tingting Menga1a24f12025-02-21 21:49:41 +080056#if CONFIG_IS_ENABLED(HANDOFF) && IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5)
57 struct spl_handoff *ho;
58
59 ho = bloblist_find(BLOBLISTT_U_BOOT_SPL_HANDOFF, sizeof(*ho));
60 if (!ho)
61 return log_msg_ret("Missing SPL hand-off info", -ENOENT);
62 gd->ram_size = ho->ram_bank[0].size;
63 gd->ram_base = ho->ram_bank[0].start;
64#else
Siva Durga Prasad Paladugub3d55ea2018-07-16 15:56:11 +053065 if (fdtdec_setup_mem_size_base() != 0)
Marek Vasut15303172018-05-28 17:09:45 +020066 return -EINVAL;
Tingting Menga1a24f12025-02-21 21:49:41 +080067#endif /* HANDOFF && CONFIG_TARGET_SOCFPGA_AGILEX5 */
Marek Vasut15303172018-05-28 17:09:45 +020068
Dinh Nguyenad51f7c2012-10-04 06:46:02 +000069 return 0;
70}
Pavel Machek57d75eb2014-09-08 14:08:45 +020071
Marek Vasutd5157942014-09-21 13:57:40 +020072void enable_caches(void)
73{
Trevor Woerner43ec7e02019-05-03 09:41:00 -040074#if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
Marek Vasutd5157942014-09-21 13:57:40 +020075 icache_enable();
76#endif
Trevor Woerner43ec7e02019-05-03 09:41:00 -040077#if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
Marek Vasutd5157942014-09-21 13:57:40 +020078 dcache_enable();
79#endif
80}
81
Ley Foon Tan6fa091d2018-05-18 22:05:25 +080082#ifdef CONFIG_SYS_L2_PL310
Dinh Nguyene89ff702015-10-15 10:13:36 -050083void v7_outer_cache_enable(void)
84{
Dinh Nguyen86fbf9d2019-04-23 16:55:05 -050085 struct udevice *dev;
Marek Vasut9f7b30d2015-12-20 04:00:09 +010086
Dinh Nguyen86fbf9d2019-04-23 16:55:05 -050087 if (uclass_get_device(UCLASS_CACHE, 0, &dev))
88 pr_err("cache controller driver NOT found!\n");
Marek Vasut9f7b30d2015-12-20 04:00:09 +010089}
90
91void v7_outer_cache_disable(void)
92{
93 /* Disable the L2 cache */
94 clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN);
Dinh Nguyene89ff702015-10-15 10:13:36 -050095}
Marek Vasutb6ba4902019-03-21 23:05:38 +010096
97void socfpga_pl310_clear(void)
98{
99 u32 mask = 0xff, ena = 0;
100
101 icache_enable();
102
103 /* Disable the L2 cache */
104 clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN);
105
106 writel(0x0, &pl310->pl310_tag_latency_ctrl);
107 writel(0x10, &pl310->pl310_data_latency_ctrl);
108
109 /* enable BRESP, instruction and data prefetch, full line of zeroes */
110 setbits_le32(&pl310->pl310_aux_ctrl,
111 L310_AUX_CTRL_DATA_PREFETCH_MASK |
112 L310_AUX_CTRL_INST_PREFETCH_MASK |
113 L310_SHARED_ATT_OVERRIDE_ENABLE);
114
115 /* Enable the L2 cache */
116 ena = readl(&pl310->pl310_ctrl);
117 ena |= L2X0_CTRL_EN;
118
119 /*
120 * Invalidate the PL310 L2 cache. Keep the invalidation code
121 * entirely in L1 I-cache to avoid any bus traffic through
122 * the L2.
123 */
124 asm volatile(
125 ".align 5 \n"
126 " b 3f \n"
127 "1: str %1, [%4] \n"
128 " dsb \n"
129 " isb \n"
130 " str %0, [%2] \n"
131 " dsb \n"
132 " isb \n"
133 "2: ldr %0, [%2] \n"
134 " cmp %0, #0 \n"
135 " bne 2b \n"
136 " str %0, [%3] \n"
137 " dsb \n"
138 " isb \n"
139 " b 4f \n"
140 "3: b 1b \n"
141 "4: nop \n"
142 : "+r"(mask), "+r"(ena)
143 : "r"(&pl310->pl310_inv_way),
144 "r"(&pl310->pl310_cache_sync), "r"(&pl310->pl310_ctrl)
145 : "memory", "cc");
146
147 /* Disable the L2 cache */
148 clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN);
149}
Ley Foon Tan6fa091d2018-05-18 22:05:25 +0800150#endif
Dinh Nguyene89ff702015-10-15 10:13:36 -0500151
Chin Liang Seebff262c2014-06-10 02:23:45 -0500152#if defined(CONFIG_SYS_CONSOLE_IS_IN_ENV) && \
153defined(CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE)
154int overwrite_console(void)
155{
156 return 0;
157}
158#endif
159
Pavel Machekc7213802014-09-08 14:08:45 +0200160#ifdef CONFIG_FPGA
Pavel Machekc7213802014-09-08 14:08:45 +0200161/* add device descriptor to FPGA device table */
Ang, Chee Hongff14f162018-12-19 18:35:15 -0800162void socfpga_fpga_add(void *fpga_desc)
Pavel Machekc7213802014-09-08 14:08:45 +0200163{
Pavel Machekc7213802014-09-08 14:08:45 +0200164 fpga_init();
Ang, Chee Hongff14f162018-12-19 18:35:15 -0800165 fpga_add(fpga_altera, fpga_desc);
Pavel Machekc7213802014-09-08 14:08:45 +0200166}
Pavel Machekc7213802014-09-08 14:08:45 +0200167#endif
168
Pavel Machek56a00ab2014-09-09 14:03:28 +0200169int arch_cpu_init(void)
170{
Ley Foon Tanfed4c952019-11-08 10:38:19 +0800171 socfpga_get_managers_addr();
172
Stefan Roese3bfb5912014-12-19 13:49:10 +0100173#ifdef CONFIG_HW_WATCHDOG
174 /*
175 * In case the watchdog is enabled, make sure to (re-)configure it
176 * so that the defined timeout is valid. Otherwise the SPL (Perloader)
177 * timeout value is still active which might too short for Linux
178 * booting.
179 */
180 hw_watchdog_init();
181#else
Pavel Machek56a00ab2014-09-09 14:03:28 +0200182 /*
183 * If the HW watchdog is NOT enabled, make sure it is not running,
184 * for example because it was enabled in the preloader. This might
185 * trigger a watchdog-triggered reboot of Linux kernel later.
Marek Vasut75f6b5c2015-07-09 02:51:56 +0200186 * Toggle watchdog reset, so watchdog in not running state.
Pavel Machek56a00ab2014-09-09 14:03:28 +0200187 */
Marek Vasut75f6b5c2015-07-09 02:51:56 +0200188 socfpga_per_reset(SOCFPGA_RESET(L4WD0), 1);
189 socfpga_per_reset(SOCFPGA_RESET(L4WD0), 0);
Pavel Machek56a00ab2014-09-09 14:03:28 +0200190#endif
Stefan Roese3bfb5912014-12-19 13:49:10 +0100191
Pavel Machek56a00ab2014-09-09 14:03:28 +0200192 return 0;
193}
Marek Vasut3386c852018-04-23 22:49:31 +0200194
Simon Glass85ed77d2024-09-29 19:49:46 -0600195#ifndef CONFIG_XPL_BUILD
Simon Glassed38aef2020-05-10 11:40:03 -0600196static int do_bridge(struct cmd_tbl *cmdtp, int flag, int argc,
197 char *const argv[])
Ley Foon Tan4cc6b582018-05-24 00:17:23 +0800198{
Marek Vasut713a8a22019-04-16 22:28:08 +0200199 unsigned int mask = ~0;
200
201 if (argc < 2 || argc > 3)
Ley Foon Tan4cc6b582018-05-24 00:17:23 +0800202 return CMD_RET_USAGE;
203
204 argv++;
205
Marek Vasut713a8a22019-04-16 22:28:08 +0200206 if (argc == 3)
Simon Glass3ff49ec2021-07-24 09:03:29 -0600207 mask = hextoul(argv[1], NULL);
Marek Vasut713a8a22019-04-16 22:28:08 +0200208
Ley Foon Tan4cc6b582018-05-24 00:17:23 +0800209 switch (*argv[0]) {
210 case 'e': /* Enable */
Marek Vasut713a8a22019-04-16 22:28:08 +0200211 do_bridge_reset(1, mask);
Ley Foon Tan4cc6b582018-05-24 00:17:23 +0800212 break;
213 case 'd': /* Disable */
Marek Vasut713a8a22019-04-16 22:28:08 +0200214 do_bridge_reset(0, mask);
Ley Foon Tan4cc6b582018-05-24 00:17:23 +0800215 break;
216 default:
217 return CMD_RET_USAGE;
218 }
219
220 return 0;
221}
222
Marek Vasut713a8a22019-04-16 22:28:08 +0200223U_BOOT_CMD(bridge, 3, 1, do_bridge,
Ley Foon Tanf9c7f792018-05-24 00:17:30 +0800224 "SoCFPGA HPS FPGA bridge control",
Marek Vasut713a8a22019-04-16 22:28:08 +0200225 "enable [mask] - Enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges\n"
226 "bridge disable [mask] - Enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges\n"
Ley Foon Tanf9c7f792018-05-24 00:17:30 +0800227 ""
Ley Foon Tan4cc6b582018-05-24 00:17:23 +0800228);
229
230#endif
Ley Foon Tanfed4c952019-11-08 10:38:19 +0800231
232static int socfpga_get_base_addr(const char *compat, phys_addr_t *base)
233{
234 const void *blob = gd->fdt_blob;
235 struct fdt_resource r;
236 int node;
237 int ret;
238
239 node = fdt_node_offset_by_compatible(blob, -1, compat);
240 if (node < 0)
241 return node;
242
243 if (!fdtdec_get_is_enabled(blob, node))
244 return -ENODEV;
245
246 ret = fdt_get_resource(blob, node, "reg", 0, &r);
247 if (ret)
248 return ret;
249
250 *base = (phys_addr_t)r.start;
251
252 return 0;
253}
254
255void socfpga_get_managers_addr(void)
256{
257 int ret;
258
259 ret = socfpga_get_base_addr("altr,rst-mgr", &socfpga_rstmgr_base);
260 if (ret)
261 hang();
Ley Foon Tan3d3a8602019-11-08 10:38:20 +0800262
Alif Zakuan Yuslaimi73300f62025-02-18 16:34:47 +0800263 if (IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX))
264 ret = socfpga_get_base_addr("intel,agilex-clkmgr",
265 &socfpga_clkmgr_base);
266 else if (IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X))
267 ret = socfpga_get_base_addr("intel,n5x-clkmgr",
268 &socfpga_clkmgr_base);
269 else if (!IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5))
270 ret = socfpga_get_base_addr("altr,clk-mgr",
271 &socfpga_clkmgr_base);
272
Ley Foon Tan26695912019-11-08 10:38:21 +0800273 if (ret)
274 hang();
Ley Foon Tanfed4c952019-11-08 10:38:19 +0800275}
276
Tien Fong Chee3a07a2c2024-09-18 16:43:02 +0800277void socfpga_get_sys_mgr_addr(const char *compat)
278{
279 int ret;
280 struct udevice *sysmgr_dev;
281
282 ret = uclass_get_device_by_name(UCLASS_NOP, compat, &sysmgr_dev);
283 if (ret) {
284 printf("Altera system manager init failed: %d\n", ret);
285 hang();
286 } else {
287 socfpga_sysmgr_base = (phys_addr_t)dev_read_addr(sysmgr_dev);
288 }
289}
290
Ley Foon Tanfed4c952019-11-08 10:38:19 +0800291phys_addr_t socfpga_get_rstmgr_addr(void)
292{
293 return socfpga_rstmgr_base;
294}
Ley Foon Tan3d3a8602019-11-08 10:38:20 +0800295
296phys_addr_t socfpga_get_sysmgr_addr(void)
297{
298 return socfpga_sysmgr_base;
299}
Ley Foon Tan26695912019-11-08 10:38:21 +0800300
301phys_addr_t socfpga_get_clkmgr_addr(void)
302{
303 return socfpga_clkmgr_base;
304}