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