blob: 1bc30f10ded42e791618f2bb6e00533c70f36383 [file] [log] [blame]
Siva Durga Prasad Paladugufe4af662018-09-25 18:44:58 +05301/*
Michal Simek2a47faa2023-04-14 08:43:51 +02002 * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
Prasad Kummari7d0623a2023-06-09 14:32:00 +05303 * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
Siva Durga Prasad Paladugufe4af662018-09-25 18:44:58 +05304 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
Tejas Patel54d13192019-02-27 18:44:55 +05308#include <assert.h>
9#include <plat_arm.h>
Tejas Patel69409962018-12-14 00:55:29 -080010#include <plat_private.h>
Tejas Patel61717112019-02-27 18:44:57 +053011#include <pm_common.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000012#include <common/debug.h>
13#include <lib/mmio.h>
14#include <lib/psci/psci.h>
15#include <plat/common/platform.h>
Saeed Nowshadic5a1bda2019-12-08 23:35:35 -080016#include <plat/arm/common/plat_arm.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000017
Tejas Patel61717112019-02-27 18:44:57 +053018#include "pm_api_sys.h"
19#include "pm_client.h"
20
Siva Durga Prasad Paladugufe4af662018-09-25 18:44:58 +053021static uintptr_t versal_sec_entry;
22
Venkatesh Yadav Abbarapubde87592022-05-24 11:11:12 +053023static int32_t versal_pwr_domain_on(u_register_t mpidr)
Siva Durga Prasad Paladugufe4af662018-09-25 18:44:58 +053024{
Venkatesh Yadav Abbarapubde87592022-05-24 11:11:12 +053025 int32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
Tejas Patel61717112019-02-27 18:44:57 +053026 const struct pm_proc *proc;
Siva Durga Prasad Paladugufe4af662018-09-25 18:44:58 +053027
28 VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr);
29
Abhyuday Godhasaraf55a5cd2021-08-09 08:15:13 -070030 if (cpu_id == -1) {
Siva Durga Prasad Paladugufe4af662018-09-25 18:44:58 +053031 return PSCI_E_INTERN_FAIL;
Abhyuday Godhasaraf55a5cd2021-08-09 08:15:13 -070032 }
Siva Durga Prasad Paladugufe4af662018-09-25 18:44:58 +053033
Venkatesh Yadav Abbarapubde87592022-05-24 11:11:12 +053034 proc = pm_get_proc((uint32_t)cpu_id);
Siva Durga Prasad Paladugufe4af662018-09-25 18:44:58 +053035
Tejas Patel61717112019-02-27 18:44:57 +053036 /* Send request to PMC to wake up selected ACPU core */
Abhyuday Godhasaraf435a142021-08-20 00:04:33 -070037 (void)pm_req_wakeup(proc->node_id, (versal_sec_entry & 0xFFFFFFFFU) | 0x1U,
38 versal_sec_entry >> 32, 0, SECURE_FLAG);
Siva Durga Prasad Paladugufe4af662018-09-25 18:44:58 +053039
Tejas Patel61717112019-02-27 18:44:57 +053040 /* Clear power down request */
41 pm_client_wakeup(proc);
Siva Durga Prasad Paladugufe4af662018-09-25 18:44:58 +053042
43 return PSCI_E_SUCCESS;
44}
45
Tejas Patel54d13192019-02-27 18:44:55 +053046/**
47 * versal_pwr_domain_suspend() - This function sends request to PMC to suspend
Prasad Kummari7d0623a2023-06-09 14:32:00 +053048 * core.
49 * @target_state: Targated state.
Tejas Patel54d13192019-02-27 18:44:55 +053050 *
Tejas Patel54d13192019-02-27 18:44:55 +053051 */
52static void versal_pwr_domain_suspend(const psci_power_state_t *target_state)
53{
Venkatesh Yadav Abbarapubde87592022-05-24 11:11:12 +053054 uint32_t state;
55 uint32_t cpu_id = plat_my_core_pos();
Tejas Patel54d13192019-02-27 18:44:55 +053056 const struct pm_proc *proc = pm_get_proc(cpu_id);
57
Abhyuday Godhasara589afa52021-08-11 06:15:13 -070058 for (size_t i = 0U; i <= PLAT_MAX_PWR_LVL; i++) {
Tejas Patel54d13192019-02-27 18:44:55 +053059 VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
60 __func__, i, target_state->pwr_domain_state[i]);
Abhyuday Godhasaraf55a5cd2021-08-09 08:15:13 -070061 }
Tejas Patel54d13192019-02-27 18:44:55 +053062
63 plat_versal_gic_cpuif_disable();
64
Ravi Pateleafc8782019-06-21 05:00:49 -070065 if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
66 plat_versal_gic_save();
67 }
Tejas Patel54d13192019-02-27 18:44:55 +053068
69 state = target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE ?
70 PM_STATE_SUSPEND_TO_RAM : PM_STATE_CPU_IDLE;
71
72 /* Send request to PMC to suspend this core */
Abhyuday Godhasaraf435a142021-08-20 00:04:33 -070073 (void)pm_self_suspend(proc->node_id, MAX_LATENCY, state, versal_sec_entry,
74 SECURE_FLAG);
Tejas Patel54d13192019-02-27 18:44:55 +053075
76 /* APU is to be turned off */
77 if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
78 /* disable coherency */
79 plat_arm_interconnect_exit_coherency();
80 }
81}
82
83/**
84 * versal_pwr_domain_suspend_finish() - This function performs actions to finish
Prasad Kummari7d0623a2023-06-09 14:32:00 +053085 * suspend procedure.
86 * @target_state: Targated state.
Tejas Patel54d13192019-02-27 18:44:55 +053087 *
Tejas Patel54d13192019-02-27 18:44:55 +053088 */
89static void versal_pwr_domain_suspend_finish(
90 const psci_power_state_t *target_state)
91{
Venkatesh Yadav Abbarapubde87592022-05-24 11:11:12 +053092 uint32_t cpu_id = plat_my_core_pos();
Tejas Patel54d13192019-02-27 18:44:55 +053093 const struct pm_proc *proc = pm_get_proc(cpu_id);
94
Abhyuday Godhasara589afa52021-08-11 06:15:13 -070095 for (size_t i = 0U; i <= PLAT_MAX_PWR_LVL; i++) {
Tejas Patel54d13192019-02-27 18:44:55 +053096 VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
97 __func__, i, target_state->pwr_domain_state[i]);
Abhyuday Godhasaraf55a5cd2021-08-09 08:15:13 -070098 }
Tejas Patel54d13192019-02-27 18:44:55 +053099
100 /* Clear the APU power control register for this cpu */
101 pm_client_wakeup(proc);
102
103 /* enable coherency */
104 plat_arm_interconnect_enter_coherency();
105
106 /* APU was turned off, so restore GIC context */
107 if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
108 plat_versal_gic_resume();
Tejas Patel54d13192019-02-27 18:44:55 +0530109 }
Ravi Pateleafc8782019-06-21 05:00:49 -0700110
111 plat_versal_gic_cpuif_enable();
Tejas Patel54d13192019-02-27 18:44:55 +0530112}
113
Siva Durga Prasad Paladugufe4af662018-09-25 18:44:58 +0530114void versal_pwr_domain_on_finish(const psci_power_state_t *target_state)
115{
116 /* Enable the gic cpu interface */
117 plat_versal_gic_pcpu_init();
118
119 /* Program the gic per-cpu distributor or re-distributor interface */
120 plat_versal_gic_cpuif_enable();
121}
122
Tejas Patel54d13192019-02-27 18:44:55 +0530123/**
Prasad Kummari7d0623a2023-06-09 14:32:00 +0530124 * versal_system_off() - This function sends the system off request to firmware.
125 * This function does not return.
126 *
Saeed Nowshadic5a1bda2019-12-08 23:35:35 -0800127 */
128static void __dead2 versal_system_off(void)
129{
130 /* Send the power down request to the PMC */
Abhyuday Godhasaraf435a142021-08-20 00:04:33 -0700131 (void)pm_system_shutdown(XPM_SHUTDOWN_TYPE_SHUTDOWN,
132 pm_get_shutdown_scope(), SECURE_FLAG);
Saeed Nowshadic5a1bda2019-12-08 23:35:35 -0800133
Abhyuday Godhasaraf55a5cd2021-08-09 08:15:13 -0700134 while (1) {
Saeed Nowshadic5a1bda2019-12-08 23:35:35 -0800135 wfi();
Abhyuday Godhasaraf55a5cd2021-08-09 08:15:13 -0700136 }
Saeed Nowshadic5a1bda2019-12-08 23:35:35 -0800137}
138
139/**
Prasad Kummari7d0623a2023-06-09 14:32:00 +0530140 * versal_system_reset() - This function sends the reset request to firmware
141 * for the system to reset. This function does not
142 * return.
143 *
Saeed Nowshadic5a1bda2019-12-08 23:35:35 -0800144 */
145static void __dead2 versal_system_reset(void)
146{
147 /* Send the system reset request to the PMC */
Abhyuday Godhasaraf435a142021-08-20 00:04:33 -0700148 (void)pm_system_shutdown(XPM_SHUTDOWN_TYPE_RESET,
149 pm_get_shutdown_scope(), SECURE_FLAG);
Saeed Nowshadic5a1bda2019-12-08 23:35:35 -0800150
Abhyuday Godhasaraf55a5cd2021-08-09 08:15:13 -0700151 while (1) {
Saeed Nowshadic5a1bda2019-12-08 23:35:35 -0800152 wfi();
Abhyuday Godhasaraf55a5cd2021-08-09 08:15:13 -0700153 }
Saeed Nowshadic5a1bda2019-12-08 23:35:35 -0800154}
155
156/**
Prasad Kummari7d0623a2023-06-09 14:32:00 +0530157 * versal_pwr_domain_off() - This function performs actions to turn off core.
158 * @target_state: Targated state.
Tejas Patel54d13192019-02-27 18:44:55 +0530159 *
Tejas Patel54d13192019-02-27 18:44:55 +0530160 */
161static void versal_pwr_domain_off(const psci_power_state_t *target_state)
162{
Venkatesh Yadav Abbarapubde87592022-05-24 11:11:12 +0530163 uint32_t cpu_id = plat_my_core_pos();
Tejas Patel54d13192019-02-27 18:44:55 +0530164 const struct pm_proc *proc = pm_get_proc(cpu_id);
165
Abhyuday Godhasara589afa52021-08-11 06:15:13 -0700166 for (size_t i = 0U; i <= PLAT_MAX_PWR_LVL; i++) {
Tejas Patel54d13192019-02-27 18:44:55 +0530167 VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
168 __func__, i, target_state->pwr_domain_state[i]);
Abhyuday Godhasaraf55a5cd2021-08-09 08:15:13 -0700169 }
Tejas Patel54d13192019-02-27 18:44:55 +0530170
171 /* Prevent interrupts from spuriously waking up this cpu */
172 plat_versal_gic_cpuif_disable();
173
174 /*
175 * Send request to PMC to power down the appropriate APU CPU
176 * core.
177 * According to PSCI specification, CPU_off function does not
178 * have resume address and CPU core can only be woken up
179 * invoking CPU_on function, during which resume address will
180 * be set.
181 */
Abhyuday Godhasaraf435a142021-08-20 00:04:33 -0700182 (void)pm_self_suspend(proc->node_id, MAX_LATENCY, PM_STATE_CPU_IDLE, 0,
183 SECURE_FLAG);
Tejas Patel54d13192019-02-27 18:44:55 +0530184}
185
186/**
187 * versal_validate_power_state() - This function ensures that the power state
Prasad Kummari7d0623a2023-06-09 14:32:00 +0530188 * parameter in request is valid.
189 * @power_state: Power state of core.
190 * @req_state: Requested state.
Tejas Patel54d13192019-02-27 18:44:55 +0530191 *
Prasad Kummari7d0623a2023-06-09 14:32:00 +0530192 * Return: Returns status, either success or reason.
Tejas Patel54d13192019-02-27 18:44:55 +0530193 *
Tejas Patel54d13192019-02-27 18:44:55 +0530194 */
Venkatesh Yadav Abbarapubde87592022-05-24 11:11:12 +0530195static int32_t versal_validate_power_state(uint32_t power_state,
Tejas Patel54d13192019-02-27 18:44:55 +0530196 psci_power_state_t *req_state)
197{
198 VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
199
Venkatesh Yadav Abbarapubde87592022-05-24 11:11:12 +0530200 uint32_t pstate = psci_get_pstate_type(power_state);
Tejas Patel54d13192019-02-27 18:44:55 +0530201
202 assert(req_state);
203
204 /* Sanity check the requested state */
Abhyuday Godhasaraf55a5cd2021-08-09 08:15:13 -0700205 if (pstate == PSTATE_TYPE_STANDBY) {
Tejas Patel54d13192019-02-27 18:44:55 +0530206 req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE;
Abhyuday Godhasaraf55a5cd2021-08-09 08:15:13 -0700207 } else {
Tejas Patel54d13192019-02-27 18:44:55 +0530208 req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE;
Abhyuday Godhasaraf55a5cd2021-08-09 08:15:13 -0700209 }
Tejas Patel54d13192019-02-27 18:44:55 +0530210
211 /* We expect the 'state id' to be zero */
Abhyuday Godhasarabacbdee2021-08-20 00:27:03 -0700212 if (psci_get_pstate_id(power_state) != 0U) {
Tejas Patel54d13192019-02-27 18:44:55 +0530213 return PSCI_E_INVALID_PARAMS;
Abhyuday Godhasaraf55a5cd2021-08-09 08:15:13 -0700214 }
Tejas Patel54d13192019-02-27 18:44:55 +0530215
216 return PSCI_E_SUCCESS;
217}
218
219/**
Prasad Kummari7d0623a2023-06-09 14:32:00 +0530220 * versal_get_sys_suspend_power_state() - Get power state for system suspend.
221 * @req_state: Requested state.
Tejas Patel54d13192019-02-27 18:44:55 +0530222 *
Tejas Patel54d13192019-02-27 18:44:55 +0530223 */
224static void versal_get_sys_suspend_power_state(psci_power_state_t *req_state)
225{
226 req_state->pwr_domain_state[PSCI_CPU_PWR_LVL] = PLAT_MAX_OFF_STATE;
227 req_state->pwr_domain_state[1] = PLAT_MAX_OFF_STATE;
228}
229
Siva Durga Prasad Paladugufe4af662018-09-25 18:44:58 +0530230static const struct plat_psci_ops versal_nopmc_psci_ops = {
Tejas Patel61717112019-02-27 18:44:57 +0530231 .pwr_domain_on = versal_pwr_domain_on,
Tejas Patel54d13192019-02-27 18:44:55 +0530232 .pwr_domain_off = versal_pwr_domain_off,
Siva Durga Prasad Paladugufe4af662018-09-25 18:44:58 +0530233 .pwr_domain_on_finish = versal_pwr_domain_on_finish,
Tejas Patel54d13192019-02-27 18:44:55 +0530234 .pwr_domain_suspend = versal_pwr_domain_suspend,
235 .pwr_domain_suspend_finish = versal_pwr_domain_suspend_finish,
Saeed Nowshadic5a1bda2019-12-08 23:35:35 -0800236 .system_off = versal_system_off,
237 .system_reset = versal_system_reset,
Tejas Patel54d13192019-02-27 18:44:55 +0530238 .validate_power_state = versal_validate_power_state,
239 .get_sys_suspend_power_state = versal_get_sys_suspend_power_state,
Siva Durga Prasad Paladugufe4af662018-09-25 18:44:58 +0530240};
241
242/*******************************************************************************
243 * Export the platform specific power ops.
244 ******************************************************************************/
Venkatesh Yadav Abbarapu2cefbcd2022-07-31 14:05:40 +0530245int32_t plat_setup_psci_ops(uintptr_t sec_entrypoint,
Siva Durga Prasad Paladugufe4af662018-09-25 18:44:58 +0530246 const struct plat_psci_ops **psci_ops)
247{
248 versal_sec_entry = sec_entrypoint;
249
250 *psci_ops = &versal_nopmc_psci_ops;
251
252 return 0;
253}