blob: 623843e3b788d4c417ecae27bbd47f11458eb8ba [file] [log] [blame]
Hadi Asyrafi616da772019-06-27 11:34:03 +08001/*
Jit Loon Lim86f6fb32023-05-17 12:26:11 +08002 * Copyright (c) 2019-2023, ARM Limited and Contributors. All rights reserved.
Jit Loon Limb24dddf2023-05-17 12:26:11 +08003 * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
Sieu Mun Tangebca5152024-08-26 07:59:10 +08004 * Copyright (c) 2024, Altera Corporation. All rights reserved.
Hadi Asyrafi616da772019-06-27 11:34:03 +08005 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9#include <arch_helpers.h>
10#include <common/debug.h>
Jit Loon Limb24dddf2023-05-17 12:26:11 +080011
12#ifndef GICV3_SUPPORT_GIC600
Hadi Asyrafi616da772019-06-27 11:34:03 +080013#include <drivers/arm/gicv2.h>
Jit Loon Lim86f6fb32023-05-17 12:26:11 +080014#else
15#include <drivers/arm/gicv3.h>
16#endif
Hadi Asyrafi616da772019-06-27 11:34:03 +080017#include <lib/mmio.h>
18#include <lib/psci/psci.h>
19#include <plat/common/platform.h>
Hadi Asyrafi6f8a2b22019-10-23 18:34:14 +080020#include "socfpga_mailbox.h"
Hadi Asyrafi4d9f3952019-10-23 17:35:32 +080021#include "socfpga_plat_def.h"
Hadi Asyrafi5fae68f2019-10-22 14:23:57 +080022#include "socfpga_reset_manager.h"
Sieu Mun Tangdbcc2cf2022-03-07 12:13:04 +080023#include "socfpga_sip_svc.h"
Jit Loon Lim86f6fb32023-05-17 12:26:11 +080024#include "socfpga_system_manager.h"
Hadi Asyrafi616da772019-06-27 11:34:03 +080025
Jit Loon Limb24dddf2023-05-17 12:26:11 +080026#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
27void socfpga_wakeup_secondary_cpu(unsigned int cpu_id);
28extern void plat_secondary_cold_boot_setup(void);
29#endif
Hadi Asyrafi616da772019-06-27 11:34:03 +080030
Hadi Asyrafi616da772019-06-27 11:34:03 +080031/*******************************************************************************
32 * plat handler called when a CPU is about to enter standby.
33 ******************************************************************************/
34void socfpga_cpu_standby(plat_local_state_t cpu_state)
35{
36 /*
37 * Enter standby state
38 * dsb is good practice before using wfi to enter low power states
39 */
40 VERBOSE("%s: cpu_state: 0x%x\n", __func__, cpu_state);
41 dsb();
42 wfi();
43}
44
45/*******************************************************************************
46 * plat handler called when a power domain is about to be turned on. The
47 * mpidr determines the CPU to be turned on.
48 ******************************************************************************/
49int socfpga_pwr_domain_on(u_register_t mpidr)
50{
51 unsigned int cpu_id = plat_core_pos_by_mpidr(mpidr);
Jit Loon Limb24dddf2023-05-17 12:26:11 +080052#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
53 /* TODO: Add in CPU FUSE from SDM */
54#else
Jit Loon Lim44c61fc2023-03-02 13:38:53 +080055 uint32_t psci_boot = 0x00;
Hadi Asyrafi616da772019-06-27 11:34:03 +080056
57 VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr);
Jit Loon Limb24dddf2023-05-17 12:26:11 +080058#endif
Hadi Asyrafi616da772019-06-27 11:34:03 +080059
60 if (cpu_id == -1)
61 return PSCI_E_INTERN_FAIL;
62
Jit Loon Limb24dddf2023-05-17 12:26:11 +080063#if PLATFORM_MODEL != PLAT_SOCFPGA_AGILEX5
Jit Loon Lim44c61fc2023-03-02 13:38:53 +080064 if (cpu_id == 0x00) {
65 psci_boot = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_8));
Jit Loon Lim9da76202023-06-10 00:04:49 +080066 psci_boot |= 0x80000; /* bit 19 */
Jit Loon Lim44c61fc2023-03-02 13:38:53 +080067 mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_8), psci_boot);
68 }
69
Hadi Asyrafia2edf0e2019-10-22 13:39:14 +080070 mmio_write_64(PLAT_CPUID_RELEASE, cpu_id);
Jit Loon Limb24dddf2023-05-17 12:26:11 +080071#endif
Hadi Asyrafi616da772019-06-27 11:34:03 +080072
73 /* release core reset */
Jit Loon Limb24dddf2023-05-17 12:26:11 +080074#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
75 bl31_plat_set_secondary_cpu_entrypoint(cpu_id);
76#else
Hadi Asyrafi67cb0ea2019-12-23 13:25:33 +080077 mmio_setbits_32(SOCFPGA_RSTMGR(MPUMODRST), 1 << cpu_id);
Jit Loon Limb24dddf2023-05-17 12:26:11 +080078 mmio_write_64(PLAT_CPUID_RELEASE, cpu_id);
79#endif
80
Hadi Asyrafi616da772019-06-27 11:34:03 +080081 return PSCI_E_SUCCESS;
82}
83
84/*******************************************************************************
85 * plat handler called when a power domain is about to be turned off. The
86 * target_state encodes the power state that each level should transition to.
87 ******************************************************************************/
88void socfpga_pwr_domain_off(const psci_power_state_t *target_state)
89{
Hadi Asyrafi616da772019-06-27 11:34:03 +080090 for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
91 VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
92 __func__, i, target_state->pwr_domain_state[i]);
93
Hadi Asyrafi91071fc2019-09-12 15:14:01 +080094 /* Prevent interrupts from spuriously waking up this cpu */
Jit Loon Limb24dddf2023-05-17 12:26:11 +080095#ifdef GICV3_SUPPORT_GIC600
96 gicv3_cpuif_disable(plat_my_core_pos());
97#else
Hadi Asyrafi91071fc2019-09-12 15:14:01 +080098 gicv2_cpuif_disable();
Jit Loon Limb24dddf2023-05-17 12:26:11 +080099#endif
100
Hadi Asyrafi616da772019-06-27 11:34:03 +0800101}
102
103/*******************************************************************************
104 * plat handler called when a power domain is about to be suspended. The
105 * target_state encodes the power state that each level should transition to.
106 ******************************************************************************/
107void socfpga_pwr_domain_suspend(const psci_power_state_t *target_state)
108{
Jit Loon Limb24dddf2023-05-17 12:26:11 +0800109#if PLATFORM_MODEL != PLAT_SOCFPGA_AGILEX5
Hadi Asyrafi616da772019-06-27 11:34:03 +0800110 unsigned int cpu_id = plat_my_core_pos();
Jit Loon Limb24dddf2023-05-17 12:26:11 +0800111#endif
Hadi Asyrafi616da772019-06-27 11:34:03 +0800112
113 for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
114 VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
115 __func__, i, target_state->pwr_domain_state[i]);
Hadi Asyrafi5fae68f2019-10-22 14:23:57 +0800116
Jit Loon Limb24dddf2023-05-17 12:26:11 +0800117#if PLATFORM_MODEL != PLAT_SOCFPGA_AGILEX5
Hadi Asyrafi616da772019-06-27 11:34:03 +0800118 /* assert core reset */
Hadi Asyrafi67cb0ea2019-12-23 13:25:33 +0800119 mmio_setbits_32(SOCFPGA_RSTMGR(MPUMODRST), 1 << cpu_id);
Jit Loon Limb24dddf2023-05-17 12:26:11 +0800120#endif
Hadi Asyrafi616da772019-06-27 11:34:03 +0800121}
122
123/*******************************************************************************
124 * plat handler called when a power domain has just been powered on after
125 * being turned off earlier. The target_state encodes the low power state that
126 * each level has woken up from.
127 ******************************************************************************/
128void socfpga_pwr_domain_on_finish(const psci_power_state_t *target_state)
129{
130 for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
131 VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
132 __func__, i, target_state->pwr_domain_state[i]);
133
Jit Loon Limb24dddf2023-05-17 12:26:11 +0800134 /* Enable the gic cpu interface */
135#ifdef GICV3_SUPPORT_GIC600
136 gicv3_rdistif_init(plat_my_core_pos());
137 gicv3_cpuif_enable(plat_my_core_pos());
138#else
Hadi Asyrafi616da772019-06-27 11:34:03 +0800139 /* Program the gic per-cpu distributor or re-distributor interface */
140 gicv2_pcpu_distif_init();
141 gicv2_set_pe_target_mask(plat_my_core_pos());
142
143 /* Enable the gic cpu interface */
144 gicv2_cpuif_enable();
Jit Loon Limb24dddf2023-05-17 12:26:11 +0800145#endif
Hadi Asyrafi616da772019-06-27 11:34:03 +0800146}
147
148/*******************************************************************************
149 * plat handler called when a power domain has just been powered on after
150 * having been suspended earlier. The target_state encodes the low power state
151 * that each level has woken up from.
152 * TODO: At the moment we reuse the on finisher and reinitialize the secure
153 * context. Need to implement a separate suspend finisher.
154 ******************************************************************************/
155void socfpga_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
156{
Jit Loon Limb24dddf2023-05-17 12:26:11 +0800157#if PLATFORM_MODEL != PLAT_SOCFPGA_AGILEX5
Hadi Asyrafi616da772019-06-27 11:34:03 +0800158 unsigned int cpu_id = plat_my_core_pos();
Jit Loon Limb24dddf2023-05-17 12:26:11 +0800159#endif
Hadi Asyrafi616da772019-06-27 11:34:03 +0800160
161 for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
162 VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
163 __func__, i, target_state->pwr_domain_state[i]);
164
Jit Loon Limb24dddf2023-05-17 12:26:11 +0800165#if PLATFORM_MODEL != PLAT_SOCFPGA_AGILEX5
Hadi Asyrafi616da772019-06-27 11:34:03 +0800166 /* release core reset */
Hadi Asyrafi67cb0ea2019-12-23 13:25:33 +0800167 mmio_clrbits_32(SOCFPGA_RSTMGR(MPUMODRST), 1 << cpu_id);
Jit Loon Limb24dddf2023-05-17 12:26:11 +0800168#endif
Hadi Asyrafi616da772019-06-27 11:34:03 +0800169}
170
171/*******************************************************************************
172 * plat handlers to shutdown/reboot the system
173 ******************************************************************************/
174static void __dead2 socfpga_system_off(void)
175{
176 wfi();
177 ERROR("System Off: operation not handled.\n");
178 panic();
179}
180
Hadi Asyrafi593c4c52019-12-17 19:22:17 +0800181extern uint64_t intel_rsu_update_address;
182
Hadi Asyrafi616da772019-06-27 11:34:03 +0800183static void __dead2 socfpga_system_reset(void)
184{
Abdul Halim, Muhammad Hadi Asyrafid84bfef2020-02-25 16:28:10 +0800185 uint32_t addr_buf[2];
186
Sieu Mun Tangebca5152024-08-26 07:59:10 +0800187 memcpy_s(addr_buf, sizeof(intel_rsu_update_address),
188 &intel_rsu_update_address, sizeof(intel_rsu_update_address));
189
Jit Loon Lim86f6fb32023-05-17 12:26:11 +0800190 if (intel_rsu_update_address) {
Abdul Halim, Muhammad Hadi Asyrafid84bfef2020-02-25 16:28:10 +0800191 mailbox_rsu_update(addr_buf);
Jit Loon Lim86f6fb32023-05-17 12:26:11 +0800192 } else {
Hadi Asyrafi593c4c52019-12-17 19:22:17 +0800193 mailbox_reset_cold();
Jit Loon Lim86f6fb32023-05-17 12:26:11 +0800194 }
Hadi Asyrafi616da772019-06-27 11:34:03 +0800195
196 while (1)
197 wfi();
198}
199
Hadi Asyrafi5fae68f2019-10-22 14:23:57 +0800200static int socfpga_system_reset2(int is_vendor, int reset_type,
201 u_register_t cookie)
202{
Jit Loon Limb24dddf2023-05-17 12:26:11 +0800203#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
204 mailbox_reset_warm(reset_type);
205#else
Sieu Mun Tangdbcc2cf2022-03-07 12:13:04 +0800206 if (cold_reset_for_ecc_dbe()) {
207 mailbox_reset_cold();
208 }
Jit Loon Limb24dddf2023-05-17 12:26:11 +0800209#endif
210
Hadi Asyrafi5fae68f2019-10-22 14:23:57 +0800211 /* disable cpuif */
Jit Loon Limb24dddf2023-05-17 12:26:11 +0800212#ifdef GICV3_SUPPORT_GIC600
213 gicv3_cpuif_disable(plat_my_core_pos());
214#else
Hadi Asyrafi5fae68f2019-10-22 14:23:57 +0800215 gicv2_cpuif_disable();
Jit Loon Limb24dddf2023-05-17 12:26:11 +0800216#endif
Hadi Asyrafi5fae68f2019-10-22 14:23:57 +0800217
218 /* Store magic number */
219 mmio_write_32(L2_RESET_DONE_REG, L2_RESET_DONE_STATUS);
220
221 /* Increase timeout */
Hadi Asyrafi67cb0ea2019-12-23 13:25:33 +0800222 mmio_write_32(SOCFPGA_RSTMGR(HDSKTIMEOUT), 0xffffff);
Hadi Asyrafi5fae68f2019-10-22 14:23:57 +0800223
224 /* Enable handshakes */
Hadi Asyrafi67cb0ea2019-12-23 13:25:33 +0800225 mmio_setbits_32(SOCFPGA_RSTMGR(HDSKEN), RSTMGR_HDSKEN_SET);
Hadi Asyrafi5fae68f2019-10-22 14:23:57 +0800226
Jit Loon Limb24dddf2023-05-17 12:26:11 +0800227#if PLATFORM_MODEL != PLAT_SOCFPGA_AGILEX5
Hadi Asyrafi5fae68f2019-10-22 14:23:57 +0800228 /* Reset L2 module */
Hadi Asyrafi67cb0ea2019-12-23 13:25:33 +0800229 mmio_setbits_32(SOCFPGA_RSTMGR(COLDMODRST), 0x100);
Jit Loon Limb24dddf2023-05-17 12:26:11 +0800230#endif
Hadi Asyrafi5fae68f2019-10-22 14:23:57 +0800231
232 while (1)
233 wfi();
234
235 /* Should not reach here */
236 return 0;
237}
238
Hadi Asyrafi616da772019-06-27 11:34:03 +0800239int socfpga_validate_power_state(unsigned int power_state,
240 psci_power_state_t *req_state)
241{
242 VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
243
244 return PSCI_E_SUCCESS;
245}
246
247int socfpga_validate_ns_entrypoint(unsigned long ns_entrypoint)
248{
249 VERBOSE("%s: ns_entrypoint: 0x%lx\n", __func__, ns_entrypoint);
250 return PSCI_E_SUCCESS;
251}
252
253void socfpga_get_sys_suspend_power_state(psci_power_state_t *req_state)
254{
255 req_state->pwr_domain_state[PSCI_CPU_PWR_LVL] = PLAT_MAX_OFF_STATE;
256 req_state->pwr_domain_state[1] = PLAT_MAX_OFF_STATE;
257}
258
259/*******************************************************************************
260 * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
261 * platform layer will take care of registering the handlers with PSCI.
262 ******************************************************************************/
263const plat_psci_ops_t socfpga_psci_pm_ops = {
264 .cpu_standby = socfpga_cpu_standby,
265 .pwr_domain_on = socfpga_pwr_domain_on,
266 .pwr_domain_off = socfpga_pwr_domain_off,
267 .pwr_domain_suspend = socfpga_pwr_domain_suspend,
268 .pwr_domain_on_finish = socfpga_pwr_domain_on_finish,
269 .pwr_domain_suspend_finish = socfpga_pwr_domain_suspend_finish,
270 .system_off = socfpga_system_off,
271 .system_reset = socfpga_system_reset,
Hadi Asyrafi5fae68f2019-10-22 14:23:57 +0800272 .system_reset2 = socfpga_system_reset2,
Hadi Asyrafi616da772019-06-27 11:34:03 +0800273 .validate_power_state = socfpga_validate_power_state,
274 .validate_ns_entrypoint = socfpga_validate_ns_entrypoint,
275 .get_sys_suspend_power_state = socfpga_get_sys_suspend_power_state
276};
277
278/*******************************************************************************
279 * Export the platform specific power ops.
280 ******************************************************************************/
281int plat_setup_psci_ops(uintptr_t sec_entrypoint,
282 const struct plat_psci_ops **psci_ops)
283{
284 /* Save warm boot entrypoint.*/
Hadi Asyrafia2edf0e2019-10-22 13:39:14 +0800285 mmio_write_64(PLAT_SEC_ENTRY, sec_entrypoint);
Hadi Asyrafi616da772019-06-27 11:34:03 +0800286 *psci_ops = &socfpga_psci_pm_ops;
Hadi Asyrafia2edf0e2019-10-22 13:39:14 +0800287
Hadi Asyrafi616da772019-06-27 11:34:03 +0800288 return 0;
289}