Commit 09a8d6d4 authored by Marc Zyngier's avatar Marc Zyngier Committed by Catalin Marinas

firmware/psci: Expose PSCI conduit

In order to call into the firmware to apply workarounds, it is
useful to find out whether we're using HVC or SMC. Let's expose
this through the psci_ops.
Acked-by: default avatarLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: default avatarRobin Murphy <robin.murphy@arm.com>
Tested-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent f72af90c
...@@ -59,7 +59,9 @@ bool psci_tos_resident_on(int cpu) ...@@ -59,7 +59,9 @@ bool psci_tos_resident_on(int cpu)
return cpu == resident_cpu; return cpu == resident_cpu;
} }
struct psci_operations psci_ops; struct psci_operations psci_ops = {
.conduit = PSCI_CONDUIT_NONE,
};
typedef unsigned long (psci_fn)(unsigned long, unsigned long, typedef unsigned long (psci_fn)(unsigned long, unsigned long,
unsigned long, unsigned long); unsigned long, unsigned long);
...@@ -210,6 +212,22 @@ static unsigned long psci_migrate_info_up_cpu(void) ...@@ -210,6 +212,22 @@ static unsigned long psci_migrate_info_up_cpu(void)
0, 0, 0); 0, 0, 0);
} }
static void set_conduit(enum psci_conduit conduit)
{
switch (conduit) {
case PSCI_CONDUIT_HVC:
invoke_psci_fn = __invoke_psci_fn_hvc;
break;
case PSCI_CONDUIT_SMC:
invoke_psci_fn = __invoke_psci_fn_smc;
break;
default:
WARN(1, "Unexpected PSCI conduit %d\n", conduit);
}
psci_ops.conduit = conduit;
}
static int get_set_conduit_method(struct device_node *np) static int get_set_conduit_method(struct device_node *np)
{ {
const char *method; const char *method;
...@@ -222,9 +240,9 @@ static int get_set_conduit_method(struct device_node *np) ...@@ -222,9 +240,9 @@ static int get_set_conduit_method(struct device_node *np)
} }
if (!strcmp("hvc", method)) { if (!strcmp("hvc", method)) {
invoke_psci_fn = __invoke_psci_fn_hvc; set_conduit(PSCI_CONDUIT_HVC);
} else if (!strcmp("smc", method)) { } else if (!strcmp("smc", method)) {
invoke_psci_fn = __invoke_psci_fn_smc; set_conduit(PSCI_CONDUIT_SMC);
} else { } else {
pr_warn("invalid \"method\" property: %s\n", method); pr_warn("invalid \"method\" property: %s\n", method);
return -EINVAL; return -EINVAL;
...@@ -654,9 +672,9 @@ int __init psci_acpi_init(void) ...@@ -654,9 +672,9 @@ int __init psci_acpi_init(void)
pr_info("probing for conduit method from ACPI.\n"); pr_info("probing for conduit method from ACPI.\n");
if (acpi_psci_use_hvc()) if (acpi_psci_use_hvc())
invoke_psci_fn = __invoke_psci_fn_hvc; set_conduit(PSCI_CONDUIT_HVC);
else else
invoke_psci_fn = __invoke_psci_fn_smc; set_conduit(PSCI_CONDUIT_SMC);
return psci_probe(); return psci_probe();
} }
......
...@@ -25,6 +25,12 @@ bool psci_tos_resident_on(int cpu); ...@@ -25,6 +25,12 @@ bool psci_tos_resident_on(int cpu);
int psci_cpu_init_idle(unsigned int cpu); int psci_cpu_init_idle(unsigned int cpu);
int psci_cpu_suspend_enter(unsigned long index); int psci_cpu_suspend_enter(unsigned long index);
enum psci_conduit {
PSCI_CONDUIT_NONE,
PSCI_CONDUIT_SMC,
PSCI_CONDUIT_HVC,
};
struct psci_operations { struct psci_operations {
u32 (*get_version)(void); u32 (*get_version)(void);
int (*cpu_suspend)(u32 state, unsigned long entry_point); int (*cpu_suspend)(u32 state, unsigned long entry_point);
...@@ -34,6 +40,7 @@ struct psci_operations { ...@@ -34,6 +40,7 @@ struct psci_operations {
int (*affinity_info)(unsigned long target_affinity, int (*affinity_info)(unsigned long target_affinity,
unsigned long lowest_affinity_level); unsigned long lowest_affinity_level);
int (*migrate_info_type)(void); int (*migrate_info_type)(void);
enum psci_conduit conduit;
}; };
extern struct psci_operations psci_ops; extern struct psci_operations psci_ops;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment