ARM: psci: add cmdline option to enable use of psci
authorAchin Gupta <achin.gupta@arm.com>
Sun, 10 Mar 2013 22:04:29 +0000 (22:04 +0000)
committerJon Medhurst <tixy@linaro.org>
Mon, 1 Jul 2013 10:05:02 +0000 (11:05 +0100)
This patch adds the 'psci' kernel command line option. Secure firmware cannot
yet add a psci device node in the dt to indicate whether it supports psci or
not. So in the current dt, the psci device node is present by default. The
probe function will always indicate that the secure firmware implements psci
irrespective of the address space linux runs in as the same device tree will
be used in either case. Hence a kernel cmdline option is required to choose
either the native or psci power api backend depending upon the address space
linux is running in.

Specifying 'psci=enable' in the cmdline will allow Linux running in the
non-secure address space to use the same dt but use the psci backend instead
of the native backend. It effectively overrides the presence of the native
implementation by ensuring registration of the psci backend. Linux running in
the secure address space will use the native backend for power management when
'psci=disable' in the cmdline (also the default value i.e. psci backend is
disabled by default) or the psci node in the dt is absent.

Signed-off-by: Achin Gupta <achin.gupta@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
arch/arm/kernel/psci.c

index 03c10f65addef0f6182fc97b5cdd6f7d9fbf4cbc..1180801468d894b5ff33c43c9852c7c69e1c638a 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <linux/init.h>
 #include <linux/of.h>
+#include <linux/string.h>
 
 #include <asm/compiler.h>
 #include <asm/errno.h>
 
 struct psci_operations psci_ops;
 
+/* Type of psci support. Currently can only be enabled or disabled */
+#define PSCI_SUP_DISABLED              0
+#define PSCI_SUP_ENABLED               1
+
+static unsigned int psci;
 static int (*invoke_psci_fn)(u32, u32, u32, u32);
 
 enum psci_function {
@@ -167,6 +173,9 @@ static int __init psci_init(void)
        const char *method;
        u32 id;
 
+       if (psci == PSCI_SUP_DISABLED)
+               return 0;
+
        np = of_find_matching_node(NULL, psci_of_match);
        if (!np)
                return 0;
@@ -218,10 +227,27 @@ int __init psci_probe(void)
        struct device_node *np;
        int ret = -ENODEV;
 
-       np = of_find_matching_node(NULL, psci_of_match);
-       if (np)
-               ret = 0;
+       if (psci == PSCI_SUP_ENABLED) {
+               np = of_find_matching_node(NULL, psci_of_match);
+               if (np)
+                       ret = 0;
+       }
 
        of_node_put(np);
        return ret;
 }
+
+static int __init early_psci(char *val)
+{
+       int ret = 0;
+
+       if (strcmp(val, "enable") == 0)
+               psci = PSCI_SUP_ENABLED;
+       else if (strcmp(val, "disable") == 0)
+               psci = PSCI_SUP_DISABLED;
+       else
+               ret = -EINVAL;
+
+       return ret;
+}
+early_param("psci", early_psci);