xref: /rk3399_ARM-atf/plat/arm/board/corstone1000/common/corstone1000_pm.c (revision 1e967fb63ad1b581f0014554a6412d42a89a1cfc)
1 /*
2  * Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <lib/psci/psci.h>
8 #include <plat/arm/common/plat_arm.h>
9 #include <platform_def.h>
10 #include <plat/common/platform.h>
11 #ifdef CORSTONE1000_CORTEX_A320
12 #include <drivers/arm/gicv3.h>
13 #else
14 #include <drivers/arm/gicv2.h>
15 #endif
16 /*******************************************************************************
17  * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
18  * platform layer will take care of registering the handlers with PSCI.
19  ******************************************************************************/
20 
corstone1000_system_reset(void)21 static void corstone1000_system_reset(void)
22 {
23 
24 	uint32_t volatile * const watchdog_ctrl_reg = (uint32_t *) SECURE_WATCHDOG_ADDR_CTRL_REG;
25 	uint32_t volatile * const watchdog_val_reg = (uint32_t *) SECURE_WATCHDOG_ADDR_VAL_REG;
26 
27 	/*
28 	 * Disable GIC CPU interface to prevent pending interrupt
29 	 * from waking up the AP from WFI.
30 	 */
31 #ifdef CORSTONE1000_CORTEX_A320
32 	gicv3_cpuif_disable(plat_my_core_pos());
33 #else
34 	gicv2_cpuif_disable();
35 #endif
36 
37 	/* Flush and invalidate data cache */
38 	dcsw_op_all(DCCISW);
39 
40 	*(watchdog_val_reg) = SECURE_WATCHDOG_COUNTDOWN_VAL;
41 	*watchdog_ctrl_reg = SECURE_WATCHDOG_MASK_ENABLE;
42 }
43 
44 #if defined(CORSTONE1000_FVP_MULTICORE)
corstone1000_validate_ns_entrypoint(uintptr_t entrypoint)45 int corstone1000_validate_ns_entrypoint(uintptr_t entrypoint)
46 {
47 	/*
48 	 * Check if the non secure entrypoint lies within the non
49 	 * secure DRAM.
50 	 */
51 	if ((entrypoint >= ARM_NS_DRAM1_BASE) && (entrypoint < (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE))) {
52 		return PSCI_E_SUCCESS;
53 	}
54 	return PSCI_E_INVALID_ADDRESS;
55 }
56 
corstone1000_pwr_domain_on(u_register_t mpidr)57 int corstone1000_pwr_domain_on(u_register_t mpidr)
58 {
59 	int core_index = plat_core_pos_by_mpidr(mpidr);
60 	uint64_t *secondary_core_hold_base = (uint64_t *)CORSTONE1000_SECONDARY_CORE_HOLD_BASE;
61 
62 	/* Validate the core index */
63 	if (core_index < 0 || core_index > PLATFORM_CORE_COUNT) {
64 		return PSCI_E_INVALID_PARAMS;
65 	}
66 	secondary_core_hold_base[core_index] = CORSTONE1000_SECONDARY_CORE_STATE_GO;
67 	dsbish();
68 	sev();
69 
70 	return PSCI_E_SUCCESS;
71 }
72 
corstone1000_pwr_domain_on_finish(const psci_power_state_t * target_state)73 void corstone1000_pwr_domain_on_finish(const psci_power_state_t *target_state)
74 {
75 	(void)target_state;
76 }
77 #endif
78 
79 plat_psci_ops_t plat_arm_psci_pm_ops = {
80 #if defined(CORSTONE1000_FVP_MULTICORE)
81 	.pwr_domain_on = corstone1000_pwr_domain_on,
82 	.pwr_domain_on_finish = corstone1000_pwr_domain_on_finish,
83 	.validate_ns_entrypoint = corstone1000_validate_ns_entrypoint,
84 	.system_reset = corstone1000_system_reset,
85 #else
86 	.validate_ns_entrypoint = NULL,
87 	.system_reset = corstone1000_system_reset,
88 #endif
89 };
90 
plat_arm_psci_override_pm_ops(plat_psci_ops_t * ops)91 const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
92 {
93 	ops = &plat_arm_psci_pm_ops;
94 	return ops;
95 }
96