summaryrefslogtreecommitdiff
path: root/plat/imx/imx8qm
diff options
context:
space:
mode:
authorAnson Huang <Anson.Huang@nxp.com>2017-10-20 00:55:04 +0800
committerAbel Vesa <abel.vesa@nxp.com>2018-06-11 10:08:40 +0300
commit905204763cb18b899b261fe893dd6e889e0fcb8d (patch)
treeec4bff34928db1887bfc45dd5b3f3bca6522852f /plat/imx/imx8qm
parenteaf27aaa2334ba02199ceeec509146dc9b775ae0 (diff)
imx8qm: add cluster power on/off for cpu hot-plug and suspend
When doing cpu hot-plug, if all CPUs in same cluster are off, then this cluster's power and CCI port can be also turned off to save power. Also add cluster and CCI low power mode request to SCFW. Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
Diffstat (limited to 'plat/imx/imx8qm')
-rw-r--r--plat/imx/imx8qm/imx8qm_psci.c39
-rw-r--r--plat/imx/imx8qm/platform.mk1
2 files changed, 25 insertions, 15 deletions
diff --git a/plat/imx/imx8qm/imx8qm_psci.c b/plat/imx/imx8qm/imx8qm_psci.c
index fc36216f..0f5012c7 100644
--- a/plat/imx/imx8qm/imx8qm_psci.c
+++ b/plat/imx/imx8qm/imx8qm_psci.c
@@ -55,13 +55,8 @@ const static int ap_core_index[PLATFORM_CORE_COUNT] = {
SC_R_A53_3, SC_R_A72_0, SC_R_A72_1,
};
-plat_local_state_t plat_get_target_pwr_state(unsigned int lvl,
- const plat_local_state_t *target_state,
- unsigned int ncpu)
-{
- /* TODO */
- return 0;
-}
+static unsigned int a53_cpu_on_number;
+static unsigned int a72_cpu_on_number;
int imx_pwr_domain_on(u_register_t mpidr)
{
@@ -74,6 +69,9 @@ int imx_pwr_domain_on(u_register_t mpidr)
tf_printf("imx_pwr_domain_on cluster_id %d, cpu_id %d\n", cluster_id, cpu_id);
if (cluster_id == 0) {
+ if (a53_cpu_on_number == 0)
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_ON);
+
if (sc_pm_set_resource_power_mode(ipc_handle, ap_core_index[cpu_id],
SC_PM_PW_MODE_ON) != SC_ERR_NONE) {
ERROR("cluster0 core %d power on failed!\n", cpu_id);
@@ -86,11 +84,8 @@ int imx_pwr_domain_on(u_register_t mpidr)
ret = PSCI_E_INTERN_FAIL;
}
} else {
- if (sc_pm_set_resource_power_mode(ipc_handle, SC_R_A72,
- SC_PM_PW_MODE_ON) != SC_ERR_NONE) {
- ERROR(" cluster1 power on failed!\n");
- ret = PSCI_E_INTERN_FAIL;
- }
+ if (a72_cpu_on_number == 0)
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON);
if (sc_pm_set_resource_power_mode(ipc_handle, ap_core_index[cpu_id + 4],
SC_PM_PW_MODE_ON) != SC_ERR_NONE) {
@@ -114,8 +109,10 @@ void imx_pwr_domain_on_finish(const psci_power_state_t *target_state)
unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
- if (cluster_id == 1 && cpu_id == 0)
- cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+ if (cluster_id == 0 && a53_cpu_on_number++ == 0)
+ cci_enable_snoop_dvm_reqs(0);
+ if (cluster_id == 1 && a72_cpu_on_number++ == 0)
+ cci_enable_snoop_dvm_reqs(1);
/* program the GIC per cpu dist and rdist interface */
plat_gic_pcpu_init();
@@ -144,7 +141,6 @@ void imx_pwr_domain_off(const psci_power_state_t *target_state)
if (--a72_cpu_on_number == 0)
cci_disable_snoop_dvm_reqs(1);
}
-
tf_printf("turn off cluster:%d core:%d\n", cluster_id, cpu_id);
}
@@ -267,9 +263,22 @@ static const plat_psci_ops_t imx_plat_psci_ops = {
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
const plat_psci_ops_t **psci_ops)
{
+ uint64_t mpidr = read_mpidr_el1();
+ unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+
imx_mailbox_init(sec_entrypoint);
/* sec_entrypoint is used for warm reset */
*psci_ops = &imx_plat_psci_ops;
+ if (cluster_id == 0)
+ a53_cpu_on_number++;
+ else
+ a72_cpu_on_number++;
+
+ /* request low power mode for cluster/cci, only need to do once */
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_OFF);
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_OFF);
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_OFF);
+
return 0;
}
diff --git a/plat/imx/imx8qm/platform.mk b/plat/imx/imx8qm/platform.mk
index e68bfca1..d12c1a45 100644
--- a/plat/imx/imx8qm/platform.mk
+++ b/plat/imx/imx8qm/platform.mk
@@ -36,6 +36,7 @@ PLAT_GIC_SOURCES := drivers/arm/gic/v3/gicv3_helpers.c \
drivers/arm/gic/v3/gicv3_main.c \
drivers/arm/gic/common/gic_common.c \
plat/common/plat_gicv3.c \
+ plat/common/plat_psci_common.c \
plat/imx/common/plat_imx8_gic.c
BL31_SOURCES += plat/imx/common/lpuart_console.S \