xref: /rk3399_ARM-atf/plat/imx/imx8qm/imx8qm_psci.c (revision 0f53bca05c5e24a740fa4f8d15ca003ce9bb0d54)
1baa7650bSAnson Huang /*
2baa7650bSAnson Huang  * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
3baa7650bSAnson Huang  *
4baa7650bSAnson Huang  * SPDX-License-Identifier: BSD-3-Clause
5baa7650bSAnson Huang  */
6baa7650bSAnson Huang 
7baa7650bSAnson Huang #include <arch.h>
8baa7650bSAnson Huang #include <arch_helpers.h>
9baa7650bSAnson Huang #include <cci.h>
10baa7650bSAnson Huang #include <debug.h>
11baa7650bSAnson Huang #include <gicv3.h>
12baa7650bSAnson Huang #include <mmio.h>
13baa7650bSAnson Huang #include <plat_imx8.h>
14baa7650bSAnson Huang #include <psci.h>
15baa7650bSAnson Huang #include <sci/sci.h>
16baa7650bSAnson Huang #include <stdbool.h>
17baa7650bSAnson Huang 
18baa7650bSAnson Huang const static int ap_core_index[PLATFORM_CORE_COUNT] = {
19baa7650bSAnson Huang 	SC_R_A53_0, SC_R_A53_1, SC_R_A53_2,
20baa7650bSAnson Huang 	SC_R_A53_3, SC_R_A72_0, SC_R_A72_1,
21baa7650bSAnson Huang };
22baa7650bSAnson Huang 
23baa7650bSAnson Huang /* need to enable USE_COHERENT_MEM to avoid coherence issue */
24baa7650bSAnson Huang #if USE_COHERENT_MEM
25baa7650bSAnson Huang static unsigned int a53_cpu_on_number __section("tzfw_coherent_mem");
26baa7650bSAnson Huang static unsigned int a72_cpu_on_number __section("tzfw_coherent_mem");
27baa7650bSAnson Huang #endif
28baa7650bSAnson Huang 
29baa7650bSAnson Huang int imx_pwr_domain_on(u_register_t mpidr)
30baa7650bSAnson Huang {
31baa7650bSAnson Huang 	int ret = PSCI_E_SUCCESS;
32baa7650bSAnson Huang 	unsigned int cluster_id, cpu_id;
33baa7650bSAnson Huang 
34baa7650bSAnson Huang 	cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
35baa7650bSAnson Huang 	cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
36baa7650bSAnson Huang 
37baa7650bSAnson Huang 	tf_printf("imx_pwr_domain_on cluster_id %d, cpu_id %d\n", cluster_id, cpu_id);
38baa7650bSAnson Huang 
39baa7650bSAnson Huang 	if (cluster_id == 0) {
40baa7650bSAnson Huang 		if (a53_cpu_on_number == 0)
41baa7650bSAnson Huang 			sc_pm_set_resource_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_ON);
42baa7650bSAnson Huang 
43baa7650bSAnson Huang 		if (sc_pm_set_resource_power_mode(ipc_handle, ap_core_index[cpu_id],
44baa7650bSAnson Huang 			SC_PM_PW_MODE_ON) != SC_ERR_NONE) {
45baa7650bSAnson Huang 			ERROR("cluster0 core %d power on failed!\n", cpu_id);
46baa7650bSAnson Huang 			ret = PSCI_E_INTERN_FAIL;
47baa7650bSAnson Huang 		}
48baa7650bSAnson Huang 
49baa7650bSAnson Huang 		if (sc_pm_cpu_start(ipc_handle, ap_core_index[cpu_id],
50baa7650bSAnson Huang 			true, BL31_BASE) != SC_ERR_NONE) {
51baa7650bSAnson Huang 			ERROR("boot cluster0 core %d failed!\n", cpu_id);
52baa7650bSAnson Huang 			ret = PSCI_E_INTERN_FAIL;
53baa7650bSAnson Huang 		}
54baa7650bSAnson Huang 	} else {
55baa7650bSAnson Huang 		if (a72_cpu_on_number == 0)
56baa7650bSAnson Huang 			sc_pm_set_resource_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON);
57baa7650bSAnson Huang 
58baa7650bSAnson Huang 		if (sc_pm_set_resource_power_mode(ipc_handle, ap_core_index[cpu_id + 4],
59baa7650bSAnson Huang 			SC_PM_PW_MODE_ON) != SC_ERR_NONE) {
60baa7650bSAnson Huang 			ERROR(" cluster1 core %d power on failed!\n", cpu_id);
61baa7650bSAnson Huang 			ret = PSCI_E_INTERN_FAIL;
62baa7650bSAnson Huang 		}
63baa7650bSAnson Huang 
64baa7650bSAnson Huang 		if (sc_pm_cpu_start(ipc_handle, ap_core_index[cpu_id + 4],
65baa7650bSAnson Huang 			true, BL31_BASE) != SC_ERR_NONE) {
66baa7650bSAnson Huang 			ERROR("boot cluster1 core %d failed!\n", cpu_id);
67baa7650bSAnson Huang 			ret = PSCI_E_INTERN_FAIL;
68baa7650bSAnson Huang 		}
69baa7650bSAnson Huang 	}
70baa7650bSAnson Huang 
71baa7650bSAnson Huang 	return ret;
72baa7650bSAnson Huang }
73baa7650bSAnson Huang 
74baa7650bSAnson Huang void imx_pwr_domain_on_finish(const psci_power_state_t *target_state)
75baa7650bSAnson Huang {
76baa7650bSAnson Huang 	uint64_t mpidr = read_mpidr_el1();
77baa7650bSAnson Huang 	unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
78baa7650bSAnson Huang 
79baa7650bSAnson Huang 	if (cluster_id == 0 && a53_cpu_on_number++ == 0)
80baa7650bSAnson Huang 		cci_enable_snoop_dvm_reqs(0);
81baa7650bSAnson Huang 	if (cluster_id == 1 && a72_cpu_on_number++ == 0)
82baa7650bSAnson Huang 		cci_enable_snoop_dvm_reqs(1);
83baa7650bSAnson Huang 
84baa7650bSAnson Huang 	plat_gic_pcpu_init();
85baa7650bSAnson Huang 	plat_gic_cpuif_enable();
86baa7650bSAnson Huang }
87baa7650bSAnson Huang 
88*0f53bca0SAnson Huang void imx_pwr_domain_off(const psci_power_state_t *target_state)
89*0f53bca0SAnson Huang {
90*0f53bca0SAnson Huang 	u_register_t mpidr = read_mpidr_el1();
91*0f53bca0SAnson Huang 	unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
92*0f53bca0SAnson Huang 	unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
93*0f53bca0SAnson Huang 
94*0f53bca0SAnson Huang 	plat_gic_cpuif_disable();
95*0f53bca0SAnson Huang 	if (cluster_id == 0) {
96*0f53bca0SAnson Huang 		sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
97*0f53bca0SAnson Huang 			SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_NONE);
98*0f53bca0SAnson Huang 		if (--a53_cpu_on_number == 0)
99*0f53bca0SAnson Huang 			cci_disable_snoop_dvm_reqs(0);
100*0f53bca0SAnson Huang 	} else {
101*0f53bca0SAnson Huang 		sc_pm_req_cpu_low_power_mode(ipc_handle,
102*0f53bca0SAnson Huang 			ap_core_index[cpu_id + 4],
103*0f53bca0SAnson Huang 			SC_PM_PW_MODE_OFF,
104*0f53bca0SAnson Huang 			SC_PM_WAKE_SRC_NONE);
105*0f53bca0SAnson Huang 		if (--a72_cpu_on_number == 0)
106*0f53bca0SAnson Huang 			cci_disable_snoop_dvm_reqs(1);
107*0f53bca0SAnson Huang 	}
108*0f53bca0SAnson Huang 	tf_printf("turn off cluster:%d core:%d\n", cluster_id, cpu_id);
109*0f53bca0SAnson Huang }
110*0f53bca0SAnson Huang 
111baa7650bSAnson Huang int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
112baa7650bSAnson Huang {
113baa7650bSAnson Huang 	return PSCI_E_SUCCESS;
114baa7650bSAnson Huang }
115baa7650bSAnson Huang 
116baa7650bSAnson Huang static const plat_psci_ops_t imx_plat_psci_ops = {
117baa7650bSAnson Huang 	.pwr_domain_on = imx_pwr_domain_on,
118baa7650bSAnson Huang 	.pwr_domain_on_finish = imx_pwr_domain_on_finish,
119*0f53bca0SAnson Huang 	.pwr_domain_off = imx_pwr_domain_off,
120baa7650bSAnson Huang 	.validate_ns_entrypoint = imx_validate_ns_entrypoint,
121db81c592SAnson Huang 	.system_off = imx_system_off,
122d31ffcf0SAnson Huang 	.system_reset = imx_system_reset,
123baa7650bSAnson Huang };
124baa7650bSAnson Huang 
125baa7650bSAnson Huang int plat_setup_psci_ops(uintptr_t sec_entrypoint,
126baa7650bSAnson Huang 			const plat_psci_ops_t **psci_ops)
127baa7650bSAnson Huang {
128baa7650bSAnson Huang 	uint64_t mpidr = read_mpidr_el1();
129baa7650bSAnson Huang 	unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
130baa7650bSAnson Huang 
131baa7650bSAnson Huang 	imx_mailbox_init(sec_entrypoint);
132baa7650bSAnson Huang 	*psci_ops = &imx_plat_psci_ops;
133baa7650bSAnson Huang 
134baa7650bSAnson Huang 	if (cluster_id == 0)
135baa7650bSAnson Huang 		a53_cpu_on_number++;
136baa7650bSAnson Huang 	else
137baa7650bSAnson Huang 		a72_cpu_on_number++;
138baa7650bSAnson Huang 
139baa7650bSAnson Huang 	return 0;
140baa7650bSAnson Huang }
141