xref: /arm-trusted-firmware/plat/arm/board/a5ds/a5ds_pm.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2019, Arm Limited. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu #include <assert.h>
7*91f16700Schasinglulu #include <drivers/arm/gicv2.h>
8*91f16700Schasinglulu #include <lib/psci/psci.h>
9*91f16700Schasinglulu #include <plat/arm/common/plat_arm.h>
10*91f16700Schasinglulu #include <plat/common/platform.h>
11*91f16700Schasinglulu 
12*91f16700Schasinglulu /*******************************************************************************
13*91f16700Schasinglulu  * Platform handler called when a power domain is about to be turned on. The
14*91f16700Schasinglulu  * mpidr determines the CPU to be turned on.
15*91f16700Schasinglulu  ******************************************************************************/
16*91f16700Schasinglulu static int a5ds_pwr_domain_on(u_register_t mpidr)
17*91f16700Schasinglulu {
18*91f16700Schasinglulu 	unsigned int pos = plat_core_pos_by_mpidr(mpidr);
19*91f16700Schasinglulu 	uint64_t *hold_base = (uint64_t *)A5DS_HOLD_BASE;
20*91f16700Schasinglulu 
21*91f16700Schasinglulu 	hold_base[pos] = A5DS_HOLD_STATE_GO;
22*91f16700Schasinglulu 	dsbish();
23*91f16700Schasinglulu 	sev();
24*91f16700Schasinglulu 
25*91f16700Schasinglulu 	return PSCI_E_SUCCESS;
26*91f16700Schasinglulu }
27*91f16700Schasinglulu 
28*91f16700Schasinglulu /*******************************************************************************
29*91f16700Schasinglulu  * Platform handler called when a power domain has just been powered on after
30*91f16700Schasinglulu  * being turned off earlier. The target_state encodes the low power state that
31*91f16700Schasinglulu  * each level has woken up from.
32*91f16700Schasinglulu  ******************************************************************************/
33*91f16700Schasinglulu void a5ds_pwr_domain_on_finish(const psci_power_state_t *target_state)
34*91f16700Schasinglulu {
35*91f16700Schasinglulu 	/* TODO: This setup is needed only after a cold boot*/
36*91f16700Schasinglulu 	gicv2_pcpu_distif_init();
37*91f16700Schasinglulu 
38*91f16700Schasinglulu 	/* Enable the gic cpu interface */
39*91f16700Schasinglulu 	gicv2_cpuif_enable();
40*91f16700Schasinglulu }
41*91f16700Schasinglulu 
42*91f16700Schasinglulu /*******************************************************************************
43*91f16700Schasinglulu  * Platform handler called when a power domain is about to be turned off. The
44*91f16700Schasinglulu  * target_state encodes the power state that each level should transition to.
45*91f16700Schasinglulu  * a5ds only has always-on power domain and there is no power control present.
46*91f16700Schasinglulu  ******************************************************************************/
47*91f16700Schasinglulu void a5ds_pwr_domain_off(const psci_power_state_t *target_state)
48*91f16700Schasinglulu {
49*91f16700Schasinglulu 	ERROR("CPU_OFF not supported on this platform\n");
50*91f16700Schasinglulu 	assert(false);
51*91f16700Schasinglulu 	panic();
52*91f16700Schasinglulu }
53*91f16700Schasinglulu 
54*91f16700Schasinglulu /*******************************************************************************
55*91f16700Schasinglulu  * Export the platform handlers via a5ds_psci_pm_ops. The ARM Standard
56*91f16700Schasinglulu  * platform layer will take care of registering the handlers with PSCI.
57*91f16700Schasinglulu  ******************************************************************************/
58*91f16700Schasinglulu plat_psci_ops_t a5ds_psci_pm_ops = {
59*91f16700Schasinglulu 	/* dummy struct */
60*91f16700Schasinglulu 	.validate_ns_entrypoint = NULL,
61*91f16700Schasinglulu 	.pwr_domain_on = a5ds_pwr_domain_on,
62*91f16700Schasinglulu 	.pwr_domain_on_finish = a5ds_pwr_domain_on_finish,
63*91f16700Schasinglulu 	.pwr_domain_off = a5ds_pwr_domain_off
64*91f16700Schasinglulu };
65*91f16700Schasinglulu 
66*91f16700Schasinglulu int __init plat_setup_psci_ops(uintptr_t sec_entrypoint,
67*91f16700Schasinglulu 				const plat_psci_ops_t **psci_ops)
68*91f16700Schasinglulu {
69*91f16700Schasinglulu 	uintptr_t *mailbox = (void *)A5DS_TRUSTED_MAILBOX_BASE;
70*91f16700Schasinglulu 	*mailbox = sec_entrypoint;
71*91f16700Schasinglulu 
72*91f16700Schasinglulu 	*psci_ops = &a5ds_psci_pm_ops;
73*91f16700Schasinglulu 
74*91f16700Schasinglulu 	return 0;
75*91f16700Schasinglulu }
76