1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  *  Copyright (C) 2012-2017 Altera Corporation <www.altera.com>
4  */
5 
6 #include <common.h>
7 #include <command.h>
8 #include <cpu_func.h>
9 #include <hang.h>
10 #include <asm/cache.h>
11 #include <init.h>
12 #include <asm/global_data.h>
13 #include <asm/io.h>
14 #include <errno.h>
15 #include <fdtdec.h>
16 #include <linux/libfdt.h>
17 #include <altera.h>
18 #include <miiphy.h>
19 #include <netdev.h>
20 #include <watchdog.h>
21 #include <asm/arch/misc.h>
22 #include <asm/arch/reset_manager.h>
23 #include <asm/arch/scan_manager.h>
24 #include <asm/arch/system_manager.h>
25 #include <asm/arch/nic301.h>
26 #include <asm/arch/scu.h>
27 #include <asm/pl310.h>
28 
29 DECLARE_GLOBAL_DATA_PTR;
30 
31 phys_addr_t socfpga_clkmgr_base __section(".data");
32 phys_addr_t socfpga_rstmgr_base __section(".data");
33 phys_addr_t socfpga_sysmgr_base __section(".data");
34 
35 #ifdef CONFIG_SYS_L2_PL310
36 static const struct pl310_regs *const pl310 =
37 	(struct pl310_regs *)CONFIG_SYS_PL310_BASE;
38 #endif
39 
40 struct bsel bsel_str[] = {
41 	{ "rsvd", "Reserved", },
42 	{ "fpga", "FPGA (HPS2FPGA Bridge)", },
43 	{ "nand", "NAND Flash (1.8V)", },
44 	{ "nand", "NAND Flash (3.0V)", },
45 	{ "sd", "SD/MMC External Transceiver (1.8V)", },
46 	{ "sd", "SD/MMC Internal Transceiver (3.0V)", },
47 	{ "qspi", "QSPI Flash (1.8V)", },
48 	{ "qspi", "QSPI Flash (3.0V)", },
49 };
50 
dram_init(void)51 int dram_init(void)
52 {
53 	if (fdtdec_setup_mem_size_base() != 0)
54 		return -EINVAL;
55 
56 	return 0;
57 }
58 
enable_caches(void)59 void enable_caches(void)
60 {
61 #if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
62 	icache_enable();
63 #endif
64 #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
65 	dcache_enable();
66 #endif
67 }
68 
69 #ifdef CONFIG_SYS_L2_PL310
v7_outer_cache_enable(void)70 void v7_outer_cache_enable(void)
71 {
72 	struct udevice *dev;
73 
74 	if (uclass_get_device(UCLASS_CACHE, 0, &dev))
75 		pr_err("cache controller driver NOT found!\n");
76 }
77 
v7_outer_cache_disable(void)78 void v7_outer_cache_disable(void)
79 {
80 	/* Disable the L2 cache */
81 	clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN);
82 }
83 
socfpga_pl310_clear(void)84 void socfpga_pl310_clear(void)
85 {
86 	u32 mask = 0xff, ena = 0;
87 
88 	icache_enable();
89 
90 	/* Disable the L2 cache */
91 	clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN);
92 
93 	writel(0x0, &pl310->pl310_tag_latency_ctrl);
94 	writel(0x10, &pl310->pl310_data_latency_ctrl);
95 
96 	/* enable BRESP, instruction and data prefetch, full line of zeroes */
97 	setbits_le32(&pl310->pl310_aux_ctrl,
98 		     L310_AUX_CTRL_DATA_PREFETCH_MASK |
99 		     L310_AUX_CTRL_INST_PREFETCH_MASK |
100 		     L310_SHARED_ATT_OVERRIDE_ENABLE);
101 
102 	/* Enable the L2 cache */
103 	ena = readl(&pl310->pl310_ctrl);
104 	ena |= L2X0_CTRL_EN;
105 
106 	/*
107 	 * Invalidate the PL310 L2 cache. Keep the invalidation code
108 	 * entirely in L1 I-cache to avoid any bus traffic through
109 	 * the L2.
110 	 */
111 	asm volatile(
112 		".align	5			\n"
113 		"	b	3f		\n"
114 		"1:	str	%1,	[%4]	\n"
115 		"	dsb			\n"
116 		"	isb			\n"
117 		"	str	%0,	[%2]	\n"
118 		"	dsb			\n"
119 		"	isb			\n"
120 		"2:	ldr	%0,	[%2]	\n"
121 		"	cmp	%0,	#0	\n"
122 		"	bne	2b		\n"
123 		"	str	%0,	[%3]	\n"
124 		"	dsb			\n"
125 		"	isb			\n"
126 		"	b	4f		\n"
127 		"3:	b	1b		\n"
128 		"4:	nop			\n"
129 	: "+r"(mask), "+r"(ena)
130 	: "r"(&pl310->pl310_inv_way),
131 	  "r"(&pl310->pl310_cache_sync), "r"(&pl310->pl310_ctrl)
132 	: "memory", "cc");
133 
134 	/* Disable the L2 cache */
135 	clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN);
136 }
137 #endif
138 
139 #if defined(CONFIG_SYS_CONSOLE_IS_IN_ENV) && \
140 defined(CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE)
overwrite_console(void)141 int overwrite_console(void)
142 {
143 	return 0;
144 }
145 #endif
146 
147 #ifdef CONFIG_FPGA
148 /* add device descriptor to FPGA device table */
socfpga_fpga_add(void * fpga_desc)149 void socfpga_fpga_add(void *fpga_desc)
150 {
151 	fpga_init();
152 	fpga_add(fpga_altera, fpga_desc);
153 }
154 #endif
155 
arch_cpu_init(void)156 int arch_cpu_init(void)
157 {
158 	socfpga_get_managers_addr();
159 
160 #ifdef CONFIG_HW_WATCHDOG
161 	/*
162 	 * In case the watchdog is enabled, make sure to (re-)configure it
163 	 * so that the defined timeout is valid. Otherwise the SPL (Perloader)
164 	 * timeout value is still active which might too short for Linux
165 	 * booting.
166 	 */
167 	hw_watchdog_init();
168 #else
169 	/*
170 	 * If the HW watchdog is NOT enabled, make sure it is not running,
171 	 * for example because it was enabled in the preloader. This might
172 	 * trigger a watchdog-triggered reboot of Linux kernel later.
173 	 * Toggle watchdog reset, so watchdog in not running state.
174 	 */
175 	socfpga_per_reset(SOCFPGA_RESET(L4WD0), 1);
176 	socfpga_per_reset(SOCFPGA_RESET(L4WD0), 0);
177 #endif
178 
179 	return 0;
180 }
181 
182 #ifndef CONFIG_SPL_BUILD
do_bridge(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])183 static int do_bridge(struct cmd_tbl *cmdtp, int flag, int argc,
184 		     char *const argv[])
185 {
186 	unsigned int mask = ~0;
187 
188 	if (argc < 2 || argc > 3)
189 		return CMD_RET_USAGE;
190 
191 	argv++;
192 
193 	if (argc == 3)
194 		mask = simple_strtoul(argv[1], NULL, 16);
195 
196 	switch (*argv[0]) {
197 	case 'e':	/* Enable */
198 		do_bridge_reset(1, mask);
199 		break;
200 	case 'd':	/* Disable */
201 		do_bridge_reset(0, mask);
202 		break;
203 	default:
204 		return CMD_RET_USAGE;
205 	}
206 
207 	return 0;
208 }
209 
210 U_BOOT_CMD(bridge, 3, 1, do_bridge,
211 	   "SoCFPGA HPS FPGA bridge control",
212 	   "enable [mask] - Enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges\n"
213 	   "bridge disable [mask] - Enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges\n"
214 	   ""
215 );
216 
217 #endif
218 
socfpga_get_base_addr(const char * compat,phys_addr_t * base)219 static int socfpga_get_base_addr(const char *compat, phys_addr_t *base)
220 {
221 	const void *blob = gd->fdt_blob;
222 	struct fdt_resource r;
223 	int node;
224 	int ret;
225 
226 	node = fdt_node_offset_by_compatible(blob, -1, compat);
227 	if (node < 0)
228 		return node;
229 
230 	if (!fdtdec_get_is_enabled(blob, node))
231 		return -ENODEV;
232 
233 	ret = fdt_get_resource(blob, node, "reg", 0, &r);
234 	if (ret)
235 		return ret;
236 
237 	*base = (phys_addr_t)r.start;
238 
239 	return 0;
240 }
241 
socfpga_get_managers_addr(void)242 void socfpga_get_managers_addr(void)
243 {
244 	int ret;
245 
246 	ret = socfpga_get_base_addr("altr,rst-mgr", &socfpga_rstmgr_base);
247 	if (ret)
248 		hang();
249 
250 	ret = socfpga_get_base_addr("altr,sys-mgr", &socfpga_sysmgr_base);
251 	if (ret)
252 		hang();
253 
254 #ifdef CONFIG_TARGET_SOCFPGA_AGILEX
255 	ret = socfpga_get_base_addr("intel,agilex-clkmgr",
256 				    &socfpga_clkmgr_base);
257 #else
258 	ret = socfpga_get_base_addr("altr,clk-mgr", &socfpga_clkmgr_base);
259 #endif
260 	if (ret)
261 		hang();
262 }
263 
socfpga_get_rstmgr_addr(void)264 phys_addr_t socfpga_get_rstmgr_addr(void)
265 {
266 	return socfpga_rstmgr_base;
267 }
268 
socfpga_get_sysmgr_addr(void)269 phys_addr_t socfpga_get_sysmgr_addr(void)
270 {
271 	return socfpga_sysmgr_base;
272 }
273 
socfpga_get_clkmgr_addr(void)274 phys_addr_t socfpga_get_clkmgr_addr(void)
275 {
276 	return socfpga_clkmgr_base;
277 }
278