aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware/psci.c
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2018-02-06 12:56:16 -0500
committerCatalin Marinas <catalin.marinas@arm.com>2018-02-06 17:54:09 -0500
commit09a8d6d48499f93e2abde691f5800081cd858726 (patch)
treec8c2b16ab960e7537b84187d00b00adeea7fbb7e /drivers/firmware/psci.c
parentf72af90c3783d924337624659b43e2d36f1b36b4 (diff)
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: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'drivers/firmware/psci.c')
-rw-r--r--drivers/firmware/psci.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 8b25d31e8401..e9493da2b111 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -59,7 +59,9 @@ bool psci_tos_resident_on(int cpu)
59 return cpu == resident_cpu; 59 return cpu == resident_cpu;
60} 60}
61 61
62struct psci_operations psci_ops; 62struct psci_operations psci_ops = {
63 .conduit = PSCI_CONDUIT_NONE,
64};
63 65
64typedef unsigned long (psci_fn)(unsigned long, unsigned long, 66typedef unsigned long (psci_fn)(unsigned long, unsigned long,
65 unsigned long, unsigned long); 67 unsigned long, unsigned long);
@@ -210,6 +212,22 @@ static unsigned long psci_migrate_info_up_cpu(void)
210 0, 0, 0); 212 0, 0, 0);
211} 213}
212 214
215static void set_conduit(enum psci_conduit conduit)
216{
217 switch (conduit) {
218 case PSCI_CONDUIT_HVC:
219 invoke_psci_fn = __invoke_psci_fn_hvc;
220 break;
221 case PSCI_CONDUIT_SMC:
222 invoke_psci_fn = __invoke_psci_fn_smc;
223 break;
224 default:
225 WARN(1, "Unexpected PSCI conduit %d\n", conduit);
226 }
227
228 psci_ops.conduit = conduit;
229}
230
213static int get_set_conduit_method(struct device_node *np) 231static int get_set_conduit_method(struct device_node *np)
214{ 232{
215 const char *method; 233 const char *method;
@@ -222,9 +240,9 @@ static int get_set_conduit_method(struct device_node *np)
222 } 240 }
223 241
224 if (!strcmp("hvc", method)) { 242 if (!strcmp("hvc", method)) {
225 invoke_psci_fn = __invoke_psci_fn_hvc; 243 set_conduit(PSCI_CONDUIT_HVC);
226 } else if (!strcmp("smc", method)) { 244 } else if (!strcmp("smc", method)) {
227 invoke_psci_fn = __invoke_psci_fn_smc; 245 set_conduit(PSCI_CONDUIT_SMC);
228 } else { 246 } else {
229 pr_warn("invalid \"method\" property: %s\n", method); 247 pr_warn("invalid \"method\" property: %s\n", method);
230 return -EINVAL; 248 return -EINVAL;
@@ -654,9 +672,9 @@ int __init psci_acpi_init(void)
654 pr_info("probing for conduit method from ACPI.\n"); 672 pr_info("probing for conduit method from ACPI.\n");
655 673
656 if (acpi_psci_use_hvc()) 674 if (acpi_psci_use_hvc())
657 invoke_psci_fn = __invoke_psci_fn_hvc; 675 set_conduit(PSCI_CONDUIT_HVC);
658 else 676 else
659 invoke_psci_fn = __invoke_psci_fn_smc; 677 set_conduit(PSCI_CONDUIT_SMC);
660 678
661 return psci_probe(); 679 return psci_probe();
662} 680}