diff options
Diffstat (limited to 'drivers/firmware/psci')
| -rw-r--r-- | drivers/firmware/psci/psci.c | 126 | 
1 files changed, 78 insertions, 48 deletions
| diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c index 00af99b6f97c..f5fc429cae3f 100644 --- a/drivers/firmware/psci/psci.c +++ b/drivers/firmware/psci/psci.c @@ -58,15 +58,12 @@ typedef unsigned long (psci_fn)(unsigned long, unsigned long,  				unsigned long, unsigned long);  static psci_fn *invoke_psci_fn; -enum psci_function { -	PSCI_FN_CPU_SUSPEND, -	PSCI_FN_CPU_ON, -	PSCI_FN_CPU_OFF, -	PSCI_FN_MIGRATE, -	PSCI_FN_MAX, -}; +static struct psci_0_1_function_ids psci_0_1_function_ids; -static u32 psci_function_id[PSCI_FN_MAX]; +struct psci_0_1_function_ids get_psci_0_1_function_ids(void) +{ +	return psci_0_1_function_ids; +}  #define PSCI_0_2_POWER_STATE_MASK		\  				(PSCI_0_2_POWER_STATE_ID_MASK | \ @@ -146,7 +143,12 @@ static int psci_to_linux_errno(int errno)  	return -EINVAL;  } -static u32 psci_get_version(void) +static u32 psci_0_1_get_version(void) +{ +	return PSCI_VERSION(0, 1); +} + +static u32 psci_0_2_get_version(void)  {  	return invoke_psci_fn(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);  } @@ -163,46 +165,80 @@ int psci_set_osi_mode(bool enable)  	return psci_to_linux_errno(err);  } -static int psci_cpu_suspend(u32 state, unsigned long entry_point) +static int __psci_cpu_suspend(u32 fn, u32 state, unsigned long entry_point)  {  	int err; -	u32 fn; -	fn = psci_function_id[PSCI_FN_CPU_SUSPEND];  	err = invoke_psci_fn(fn, state, entry_point, 0);  	return psci_to_linux_errno(err);  } -static int psci_cpu_off(u32 state) +static int psci_0_1_cpu_suspend(u32 state, unsigned long entry_point) +{ +	return __psci_cpu_suspend(psci_0_1_function_ids.cpu_suspend, +				  state, entry_point); +} + +static int psci_0_2_cpu_suspend(u32 state, unsigned long entry_point) +{ +	return __psci_cpu_suspend(PSCI_FN_NATIVE(0_2, CPU_SUSPEND), +				  state, entry_point); +} + +static int __psci_cpu_off(u32 fn, u32 state)  {  	int err; -	u32 fn; -	fn = psci_function_id[PSCI_FN_CPU_OFF];  	err = invoke_psci_fn(fn, state, 0, 0);  	return psci_to_linux_errno(err);  } -static int psci_cpu_on(unsigned long cpuid, unsigned long entry_point) +static int psci_0_1_cpu_off(u32 state) +{ +	return __psci_cpu_off(psci_0_1_function_ids.cpu_off, state); +} + +static int psci_0_2_cpu_off(u32 state) +{ +	return __psci_cpu_off(PSCI_0_2_FN_CPU_OFF, state); +} + +static int __psci_cpu_on(u32 fn, unsigned long cpuid, unsigned long entry_point)  {  	int err; -	u32 fn; -	fn = psci_function_id[PSCI_FN_CPU_ON];  	err = invoke_psci_fn(fn, cpuid, entry_point, 0);  	return psci_to_linux_errno(err);  } -static int psci_migrate(unsigned long cpuid) +static int psci_0_1_cpu_on(unsigned long cpuid, unsigned long entry_point) +{ +	return __psci_cpu_on(psci_0_1_function_ids.cpu_on, cpuid, entry_point); +} + +static int psci_0_2_cpu_on(unsigned long cpuid, unsigned long entry_point) +{ +	return __psci_cpu_on(PSCI_FN_NATIVE(0_2, CPU_ON), cpuid, entry_point); +} + +static int __psci_migrate(u32 fn, unsigned long cpuid)  {  	int err; -	u32 fn; -	fn = psci_function_id[PSCI_FN_MIGRATE];  	err = invoke_psci_fn(fn, cpuid, 0, 0);  	return psci_to_linux_errno(err);  } +static int psci_0_1_migrate(unsigned long cpuid) +{ +	return __psci_migrate(psci_0_1_function_ids.migrate, cpuid); +} + +static int psci_0_2_migrate(unsigned long cpuid) +{ +	return __psci_migrate(PSCI_FN_NATIVE(0_2, MIGRATE), cpuid); +} +  static int psci_affinity_info(unsigned long target_affinity,  		unsigned long lowest_affinity_level)  { @@ -347,7 +383,7 @@ static void __init psci_init_system_suspend(void)  static void __init psci_init_cpu_suspend(void)  { -	int feature = psci_features(psci_function_id[PSCI_FN_CPU_SUSPEND]); +	int feature = psci_features(PSCI_FN_NATIVE(0_2, CPU_SUSPEND));  	if (feature != PSCI_RET_NOT_SUPPORTED)  		psci_cpu_suspend_feature = feature; @@ -421,24 +457,16 @@ static void __init psci_init_smccc(void)  static void __init psci_0_2_set_functions(void)  {  	pr_info("Using standard PSCI v0.2 function IDs\n"); -	psci_ops.get_version = psci_get_version; - -	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_FN_NATIVE(0_2, CPU_ON); -	psci_ops.cpu_on = psci_cpu_on; -	psci_function_id[PSCI_FN_MIGRATE] = PSCI_FN_NATIVE(0_2, MIGRATE); -	psci_ops.migrate = psci_migrate; - -	psci_ops.affinity_info = psci_affinity_info; - -	psci_ops.migrate_info_type = psci_migrate_info_type; +	psci_ops = (struct psci_operations){ +		.get_version = psci_0_2_get_version, +		.cpu_suspend = psci_0_2_cpu_suspend, +		.cpu_off = psci_0_2_cpu_off, +		.cpu_on = psci_0_2_cpu_on, +		.migrate = psci_0_2_migrate, +		.affinity_info = psci_affinity_info, +		.migrate_info_type = psci_migrate_info_type, +	};  	arm_pm_restart = psci_sys_reset; @@ -450,7 +478,7 @@ static void __init psci_0_2_set_functions(void)   */  static int __init psci_probe(void)  { -	u32 ver = psci_get_version(); +	u32 ver = psci_0_2_get_version();  	pr_info("PSCIv%d.%d detected in firmware.\n",  			PSCI_VERSION_MAJOR(ver), @@ -514,24 +542,26 @@ static int __init psci_0_1_init(struct device_node *np)  	pr_info("Using PSCI v0.1 Function IDs from DT\n"); +	psci_ops.get_version = psci_0_1_get_version; +  	if (!of_property_read_u32(np, "cpu_suspend", &id)) { -		psci_function_id[PSCI_FN_CPU_SUSPEND] = id; -		psci_ops.cpu_suspend = psci_cpu_suspend; +		psci_0_1_function_ids.cpu_suspend = id; +		psci_ops.cpu_suspend = psci_0_1_cpu_suspend;  	}  	if (!of_property_read_u32(np, "cpu_off", &id)) { -		psci_function_id[PSCI_FN_CPU_OFF] = id; -		psci_ops.cpu_off = psci_cpu_off; +		psci_0_1_function_ids.cpu_off = id; +		psci_ops.cpu_off = psci_0_1_cpu_off;  	}  	if (!of_property_read_u32(np, "cpu_on", &id)) { -		psci_function_id[PSCI_FN_CPU_ON] = id; -		psci_ops.cpu_on = psci_cpu_on; +		psci_0_1_function_ids.cpu_on = id; +		psci_ops.cpu_on = psci_0_1_cpu_on;  	}  	if (!of_property_read_u32(np, "migrate", &id)) { -		psci_function_id[PSCI_FN_MIGRATE] = id; -		psci_ops.migrate = psci_migrate; +		psci_0_1_function_ids.migrate = id; +		psci_ops.migrate = psci_0_1_migrate;  	}  	return 0; | 
