From mboxrd@z Thu Jan 1 00:00:00 1970 From: sudeep.holla@arm.com (Sudeep Holla) Date: Mon, 31 Mar 2014 17:52:50 +0100 Subject: [Linaro-acpi] [PATCH v4 1/3] PSCI: Add initial support for PSCIv0.2 functions In-Reply-To: <1396278179-28181-2-git-send-email-ashwin.chaugule@linaro.org> References: <1396278179-28181-1-git-send-email-ashwin.chaugule@linaro.org> <1396278179-28181-2-git-send-email-ashwin.chaugule@linaro.org> Message-ID: <53399D62.5060704@arm.com> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org Hi Ashwin, On 31/03/14 16:02, Ashwin Chaugule wrote: > The PSCIv0.2 spec defines standard values of function IDs > and introduces a few new functions. Detect version of PSCI > and appropriately select the right PSCI functions. > > Signed-off-by: Ashwin Chaugule > --- > arch/arm/include/asm/psci.h | 7 +- > arch/arm/kernel/psci.c | 155 ++++++++++++++++++++++++++++++++++-------- > arch/arm64/kernel/psci.c | 160 +++++++++++++++++++++++++++++++++++--------- > include/uapi/linux/psci.h | 61 +++++++++++++++++ > 4 files changed, 323 insertions(+), 60 deletions(-) > create mode 100644 include/uapi/linux/psci.h > > diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h > index c4ae171..b93e34a 100644 > --- a/arch/arm/include/asm/psci.h > +++ b/arch/arm/include/asm/psci.h > @@ -29,16 +29,19 @@ struct psci_operations { > int (*cpu_off)(struct psci_power_state state); > int (*cpu_on)(unsigned long cpuid, unsigned long entry_point); > int (*migrate)(unsigned long cpuid); > + int (*affinity_info)(unsigned long target_affinity, > + unsigned long lowest_affinity_level); > + int (*migrate_info_type)(void); > }; > > extern struct psci_operations psci_ops; > extern struct smp_operations psci_smp_ops; > > #ifdef CONFIG_ARM_PSCI > -void psci_init(void); > +int psci_init(void); > bool psci_smp_available(void); > #else > -static inline void psci_init(void) { } > +static inline int psci_init(void) { } > static inline bool psci_smp_available(void) { return false; } > #endif > > diff --git a/arch/arm/kernel/psci.c b/arch/arm/kernel/psci.c > index 4693188..46b23b6 100644 > --- a/arch/arm/kernel/psci.c > +++ b/arch/arm/kernel/psci.c > @@ -17,6 +17,7 @@ > > #include > #include > +#include > > #include > #include > @@ -27,22 +28,20 @@ > struct psci_operations psci_ops; > > static int (*invoke_psci_fn)(u32, u32, u32, u32); > +typedef int (*psci_initcall_t)(const struct device_node *); > > enum psci_function { > PSCI_FN_CPU_SUSPEND, > PSCI_FN_CPU_ON, > PSCI_FN_CPU_OFF, > PSCI_FN_MIGRATE, > + PSCI_FN_AFFINITY_INFO, > + PSCI_FN_MIGRATE_INFO_TYPE, > PSCI_FN_MAX, > }; > > static u32 psci_function_id[PSCI_FN_MAX]; > > -#define PSCI_RET_SUCCESS 0 > -#define PSCI_RET_EOPNOTSUPP -1 > -#define PSCI_RET_EINVAL -2 > -#define PSCI_RET_EPERM -3 > - > static int psci_to_linux_errno(int errno) > { > switch (errno) { > @@ -59,13 +58,6 @@ static int psci_to_linux_errno(int errno) > return -EINVAL; > } > > -#define PSCI_POWER_STATE_ID_MASK 0xffff > -#define PSCI_POWER_STATE_ID_SHIFT 0 > -#define PSCI_POWER_STATE_TYPE_MASK 0x1 > -#define PSCI_POWER_STATE_TYPE_SHIFT 16 > -#define PSCI_POWER_STATE_AFFL_MASK 0x3 > -#define PSCI_POWER_STATE_AFFL_SHIFT 24 > - > static u32 psci_power_state_pack(struct psci_power_state state) > { > return ((state.id & PSCI_POWER_STATE_ID_MASK) > @@ -110,6 +102,14 @@ static noinline int __invoke_psci_fn_smc(u32 function_id, u32 arg0, u32 arg1, > return function_id; > } > > +static int psci_get_version(void) > +{ > + int err; > + > + err = invoke_psci_fn(PSCI_ID_VERSION, 0, 0, 0); > + return err; > +} > + > static int psci_cpu_suspend(struct psci_power_state state, > unsigned long entry_point) > { > @@ -153,26 +153,36 @@ static int psci_migrate(unsigned long cpuid) > return psci_to_linux_errno(err); > } > > -static const struct of_device_id psci_of_match[] __initconst = { > - { .compatible = "arm,psci", }, > - {}, > -}; > +static int psci_affinity_info(unsigned long target_affinity, > + unsigned long lowest_affinity_level) > +{ > + int err; > + u32 fn; > > -void __init psci_init(void) > + fn = psci_function_id[PSCI_FN_AFFINITY_INFO]; > + err = invoke_psci_fn(fn, target_affinity, lowest_affinity_level, 0); > + return err; > +} > + > +static int psci_migrate_info_type(void) > { > - struct device_node *np; > - const char *method; > - u32 id; > + int err; > + u32 fn; > > - np = of_find_matching_node(NULL, psci_of_match); > - if (!np) > - return; > + fn = psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE]; > + err = invoke_psci_fn(fn, 0, 0, 0); > + return err; > +} > > - pr_info("probing function IDs from device-tree\n"); > +static int get_set_conduit_method(struct device_node *np) > +{ > + const char *method; > + > + pr_info("probing for conduit method from DT.\n"); > > if (of_property_read_string(np, "method", &method)) { > - pr_warning("missing \"method\" property\n"); > - goto out_put_node; > + pr_warn("missing \"method\" property\n"); > + return -ENXIO; > } > > if (!strcmp("hvc", method)) { > @@ -180,10 +190,79 @@ void __init psci_init(void) > } else if (!strcmp("smc", method)) { > invoke_psci_fn = __invoke_psci_fn_smc; > } else { > - pr_warning("invalid \"method\" property: %s\n", method); > + pr_warn("invalid \"method\" property: %s\n", method); > + return -EINVAL; > + } > + return 0; > +} > + > +/* > + * PSCI Function IDs for v0.2+ are well defined so use > + * standard values. > + */ > +static int psci_0_2_init(struct device_node *np) > +{ > + int err, ver; > + > + err = get_set_conduit_method(np); > + > + if (err) > goto out_put_node; > + > + ver = psci_get_version(); > + > + if (ver == PSCI_RET_EOPNOTSUPP) { > + pr_info("PSCI_ID_VERSION Function not supported in firmware.\n"); IMO you should stop here as the implementation conforming to the specification must return a minor version number of 2 and major version number of 0. You can't proceed, assume ids and use them. Regards, Sudeep