This pull request contains patches that enable PSCI 1.0 firmware
features for arm/arm64 platforms: - Lorenzo Pieralisi adds support for the PSCI_FEATURES call, manages various 1.0 specifications updates (power state id and functions return values) and provides PSCI v1.0 DT bindings - Sudeep Holla implements PSCI v1.0 system suspend support to enable PSCI based suspend-to-RAM -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJWEmNwAAoJEIKLOaai0TZ/unUP/1+90ySUHIChaH70WrvIqJ3Z YfueoM63cOcRNB7EFx5SrcKWh6tFgeUsT2+4WDA8j0CIvRwO6YaESvtXRHmGfwgQ F3NWlWnJF3xiCU0kg26YQjvNll9OgQXkwCLzbsk1cdpi8hMfVL4Du8DgjREVIDff PZ4LiGlYSqvesp+kipXzfAHgHJENXJYISkRv2VwcewOnq28B/Iode3T6Ro8dSjeR 2C9hjZsrwtRZ2lpjU2/4nLMd+On+nA9fw7XhlH/FU8HeLcNlngeQghlA30uQsIxB 1wgBEzHohBqUSSMLPSrk1nca/JV5haSeZWGacdLQ/qLUeMV9TgAB8wAXayVXUoHN kkSoNWf5lh8ica4BkSGEPun4GY4h3Uv0AhnwCCKiVWL1eXglVklT4QRDVlyBPdXY nWpRN5RlQLf60Zf6vZrUoRsApy1WVFGWW+GbjBKlWWImCzEDaIJ3695C7Qmj3BJ+ 4mSqKE0xkQ8M8eYpS/ilKnmlh7+xNU3za9LtebV97v31+D9TNqvdXxEh0qGuasG4 BWGPptGlxqYH3RH5PrvjFGt0EZmyJ4uD/7doYrXFrXkiv/FX1tDzTAgIWswHeeG5 c4gAw/GlGq3d+oL/aydWlWW/UQYdmfLt2U+NZ3VdkVZVuF33VprJolBC8YQuQldS 2zvgsnflfrLeFayRtDf2 =rYJ6 -----END PGP SIGNATURE----- Merge tag 'firmware/psci-1.0' of git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux into next/drivers This pull request contains patches that enable PSCI 1.0 firmware features for arm/arm64 platforms: - Lorenzo Pieralisi adds support for the PSCI_FEATURES call, manages various 1.0 specifications updates (power state id and functions return values) and provides PSCI v1.0 DT bindings - Sudeep Holla implements PSCI v1.0 system suspend support to enable PSCI based suspend-to-RAM * tag 'firmware/psci-1.0' of git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux: drivers: firmware: psci: add system suspend support drivers: firmware: psci: define more generic PSCI_FN_NATIVE macro drivers: firmware: psci: add PSCI v1.0 DT bindings drivers: firmware: psci: add extended stateid power_state support drivers: firmware: psci: add PSCI_FEATURES call drivers: firmware: psci: move power_state handling to generic code drivers: firmware: psci: add INVALID_ADDRESS return value Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
825294cded
|
@ -31,6 +31,10 @@ Main node required properties:
|
|||
support, but are permitted to be present for compatibility with
|
||||
existing software when "arm,psci" is later in the compatible list.
|
||||
|
||||
* "arm,psci-1.0" : for implementations complying to PSCI 1.0. PSCI 1.0 is
|
||||
backward compatible with PSCI 0.2 with minor specification updates,
|
||||
as defined in the PSCI specification[2].
|
||||
|
||||
- method : The method of calling the PSCI firmware. Permitted
|
||||
values are:
|
||||
|
||||
|
@ -100,3 +104,5 @@ Case 3: PSCI v0.2 and PSCI v0.1.
|
|||
|
||||
[1] Kernel documentation - ARM idle states bindings
|
||||
Documentation/devicetree/bindings/arm/idle-states.txt
|
||||
[2] Power State Coordination Interface (PSCI) specification
|
||||
http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf
|
||||
|
|
|
@ -30,20 +30,6 @@
|
|||
#include <asm/smp_plat.h>
|
||||
#include <asm/suspend.h>
|
||||
|
||||
static bool psci_power_state_loses_context(u32 state)
|
||||
{
|
||||
return state & PSCI_0_2_POWER_STATE_TYPE_MASK;
|
||||
}
|
||||
|
||||
static bool psci_power_state_is_valid(u32 state)
|
||||
{
|
||||
const u32 valid_mask = PSCI_0_2_POWER_STATE_ID_MASK |
|
||||
PSCI_0_2_POWER_STATE_TYPE_MASK |
|
||||
PSCI_0_2_POWER_STATE_AFFL_MASK;
|
||||
|
||||
return !(state & ~valid_mask);
|
||||
}
|
||||
|
||||
static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
|
||||
|
||||
static int __maybe_unused cpu_psci_cpu_init_idle(unsigned int cpu)
|
||||
|
|
|
@ -20,23 +20,25 @@
|
|||
#include <linux/printk.h>
|
||||
#include <linux/psci.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#include <uapi/linux/psci.h>
|
||||
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/system_misc.h>
|
||||
#include <asm/smp_plat.h>
|
||||
#include <asm/suspend.h>
|
||||
|
||||
/*
|
||||
* While a 64-bit OS can make calls with SMC32 calling conventions, for some
|
||||
* calls it is necessary to use SMC64 to pass or return 64-bit values. For such
|
||||
* calls PSCI_0_2_FN_NATIVE(x) will choose the appropriate (native-width)
|
||||
* function ID.
|
||||
* calls it is necessary to use SMC64 to pass or return 64-bit values.
|
||||
* For such calls PSCI_FN_NATIVE(version, name) will choose the appropriate
|
||||
* (native-width) function ID.
|
||||
*/
|
||||
#ifdef CONFIG_64BIT
|
||||
#define PSCI_0_2_FN_NATIVE(name) PSCI_0_2_FN64_##name
|
||||
#define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN64_##name
|
||||
#else
|
||||
#define PSCI_0_2_FN_NATIVE(name) PSCI_0_2_FN_##name
|
||||
#define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN_##name
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -70,6 +72,41 @@ enum psci_function {
|
|||
|
||||
static u32 psci_function_id[PSCI_FN_MAX];
|
||||
|
||||
#define PSCI_0_2_POWER_STATE_MASK \
|
||||
(PSCI_0_2_POWER_STATE_ID_MASK | \
|
||||
PSCI_0_2_POWER_STATE_TYPE_MASK | \
|
||||
PSCI_0_2_POWER_STATE_AFFL_MASK)
|
||||
|
||||
#define PSCI_1_0_EXT_POWER_STATE_MASK \
|
||||
(PSCI_1_0_EXT_POWER_STATE_ID_MASK | \
|
||||
PSCI_1_0_EXT_POWER_STATE_TYPE_MASK)
|
||||
|
||||
static u32 psci_cpu_suspend_feature;
|
||||
|
||||
static inline bool psci_has_ext_power_state(void)
|
||||
{
|
||||
return psci_cpu_suspend_feature &
|
||||
PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK;
|
||||
}
|
||||
|
||||
bool psci_power_state_loses_context(u32 state)
|
||||
{
|
||||
const u32 mask = psci_has_ext_power_state() ?
|
||||
PSCI_1_0_EXT_POWER_STATE_TYPE_MASK :
|
||||
PSCI_0_2_POWER_STATE_TYPE_MASK;
|
||||
|
||||
return state & mask;
|
||||
}
|
||||
|
||||
bool psci_power_state_is_valid(u32 state)
|
||||
{
|
||||
const u32 valid_mask = psci_has_ext_power_state() ?
|
||||
PSCI_1_0_EXT_POWER_STATE_MASK :
|
||||
PSCI_0_2_POWER_STATE_MASK;
|
||||
|
||||
return !(state & ~valid_mask);
|
||||
}
|
||||
|
||||
static int psci_to_linux_errno(int errno)
|
||||
{
|
||||
switch (errno) {
|
||||
|
@ -78,6 +115,7 @@ static int psci_to_linux_errno(int errno)
|
|||
case PSCI_RET_NOT_SUPPORTED:
|
||||
return -EOPNOTSUPP;
|
||||
case PSCI_RET_INVALID_PARAMS:
|
||||
case PSCI_RET_INVALID_ADDRESS:
|
||||
return -EINVAL;
|
||||
case PSCI_RET_DENIED:
|
||||
return -EPERM;
|
||||
|
@ -134,7 +172,7 @@ static int psci_migrate(unsigned long cpuid)
|
|||
static int psci_affinity_info(unsigned long target_affinity,
|
||||
unsigned long lowest_affinity_level)
|
||||
{
|
||||
return invoke_psci_fn(PSCI_0_2_FN_NATIVE(AFFINITY_INFO),
|
||||
return invoke_psci_fn(PSCI_FN_NATIVE(0_2, AFFINITY_INFO),
|
||||
target_affinity, lowest_affinity_level, 0);
|
||||
}
|
||||
|
||||
|
@ -145,7 +183,7 @@ static int psci_migrate_info_type(void)
|
|||
|
||||
static unsigned long psci_migrate_info_up_cpu(void)
|
||||
{
|
||||
return invoke_psci_fn(PSCI_0_2_FN_NATIVE(MIGRATE_INFO_UP_CPU),
|
||||
return invoke_psci_fn(PSCI_FN_NATIVE(0_2, MIGRATE_INFO_UP_CPU),
|
||||
0, 0, 0);
|
||||
}
|
||||
|
||||
|
@ -181,6 +219,49 @@ static void psci_sys_poweroff(void)
|
|||
invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
|
||||
}
|
||||
|
||||
static int __init psci_features(u32 psci_func_id)
|
||||
{
|
||||
return invoke_psci_fn(PSCI_1_0_FN_PSCI_FEATURES,
|
||||
psci_func_id, 0, 0);
|
||||
}
|
||||
|
||||
static int psci_system_suspend(unsigned long unused)
|
||||
{
|
||||
return invoke_psci_fn(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND),
|
||||
virt_to_phys(cpu_resume), 0, 0);
|
||||
}
|
||||
|
||||
static int psci_system_suspend_enter(suspend_state_t state)
|
||||
{
|
||||
return cpu_suspend(0, psci_system_suspend);
|
||||
}
|
||||
|
||||
static const struct platform_suspend_ops psci_suspend_ops = {
|
||||
.valid = suspend_valid_only_mem,
|
||||
.enter = psci_system_suspend_enter,
|
||||
};
|
||||
|
||||
static void __init psci_init_system_suspend(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_SUSPEND))
|
||||
return;
|
||||
|
||||
ret = psci_features(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND));
|
||||
|
||||
if (ret != PSCI_RET_NOT_SUPPORTED)
|
||||
suspend_set_ops(&psci_suspend_ops);
|
||||
}
|
||||
|
||||
static void __init psci_init_cpu_suspend(void)
|
||||
{
|
||||
int feature = psci_features(psci_function_id[PSCI_FN_CPU_SUSPEND]);
|
||||
|
||||
if (feature != PSCI_RET_NOT_SUPPORTED)
|
||||
psci_cpu_suspend_feature = feature;
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect the presence of a resident Trusted OS which may cause CPU_OFF to
|
||||
* return DENIED (which would be fatal).
|
||||
|
@ -224,16 +305,17 @@ static void __init psci_init_migrate(void)
|
|||
static void __init psci_0_2_set_functions(void)
|
||||
{
|
||||
pr_info("Using standard PSCI v0.2 function IDs\n");
|
||||
psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_0_2_FN_NATIVE(CPU_SUSPEND);
|
||||
psci_function_id[PSCI_FN_CPU_SUSPEND] =
|
||||
PSCI_FN_NATIVE(0_2, CPU_SUSPEND);
|
||||
psci_ops.cpu_suspend = psci_cpu_suspend;
|
||||
|
||||
psci_function_id[PSCI_FN_CPU_OFF] = PSCI_0_2_FN_CPU_OFF;
|
||||
psci_ops.cpu_off = psci_cpu_off;
|
||||
|
||||
psci_function_id[PSCI_FN_CPU_ON] = PSCI_0_2_FN_NATIVE(CPU_ON);
|
||||
psci_function_id[PSCI_FN_CPU_ON] = PSCI_FN_NATIVE(0_2, CPU_ON);
|
||||
psci_ops.cpu_on = psci_cpu_on;
|
||||
|
||||
psci_function_id[PSCI_FN_MIGRATE] = PSCI_0_2_FN_NATIVE(MIGRATE);
|
||||
psci_function_id[PSCI_FN_MIGRATE] = PSCI_FN_NATIVE(0_2, MIGRATE);
|
||||
psci_ops.migrate = psci_migrate;
|
||||
|
||||
psci_ops.affinity_info = psci_affinity_info;
|
||||
|
@ -265,6 +347,10 @@ static int __init psci_probe(void)
|
|||
|
||||
psci_init_migrate();
|
||||
|
||||
psci_init_cpu_suspend();
|
||||
|
||||
psci_init_system_suspend();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -340,6 +426,7 @@ static int __init psci_0_1_init(struct device_node *np)
|
|||
static const struct of_device_id const psci_of_match[] __initconst = {
|
||||
{ .compatible = "arm,psci", .data = psci_0_1_init},
|
||||
{ .compatible = "arm,psci-0.2", .data = psci_0_2_init},
|
||||
{ .compatible = "arm,psci-1.0", .data = psci_0_2_init},
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#define PSCI_POWER_STATE_TYPE_POWER_DOWN 1
|
||||
|
||||
bool psci_tos_resident_on(int cpu);
|
||||
bool psci_power_state_loses_context(u32 state);
|
||||
bool psci_power_state_is_valid(u32 state);
|
||||
|
||||
struct psci_operations {
|
||||
int (*cpu_suspend)(u32 state, unsigned long entry_point);
|
||||
|
|
|
@ -46,6 +46,11 @@
|
|||
#define PSCI_0_2_FN64_MIGRATE PSCI_0_2_FN64(5)
|
||||
#define PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU PSCI_0_2_FN64(7)
|
||||
|
||||
#define PSCI_1_0_FN_PSCI_FEATURES PSCI_0_2_FN(10)
|
||||
#define PSCI_1_0_FN_SYSTEM_SUSPEND PSCI_0_2_FN(14)
|
||||
|
||||
#define PSCI_1_0_FN64_SYSTEM_SUSPEND PSCI_0_2_FN64(14)
|
||||
|
||||
/* PSCI v0.2 power state encoding for CPU_SUSPEND function */
|
||||
#define PSCI_0_2_POWER_STATE_ID_MASK 0xffff
|
||||
#define PSCI_0_2_POWER_STATE_ID_SHIFT 0
|
||||
|
@ -56,6 +61,13 @@
|
|||
#define PSCI_0_2_POWER_STATE_AFFL_MASK \
|
||||
(0x3 << PSCI_0_2_POWER_STATE_AFFL_SHIFT)
|
||||
|
||||
/* PSCI extended power state encoding for CPU_SUSPEND function */
|
||||
#define PSCI_1_0_EXT_POWER_STATE_ID_MASK 0xfffffff
|
||||
#define PSCI_1_0_EXT_POWER_STATE_ID_SHIFT 0
|
||||
#define PSCI_1_0_EXT_POWER_STATE_TYPE_SHIFT 30
|
||||
#define PSCI_1_0_EXT_POWER_STATE_TYPE_MASK \
|
||||
(0x1 << PSCI_1_0_EXT_POWER_STATE_TYPE_SHIFT)
|
||||
|
||||
/* PSCI v0.2 affinity level state returned by AFFINITY_INFO */
|
||||
#define PSCI_0_2_AFFINITY_LEVEL_ON 0
|
||||
#define PSCI_0_2_AFFINITY_LEVEL_OFF 1
|
||||
|
@ -76,6 +88,11 @@
|
|||
#define PSCI_VERSION_MINOR(ver) \
|
||||
((ver) & PSCI_VERSION_MINOR_MASK)
|
||||
|
||||
/* PSCI features decoding (>=1.0) */
|
||||
#define PSCI_1_0_FEATURES_CPU_SUSPEND_PF_SHIFT 1
|
||||
#define PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK \
|
||||
(0x1 << PSCI_1_0_FEATURES_CPU_SUSPEND_PF_SHIFT)
|
||||
|
||||
/* PSCI return values (inclusive of all PSCI versions) */
|
||||
#define PSCI_RET_SUCCESS 0
|
||||
#define PSCI_RET_NOT_SUPPORTED -1
|
||||
|
@ -86,5 +103,6 @@
|
|||
#define PSCI_RET_INTERNAL_FAILURE -6
|
||||
#define PSCI_RET_NOT_PRESENT -7
|
||||
#define PSCI_RET_DISABLED -8
|
||||
#define PSCI_RET_INVALID_ADDRESS -9
|
||||
|
||||
#endif /* _UAPI_LINUX_PSCI_H */
|
||||
|
|
Loading…
Reference in New Issue