]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
d1c559af LFT |
2 | /* |
3 | * Copyright (C) 2012-2017 Altera Corporation <www.altera.com> | |
d1c559af LFT |
4 | */ |
5 | ||
6 | #include <common.h> | |
9a3b4ceb | 7 | #include <cpu_func.h> |
691d719d | 8 | #include <init.h> |
d1c559af | 9 | #include <asm/io.h> |
9fb625ce | 10 | #include <env.h> |
d1c559af LFT |
11 | #include <errno.h> |
12 | #include <fdtdec.h> | |
b08c8c48 | 13 | #include <linux/libfdt.h> |
d1c559af LFT |
14 | #include <altera.h> |
15 | #include <miiphy.h> | |
16 | #include <netdev.h> | |
17 | #include <watchdog.h> | |
18 | #include <asm/arch/misc.h> | |
19 | #include <asm/arch/reset_manager.h> | |
20 | #include <asm/arch/scan_manager.h> | |
21 | #include <asm/arch/sdram.h> | |
22 | #include <asm/arch/system_manager.h> | |
23 | #include <asm/arch/nic301.h> | |
24 | #include <asm/arch/scu.h> | |
25 | #include <asm/pl310.h> | |
26 | ||
27 | #include <dt-bindings/reset/altr,rst-mgr.h> | |
28 | ||
29 | DECLARE_GLOBAL_DATA_PTR; | |
30 | ||
31 | static struct pl310_regs *const pl310 = | |
32 | (struct pl310_regs *)CONFIG_SYS_PL310_BASE; | |
d1c559af LFT |
33 | static struct nic301_registers *nic301_regs = |
34 | (struct nic301_registers *)SOCFPGA_L3REGS_ADDRESS; | |
35 | static struct scu_registers *scu_regs = | |
36 | (struct scu_registers *)SOCFPGA_MPUSCU_ADDRESS; | |
d1c559af | 37 | |
877ec6eb ACH |
38 | /* |
39 | * FPGA programming support for SoC FPGA Cyclone V | |
40 | */ | |
41 | static Altera_desc altera_fpga[] = { | |
42 | { | |
43 | /* Family */ | |
44 | Altera_SoCFPGA, | |
45 | /* Interface type */ | |
46 | fast_passive_parallel, | |
47 | /* No limitation as additional data will be ignored */ | |
48 | -1, | |
49 | /* No device function table */ | |
50 | NULL, | |
51 | /* Base interface address specified in driver */ | |
52 | NULL, | |
53 | /* No cookie implementation */ | |
54 | 0 | |
55 | }, | |
56 | }; | |
57 | ||
d1c559af LFT |
58 | static const struct { |
59 | const u16 pn; | |
60 | const char *name; | |
61 | const char *var; | |
5e8c39d4 | 62 | } socfpga_fpga_model[] = { |
d1c559af LFT |
63 | /* Cyclone V E */ |
64 | { 0x2b15, "Cyclone V, E/A2", "cv_e_a2" }, | |
65 | { 0x2b05, "Cyclone V, E/A4", "cv_e_a4" }, | |
66 | { 0x2b22, "Cyclone V, E/A5", "cv_e_a5" }, | |
67 | { 0x2b13, "Cyclone V, E/A7", "cv_e_a7" }, | |
68 | { 0x2b14, "Cyclone V, E/A9", "cv_e_a9" }, | |
69 | /* Cyclone V GX/GT */ | |
70 | { 0x2b01, "Cyclone V, GX/C3", "cv_gx_c3" }, | |
71 | { 0x2b12, "Cyclone V, GX/C4", "cv_gx_c4" }, | |
72 | { 0x2b02, "Cyclone V, GX/C5 or GT/D5", "cv_gx_c5" }, | |
73 | { 0x2b03, "Cyclone V, GX/C7 or GT/D7", "cv_gx_c7" }, | |
74 | { 0x2b04, "Cyclone V, GX/C9 or GT/D9", "cv_gx_c9" }, | |
75 | /* Cyclone V SE/SX/ST */ | |
76 | { 0x2d11, "Cyclone V, SE/A2 or SX/C2", "cv_se_a2" }, | |
77 | { 0x2d01, "Cyclone V, SE/A4 or SX/C4", "cv_se_a4" }, | |
78 | { 0x2d12, "Cyclone V, SE/A5 or SX/C5 or ST/D5", "cv_se_a5" }, | |
79 | { 0x2d02, "Cyclone V, SE/A6 or SX/C6 or ST/D6", "cv_se_a6" }, | |
80 | /* Arria V */ | |
81 | { 0x2d03, "Arria V, D5", "av_d5" }, | |
2007a730 MV |
82 | /* Arria V ST/SX */ |
83 | { 0x2d13, "Arria V, ST/D3 or SX/B3", "av_st_d3" }, | |
d1c559af LFT |
84 | }; |
85 | ||
86 | static int socfpga_fpga_id(const bool print_id) | |
87 | { | |
88 | const u32 altera_mi = 0x6e; | |
89 | const u32 id = scan_mgr_get_fpga_id(); | |
90 | ||
91 | const u32 lsb = id & 0x00000001; | |
92 | const u32 mi = (id >> 1) & 0x000007ff; | |
93 | const u32 pn = (id >> 12) & 0x0000ffff; | |
94 | const u32 version = (id >> 28) & 0x0000000f; | |
95 | int i; | |
96 | ||
97 | if ((mi != altera_mi) || (lsb != 1)) { | |
98 | printf("FPGA: Not Altera chip ID\n"); | |
99 | return -EINVAL; | |
100 | } | |
101 | ||
102 | for (i = 0; i < ARRAY_SIZE(socfpga_fpga_model); i++) | |
103 | if (pn == socfpga_fpga_model[i].pn) | |
104 | break; | |
105 | ||
106 | if (i == ARRAY_SIZE(socfpga_fpga_model)) { | |
107 | printf("FPGA: Unknown Altera chip, ID 0x%08x\n", id); | |
108 | return -EINVAL; | |
109 | } | |
110 | ||
111 | if (print_id) | |
112 | printf("FPGA: Altera %s, version 0x%01x\n", | |
113 | socfpga_fpga_model[i].name, version); | |
114 | return i; | |
115 | } | |
116 | ||
117 | /* | |
118 | * Print CPU information | |
119 | */ | |
120 | #if defined(CONFIG_DISPLAY_CPUINFO) | |
121 | int print_cpuinfo(void) | |
122 | { | |
db5741f7 LFT |
123 | const u32 bootinfo = readl(socfpga_get_sysmgr_addr() + |
124 | SYSMGR_GEN5_BOOTINFO); | |
125 | const u32 bsel = SYSMGR_GET_BOOTINFO_BSEL(bootinfo); | |
d1c559af LFT |
126 | |
127 | puts("CPU: Altera SoCFPGA Platform\n"); | |
128 | socfpga_fpga_id(1); | |
129 | ||
130 | printf("BOOT: %s\n", bsel_str[bsel].name); | |
131 | return 0; | |
132 | } | |
133 | #endif | |
134 | ||
135 | #ifdef CONFIG_ARCH_MISC_INIT | |
136 | int arch_misc_init(void) | |
137 | { | |
db5741f7 LFT |
138 | const u32 bsel = readl(socfpga_get_sysmgr_addr() + |
139 | SYSMGR_GEN5_BOOTINFO) & 0x7; | |
d1c559af | 140 | const int fpga_id = socfpga_fpga_id(0); |
382bee57 | 141 | env_set("bootmode", bsel_str[bsel].mode); |
d1c559af | 142 | if (fpga_id >= 0) |
382bee57 | 143 | env_set("fpgatype", socfpga_fpga_model[fpga_id].var); |
473f5567 | 144 | return 0; |
d1c559af LFT |
145 | } |
146 | #endif | |
147 | ||
148 | /* | |
149 | * Convert all NIC-301 AMBA slaves from secure to non-secure | |
150 | */ | |
151 | static void socfpga_nic301_slave_ns(void) | |
152 | { | |
153 | writel(0x1, &nic301_regs->lwhps2fpgaregs); | |
154 | writel(0x1, &nic301_regs->hps2fpgaregs); | |
155 | writel(0x1, &nic301_regs->acp); | |
156 | writel(0x1, &nic301_regs->rom); | |
157 | writel(0x1, &nic301_regs->ocram); | |
158 | writel(0x1, &nic301_regs->sdrdata); | |
159 | } | |
160 | ||
e4ff8420 SG |
161 | void socfpga_sdram_remap_zero(void) |
162 | { | |
30bade20 SG |
163 | u32 remap; |
164 | ||
e4ff8420 SG |
165 | socfpga_nic301_slave_ns(); |
166 | ||
167 | /* | |
168 | * Private components security: | |
169 | * U-Boot : configure private timer, global timer and cpu component | |
170 | * access as non secure for kernel stage (as required by Linux) | |
171 | */ | |
172 | setbits_le32(&scu_regs->sacr, 0xfff); | |
173 | ||
174 | /* Configure the L2 controller to make SDRAM start at 0 */ | |
30bade20 SG |
175 | remap = 0x1; /* remap.mpuzero */ |
176 | /* Keep fpga bridge enabled when running from FPGA onchip RAM */ | |
177 | if (socfpga_is_booting_from_fpga()) | |
178 | remap |= 0x8; /* remap.hps2fpga */ | |
179 | writel(remap, &nic301_regs->remap); | |
180 | ||
e4ff8420 SG |
181 | writel(0x1, &pl310->pl310_addr_filter_start); |
182 | } | |
183 | ||
d1c559af LFT |
184 | static u32 iswgrp_handoff[8]; |
185 | ||
186 | int arch_early_init_r(void) | |
187 | { | |
188 | int i; | |
189 | ||
190 | /* | |
191 | * Write magic value into magic register to unlock support for | |
192 | * issuing warm reset. The ancient kernel code expects this | |
193 | * value to be written into the register by the bootloader, so | |
194 | * to support that old code, we write it here instead of in the | |
195 | * reset_cpu() function just before resetting the CPU. | |
196 | */ | |
db5741f7 LFT |
197 | writel(0xae9efebc, |
198 | socfpga_get_sysmgr_addr() + SYSMGR_GEN5_WARMRAMGRP_EN); | |
d1c559af LFT |
199 | |
200 | for (i = 0; i < 8; i++) /* Cache initial SW setting regs */ | |
db5741f7 LFT |
201 | iswgrp_handoff[i] = readl(socfpga_get_sysmgr_addr() + |
202 | SYSMGR_ISWGRP_HANDOFF_OFFSET(i)); | |
d1c559af LFT |
203 | |
204 | socfpga_bridges_reset(1); | |
205 | ||
e4ff8420 | 206 | socfpga_sdram_remap_zero(); |
d1c559af LFT |
207 | |
208 | /* Add device descriptor to FPGA device table */ | |
877ec6eb | 209 | socfpga_fpga_add(&altera_fpga[0]); |
d1c559af | 210 | |
d1c559af LFT |
211 | return 0; |
212 | } | |
213 | ||
b4b9814f | 214 | #ifndef CONFIG_SPL_BUILD |
b4b9814f TR |
215 | static struct socfpga_sdr_ctrl *sdr_ctrl = |
216 | (struct socfpga_sdr_ctrl *)SDR_CTRLGRP_ADDRESS; | |
217 | ||
72c347ce | 218 | void do_bridge_reset(int enable, unsigned int mask) |
d1c559af | 219 | { |
72c347ce MV |
220 | int i; |
221 | ||
10f9e4b1 | 222 | if (enable) { |
72c347ce MV |
223 | socfpga_bridges_set_handoff_regs(!(mask & BIT(0)), |
224 | !(mask & BIT(1)), | |
225 | !(mask & BIT(2))); | |
226 | for (i = 0; i < 2; i++) { /* Reload SW setting cache */ | |
227 | iswgrp_handoff[i] = | |
db5741f7 LFT |
228 | readl(socfpga_get_sysmgr_addr() + |
229 | SYSMGR_ISWGRP_HANDOFF_OFFSET(i)); | |
72c347ce MV |
230 | } |
231 | ||
db5741f7 LFT |
232 | writel(iswgrp_handoff[2], |
233 | socfpga_get_sysmgr_addr() + | |
234 | SYSMGR_GEN5_FPGAINFGRP_MODULE); | |
d1c559af | 235 | writel(iswgrp_handoff[3], &sdr_ctrl->fpgaport_rst); |
bb25aca1 LFT |
236 | writel(iswgrp_handoff[0], |
237 | socfpga_get_rstmgr_addr() + RSTMGR_GEN5_BRGMODRST); | |
d1c559af | 238 | writel(iswgrp_handoff[1], &nic301_regs->remap); |
97a72bc2 | 239 | |
bb25aca1 LFT |
240 | writel(0x7, socfpga_get_rstmgr_addr() + RSTMGR_GEN5_BRGMODRST); |
241 | writel(iswgrp_handoff[0], | |
242 | socfpga_get_rstmgr_addr() + RSTMGR_GEN5_BRGMODRST); | |
10f9e4b1 | 243 | } else { |
db5741f7 LFT |
244 | writel(0, socfpga_get_sysmgr_addr() + |
245 | SYSMGR_GEN5_FPGAINFGRP_MODULE); | |
d1c559af | 246 | writel(0, &sdr_ctrl->fpgaport_rst); |
bb25aca1 | 247 | writel(0x7, socfpga_get_rstmgr_addr() + RSTMGR_GEN5_BRGMODRST); |
d1c559af | 248 | writel(1, &nic301_regs->remap); |
d1c559af | 249 | } |
d1c559af | 250 | } |
b4b9814f | 251 | #endif |