]>
Commit | Line | Data |
---|---|---|
827e6a7e LFT |
1 | /* |
2 | * Copyright (C) 2016-2017 Intel Corporation | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0 | |
5 | */ | |
6 | ||
7 | #include <asm/io.h> | |
8 | #include <asm/arch/fpga_manager.h> | |
9 | #include <asm/arch/misc.h> | |
10 | #include <asm/arch/reset_manager.h> | |
11 | #include <asm/arch/system_manager.h> | |
12 | #include <common.h> | |
13 | #include <errno.h> | |
14 | #include <fdtdec.h> | |
15 | #include <wait_bit.h> | |
16 | ||
17 | DECLARE_GLOBAL_DATA_PTR; | |
18 | ||
19 | static const struct socfpga_reset_manager *reset_manager_base = | |
20 | (void *)SOCFPGA_RSTMGR_ADDRESS; | |
21 | static const struct socfpga_system_manager *sysmgr_regs = | |
22 | (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS; | |
23 | ||
24 | #define ECC_MASK (ALT_RSTMGR_PER0MODRST_EMACECC0_SET_MSK | \ | |
25 | ALT_RSTMGR_PER0MODRST_EMACECC1_SET_MSK | \ | |
26 | ALT_RSTMGR_PER0MODRST_EMACECC2_SET_MSK | \ | |
27 | ALT_RSTMGR_PER0MODRST_NANDECC_SET_MSK | \ | |
28 | ALT_RSTMGR_PER0MODRST_QSPIECC_SET_MSK | \ | |
29 | ALT_RSTMGR_PER0MODRST_SDMMCECC_SET_MSK) | |
30 | ||
31 | void socfpga_reset_uart(int assert) | |
32 | { | |
33 | unsigned int com_port; | |
34 | ||
35 | com_port = uart_com_port(gd->fdt_blob); | |
36 | ||
37 | if (com_port == SOCFPGA_UART1_ADDRESS) | |
38 | socfpga_per_reset(SOCFPGA_RESET(UART1), assert); | |
39 | else if (com_port == SOCFPGA_UART0_ADDRESS) | |
40 | socfpga_per_reset(SOCFPGA_RESET(UART0), assert); | |
41 | } | |
42 | ||
43 | static const u32 per0fpgamasks[] = { | |
44 | ALT_RSTMGR_PER0MODRST_EMACECC0_SET_MSK | | |
45 | ALT_RSTMGR_PER0MODRST_EMAC0_SET_MSK, | |
46 | ALT_RSTMGR_PER0MODRST_EMACECC1_SET_MSK | | |
47 | ALT_RSTMGR_PER0MODRST_EMAC1_SET_MSK, | |
48 | ALT_RSTMGR_PER0MODRST_EMACECC2_SET_MSK | | |
49 | ALT_RSTMGR_PER0MODRST_EMAC2_SET_MSK, | |
50 | 0, /* i2c0 per1mod */ | |
51 | 0, /* i2c1 per1mod */ | |
52 | 0, /* i2c0_emac */ | |
53 | 0, /* i2c1_emac */ | |
54 | 0, /* i2c2_emac */ | |
55 | ALT_RSTMGR_PER0MODRST_NANDECC_SET_MSK | | |
56 | ALT_RSTMGR_PER0MODRST_NAND_SET_MSK, | |
57 | ALT_RSTMGR_PER0MODRST_QSPIECC_SET_MSK | | |
58 | ALT_RSTMGR_PER0MODRST_QSPI_SET_MSK, | |
59 | ALT_RSTMGR_PER0MODRST_SDMMCECC_SET_MSK | | |
60 | ALT_RSTMGR_PER0MODRST_SDMMC_SET_MSK, | |
61 | ALT_RSTMGR_PER0MODRST_SPIM0_SET_MSK, | |
62 | ALT_RSTMGR_PER0MODRST_SPIM1_SET_MSK, | |
63 | ALT_RSTMGR_PER0MODRST_SPIS0_SET_MSK, | |
64 | ALT_RSTMGR_PER0MODRST_SPIS1_SET_MSK, | |
65 | 0, /* uart0 per1mod */ | |
66 | 0, /* uart1 per1mod */ | |
67 | }; | |
68 | ||
69 | static const u32 per1fpgamasks[] = { | |
70 | 0, /* emac0 per0mod */ | |
71 | 0, /* emac1 per0mod */ | |
72 | 0, /* emac2 per0mod */ | |
73 | ALT_RSTMGR_PER1MODRST_I2C0_SET_MSK, | |
74 | ALT_RSTMGR_PER1MODRST_I2C1_SET_MSK, | |
75 | ALT_RSTMGR_PER1MODRST_I2C2_SET_MSK, /* i2c0_emac */ | |
76 | ALT_RSTMGR_PER1MODRST_I2C3_SET_MSK, /* i2c1_emac */ | |
77 | ALT_RSTMGR_PER1MODRST_I2C4_SET_MSK, /* i2c2_emac */ | |
78 | 0, /* nand per0mod */ | |
79 | 0, /* qspi per0mod */ | |
80 | 0, /* sdmmc per0mod */ | |
81 | 0, /* spim0 per0mod */ | |
82 | 0, /* spim1 per0mod */ | |
83 | 0, /* spis0 per0mod */ | |
84 | 0, /* spis1 per0mod */ | |
85 | ALT_RSTMGR_PER1MODRST_UART0_SET_MSK, | |
86 | ALT_RSTMGR_PER1MODRST_UART1_SET_MSK, | |
87 | }; | |
88 | ||
89 | struct bridge_cfg { | |
90 | int compat_id; | |
91 | u32 mask_noc; | |
92 | u32 mask_rstmgr; | |
93 | }; | |
94 | ||
95 | static const struct bridge_cfg bridge_cfg_tbl[] = { | |
96 | { | |
97 | COMPAT_ALTERA_SOCFPGA_H2F_BRG, | |
98 | ALT_SYSMGR_NOC_H2F_SET_MSK, | |
99 | ALT_RSTMGR_BRGMODRST_H2F_SET_MSK, | |
100 | }, | |
101 | { | |
102 | COMPAT_ALTERA_SOCFPGA_LWH2F_BRG, | |
103 | ALT_SYSMGR_NOC_LWH2F_SET_MSK, | |
104 | ALT_RSTMGR_BRGMODRST_LWH2F_SET_MSK, | |
105 | }, | |
106 | { | |
107 | COMPAT_ALTERA_SOCFPGA_F2H_BRG, | |
108 | ALT_SYSMGR_NOC_F2H_SET_MSK, | |
109 | ALT_RSTMGR_BRGMODRST_F2H_SET_MSK, | |
110 | }, | |
111 | { | |
112 | COMPAT_ALTERA_SOCFPGA_F2SDR0, | |
113 | ALT_SYSMGR_NOC_F2SDR0_SET_MSK, | |
114 | ALT_RSTMGR_BRGMODRST_F2SSDRAM0_SET_MSK, | |
115 | }, | |
116 | { | |
117 | COMPAT_ALTERA_SOCFPGA_F2SDR1, | |
118 | ALT_SYSMGR_NOC_F2SDR1_SET_MSK, | |
119 | ALT_RSTMGR_BRGMODRST_F2SSDRAM1_SET_MSK, | |
120 | }, | |
121 | { | |
122 | COMPAT_ALTERA_SOCFPGA_F2SDR2, | |
123 | ALT_SYSMGR_NOC_F2SDR2_SET_MSK, | |
124 | ALT_RSTMGR_BRGMODRST_F2SSDRAM2_SET_MSK, | |
125 | }, | |
126 | }; | |
127 | ||
128 | /* Disable the watchdog (toggle reset to watchdog) */ | |
129 | void socfpga_watchdog_disable(void) | |
130 | { | |
131 | /* assert reset for watchdog */ | |
132 | setbits_le32(&reset_manager_base->per1modrst, | |
133 | ALT_RSTMGR_PER1MODRST_WD0_SET_MSK); | |
134 | } | |
135 | ||
136 | /* Release NOC ddr scheduler from reset */ | |
137 | void socfpga_reset_deassert_noc_ddr_scheduler(void) | |
138 | { | |
139 | clrbits_le32(&reset_manager_base->brgmodrst, | |
140 | ALT_RSTMGR_BRGMODRST_DDRSCH_SET_MSK); | |
141 | } | |
142 | ||
143 | /* Check whether Watchdog in reset state? */ | |
144 | int socfpga_is_wdt_in_reset(void) | |
145 | { | |
146 | u32 val; | |
147 | ||
148 | val = readl(&reset_manager_base->per1modrst); | |
149 | val &= ALT_RSTMGR_PER1MODRST_WD0_SET_MSK; | |
150 | ||
151 | /* return 0x1 if watchdog in reset */ | |
152 | return val; | |
153 | } | |
154 | ||
155 | /* emacbase: base address of emac to enable/disable reset | |
156 | * state: 0 - disable reset, !0 - enable reset | |
157 | */ | |
158 | void socfpga_emac_manage_reset(ulong emacbase, u32 state) | |
159 | { | |
160 | ulong eccmask; | |
161 | ulong emacmask; | |
162 | ||
163 | switch (emacbase) { | |
164 | case SOCFPGA_EMAC0_ADDRESS: | |
165 | eccmask = ALT_RSTMGR_PER0MODRST_EMACECC0_SET_MSK; | |
166 | emacmask = ALT_RSTMGR_PER0MODRST_EMAC0_SET_MSK; | |
167 | break; | |
168 | case SOCFPGA_EMAC1_ADDRESS: | |
169 | eccmask = ALT_RSTMGR_PER0MODRST_EMACECC1_SET_MSK; | |
170 | emacmask = ALT_RSTMGR_PER0MODRST_EMAC1_SET_MSK; | |
171 | break; | |
172 | case SOCFPGA_EMAC2_ADDRESS: | |
173 | eccmask = ALT_RSTMGR_PER0MODRST_EMACECC2_SET_MSK; | |
174 | emacmask = ALT_RSTMGR_PER0MODRST_EMAC2_SET_MSK; | |
175 | break; | |
176 | default: | |
177 | error("emac base address unexpected! %lx", emacbase); | |
178 | hang(); | |
179 | break; | |
180 | } | |
181 | ||
182 | if (state) { | |
183 | /* Enable ECC OCP first */ | |
184 | setbits_le32(&reset_manager_base->per0modrst, eccmask); | |
185 | setbits_le32(&reset_manager_base->per0modrst, emacmask); | |
186 | } else { | |
187 | /* Disable ECC OCP first */ | |
188 | clrbits_le32(&reset_manager_base->per0modrst, emacmask); | |
189 | clrbits_le32(&reset_manager_base->per0modrst, eccmask); | |
190 | } | |
191 | } | |
192 | ||
193 | static int get_bridge_init_val(const void *blob, int compat_id) | |
194 | { | |
195 | int node; | |
196 | ||
197 | node = fdtdec_next_compatible(blob, 0, compat_id); | |
198 | if (node < 0) | |
199 | return 0; | |
200 | ||
201 | return fdtdec_get_uint(blob, node, "init-val", 0); | |
202 | } | |
203 | ||
204 | /* Enable bridges (hps2fpga, lwhps2fpga, fpga2hps, fpga2sdram) per handoff */ | |
205 | int socfpga_reset_deassert_bridges_handoff(void) | |
206 | { | |
207 | u32 mask_noc = 0, mask_rstmgr = 0; | |
208 | int i; | |
209 | ||
210 | for (i = 0; i < ARRAY_SIZE(bridge_cfg_tbl); i++) { | |
211 | if (get_bridge_init_val(gd->fdt_blob, | |
212 | bridge_cfg_tbl[i].compat_id)) { | |
213 | mask_noc |= bridge_cfg_tbl[i].mask_noc; | |
214 | mask_rstmgr |= bridge_cfg_tbl[i].mask_rstmgr; | |
215 | } | |
216 | } | |
217 | ||
218 | /* clear idle request to all bridges */ | |
219 | setbits_le32(&sysmgr_regs->noc_idlereq_clr, mask_noc); | |
220 | ||
221 | /* Release bridges from reset state per handoff value */ | |
222 | clrbits_le32(&reset_manager_base->brgmodrst, mask_rstmgr); | |
223 | ||
224 | /* Poll until all idleack to 0, timeout at 1000ms */ | |
225 | return wait_for_bit(__func__, &sysmgr_regs->noc_idleack, mask_noc, | |
226 | false, 1000, false); | |
227 | } | |
228 | ||
229 | void socfpga_reset_assert_fpga_connected_peripherals(void) | |
230 | { | |
231 | u32 mask0 = 0; | |
232 | u32 mask1 = 0; | |
233 | u32 fpga_pinux_addr = SOCFPGA_PINMUX_FPGA_INTERFACE_ADDRESS; | |
234 | int i; | |
235 | ||
236 | for (i = 0; i < ARRAY_SIZE(per1fpgamasks); i++) { | |
237 | if (readl(fpga_pinux_addr)) { | |
238 | mask0 |= per0fpgamasks[i]; | |
239 | mask1 |= per1fpgamasks[i]; | |
240 | } | |
241 | fpga_pinux_addr += sizeof(u32); | |
242 | } | |
243 | ||
244 | setbits_le32(&reset_manager_base->per0modrst, mask0 & ECC_MASK); | |
245 | setbits_le32(&reset_manager_base->per1modrst, mask1); | |
246 | setbits_le32(&reset_manager_base->per0modrst, mask0); | |
247 | } | |
248 | ||
249 | /* Release L4 OSC1 Watchdog Timer 0 from reset through reset manager */ | |
250 | void socfpga_reset_deassert_osc1wd0(void) | |
251 | { | |
252 | clrbits_le32(&reset_manager_base->per1modrst, | |
253 | ALT_RSTMGR_PER1MODRST_WD0_SET_MSK); | |
254 | } | |
255 | ||
256 | /* | |
257 | * Assert or de-assert SoCFPGA reset manager reset. | |
258 | */ | |
259 | void socfpga_per_reset(u32 reset, int set) | |
260 | { | |
261 | const u32 *reg; | |
262 | u32 rstmgr_bank = RSTMGR_BANK(reset); | |
263 | ||
264 | switch (rstmgr_bank) { | |
265 | case 0: | |
266 | reg = &reset_manager_base->mpumodrst; | |
267 | break; | |
268 | case 1: | |
269 | reg = &reset_manager_base->per0modrst; | |
270 | break; | |
271 | case 2: | |
272 | reg = &reset_manager_base->per1modrst; | |
273 | break; | |
274 | case 3: | |
275 | reg = &reset_manager_base->brgmodrst; | |
276 | break; | |
277 | case 4: | |
278 | reg = &reset_manager_base->sysmodrst; | |
279 | break; | |
280 | ||
281 | default: | |
282 | return; | |
283 | } | |
284 | ||
285 | if (set) | |
286 | setbits_le32(reg, 1 << RSTMGR_RESET(reset)); | |
287 | else | |
288 | clrbits_le32(reg, 1 << RSTMGR_RESET(reset)); | |
289 | } | |
290 | ||
291 | /* | |
292 | * Assert reset on every peripheral but L4WD0. | |
293 | * Watchdog must be kept intact to prevent glitches | |
294 | * and/or hangs. | |
295 | * For the Arria10, we disable all the peripherals except L4 watchdog0, | |
296 | * L4 Timer 0, and ECC. | |
297 | */ | |
298 | void socfpga_per_reset_all(void) | |
299 | { | |
300 | const u32 l4wd0 = (1 << RSTMGR_RESET(SOCFPGA_RESET(L4WD0)) | | |
301 | (1 << RSTMGR_RESET(SOCFPGA_RESET(L4SYSTIMER0)))); | |
302 | unsigned mask_ecc_ocp = | |
303 | ALT_RSTMGR_PER0MODRST_EMACECC0_SET_MSK | | |
304 | ALT_RSTMGR_PER0MODRST_EMACECC1_SET_MSK | | |
305 | ALT_RSTMGR_PER0MODRST_EMACECC2_SET_MSK | | |
306 | ALT_RSTMGR_PER0MODRST_USBECC0_SET_MSK | | |
307 | ALT_RSTMGR_PER0MODRST_USBECC1_SET_MSK | | |
308 | ALT_RSTMGR_PER0MODRST_NANDECC_SET_MSK | | |
309 | ALT_RSTMGR_PER0MODRST_QSPIECC_SET_MSK | | |
310 | ALT_RSTMGR_PER0MODRST_SDMMCECC_SET_MSK; | |
311 | ||
312 | /* disable all components except ECC_OCP, L4 Timer0 and L4 WD0 */ | |
313 | writel(~l4wd0, &reset_manager_base->per1modrst); | |
314 | setbits_le32(&reset_manager_base->per0modrst, ~mask_ecc_ocp); | |
315 | ||
316 | /* Finally disable the ECC_OCP */ | |
317 | setbits_le32(&reset_manager_base->per0modrst, mask_ecc_ocp); | |
318 | } | |
319 | ||
320 | #if defined(CONFIG_SOCFPGA_VIRTUAL_TARGET) | |
6a34af5b | 321 | int socfpga_bridges_reset(void) |
827e6a7e LFT |
322 | { |
323 | /* For SoCFPGA-VT, this is NOP. */ | |
324 | return 0; | |
325 | } | |
326 | #else | |
6a34af5b | 327 | int socfpga_bridges_reset(void) |
827e6a7e LFT |
328 | { |
329 | int ret; | |
330 | ||
331 | /* Disable all the bridges (hps2fpga, lwhps2fpga, fpga2hps, | |
332 | fpga2sdram) */ | |
333 | /* set idle request to all bridges */ | |
334 | writel(ALT_SYSMGR_NOC_H2F_SET_MSK | | |
335 | ALT_SYSMGR_NOC_LWH2F_SET_MSK | | |
336 | ALT_SYSMGR_NOC_F2H_SET_MSK | | |
337 | ALT_SYSMGR_NOC_F2SDR0_SET_MSK | | |
338 | ALT_SYSMGR_NOC_F2SDR1_SET_MSK | | |
339 | ALT_SYSMGR_NOC_F2SDR2_SET_MSK, | |
340 | &sysmgr_regs->noc_idlereq_set); | |
341 | ||
342 | /* Enable the NOC timeout */ | |
343 | writel(ALT_SYSMGR_NOC_TMO_EN_SET_MSK, &sysmgr_regs->noc_timeout); | |
344 | ||
345 | /* Poll until all idleack to 1 */ | |
346 | ret = wait_for_bit(__func__, &sysmgr_regs->noc_idleack, | |
347 | ALT_SYSMGR_NOC_H2F_SET_MSK | | |
348 | ALT_SYSMGR_NOC_LWH2F_SET_MSK | | |
349 | ALT_SYSMGR_NOC_F2H_SET_MSK | | |
350 | ALT_SYSMGR_NOC_F2SDR0_SET_MSK | | |
351 | ALT_SYSMGR_NOC_F2SDR1_SET_MSK | | |
352 | ALT_SYSMGR_NOC_F2SDR2_SET_MSK, | |
353 | true, 10000, false); | |
354 | if (ret) | |
355 | return ret; | |
356 | ||
357 | /* Poll until all idlestatus to 1 */ | |
358 | ret = wait_for_bit(__func__, &sysmgr_regs->noc_idlestatus, | |
359 | ALT_SYSMGR_NOC_H2F_SET_MSK | | |
360 | ALT_SYSMGR_NOC_LWH2F_SET_MSK | | |
361 | ALT_SYSMGR_NOC_F2H_SET_MSK | | |
362 | ALT_SYSMGR_NOC_F2SDR0_SET_MSK | | |
363 | ALT_SYSMGR_NOC_F2SDR1_SET_MSK | | |
364 | ALT_SYSMGR_NOC_F2SDR2_SET_MSK, | |
365 | true, 10000, false); | |
366 | if (ret) | |
367 | return ret; | |
368 | ||
369 | /* Put all bridges (except NOR DDR scheduler) into reset state */ | |
370 | setbits_le32(&reset_manager_base->brgmodrst, | |
371 | (ALT_RSTMGR_BRGMODRST_H2F_SET_MSK | | |
372 | ALT_RSTMGR_BRGMODRST_LWH2F_SET_MSK | | |
373 | ALT_RSTMGR_BRGMODRST_F2H_SET_MSK | | |
374 | ALT_RSTMGR_BRGMODRST_F2SSDRAM0_SET_MSK | | |
375 | ALT_RSTMGR_BRGMODRST_F2SSDRAM1_SET_MSK | | |
376 | ALT_RSTMGR_BRGMODRST_F2SSDRAM2_SET_MSK)); | |
377 | ||
378 | /* Disable NOC timeout */ | |
379 | writel(0, &sysmgr_regs->noc_timeout); | |
380 | ||
381 | return 0; | |
382 | } | |
383 | #endif |