From: Park Bumgyu Date: Tue, 3 May 2016 10:23:54 +0000 (+0900) Subject: [COMMON] arm64: kernel: Support customized suspend finisher X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=beeca32d9f7866a847d03212f797c8f874b9ebce;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [COMMON] arm64: kernel: Support customized suspend finisher We hope that PSCI framework cover the all platform specific power states, unfortunately PSCI can support only state managed by cpuidle. Hence it is not correspond on Exynos. psci_suspend_customized_finisher supports extra power state which cpuidle does not handle such as system sleep, system idle clock down and cluster power down. Change-Id: I970f5ec2477de8e3fea2e10528bfc564b584c144 Signed-off-by: Park Bumgyu Signed-off-by: Youngtae Lee --- diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c index b7244b7b4507..2d7557c77e4b 100644 --- a/drivers/firmware/psci.c +++ b/drivers/firmware/psci.c @@ -422,6 +422,41 @@ static u32 psci_power_state_pack(u32 id, u32 type, u32 affinity_level) & PSCI_0_2_POWER_STATE_AFFL_MASK); } +/** + * We hope that PSCI framework cover the all platform specific power + * states, unfortunately PSCI can support only state managed by cpuidle. + * psci_suspend_customized_finisher supports extra power state which + * cpuidle does not handle. This function is only for Exynos. + */ +static int psci_suspend_customized_finisher(unsigned long index) +{ + u32 state; + + switch (index) { + case PSCI_CLUSTER_SLEEP: + state = psci_power_state_pack(0, 0, 1); + break; + case PSCI_SYSTEM_IDLE: + case PSCI_SYSTEM_IDLE_AUDIO: + state = psci_power_state_pack(1, 0, 0); + break; + case PSCI_SYSTEM_IDLE_CLUSTER_SLEEP: + state = psci_power_state_pack(1, 0, 1); + break; + case PSCI_CP_CALL: + state = psci_power_state_pack(0, 0, 2); + break; + case PSCI_SYSTEM_SLEEP: + state = psci_power_state_pack(0, 0, 3); + break; + default: + panic("Unsupported psci state, index = %ld\n", index); + break; + }; + + return psci_ops.cpu_suspend(state, virt_to_phys(cpu_resume)); +} + int psci_cpu_suspend_enter(unsigned long index) { int ret; @@ -433,6 +468,9 @@ int psci_cpu_suspend_enter(unsigned long index) if (WARN_ON_ONCE(!index)) return -EINVAL; + if (unlikely(index >= PSCI_UNUSED_INDEX)) + return cpu_suspend(index, psci_suspend_customized_finisher); + if (!psci_power_state_loses_context(state[index - 1])) ret = psci_ops.cpu_suspend(state[index - 1], 0); else diff --git a/include/linux/psci.h b/include/linux/psci.h index 347077cf19c6..99095024eb86 100644 --- a/include/linux/psci.h +++ b/include/linux/psci.h @@ -17,6 +17,14 @@ #include #include +#define PSCI_UNUSED_INDEX 128 +#define PSCI_CLUSTER_SLEEP (PSCI_UNUSED_INDEX) +#define PSCI_SYSTEM_IDLE (PSCI_UNUSED_INDEX + 1) +#define PSCI_SYSTEM_IDLE_CLUSTER_SLEEP (PSCI_UNUSED_INDEX + 2) +#define PSCI_SYSTEM_IDLE_AUDIO (PSCI_UNUSED_INDEX + 3) +#define PSCI_CP_CALL (PSCI_UNUSED_INDEX + 4) +#define PSCI_SYSTEM_SLEEP (PSCI_UNUSED_INDEX + 5) + #define PSCI_POWER_STATE_TYPE_STANDBY 0 #define PSCI_POWER_STATE_TYPE_POWER_DOWN 1