@@ -13,6 +13,7 @@
#include <linux/errno.h>
#include <linux/linkage.h>
#include <linux/of.h>
+#include <linux/of_fdt.h>
#include <linux/pm.h>
#include <linux/printk.h>
#include <linux/psci.h>
@@ -767,6 +768,30 @@ int __init psci_dt_init(void)
return ret;
}
+/*
+ * Test early if PSCI is supported, and if its conduit matches @conduit
+ */
+bool __init psci_early_test_conduit(enum arm_smccc_conduit conduit)
+{
+ int len;
+ int psci_node;
+ const char *method;
+ unsigned long dt_root;
+
+ /* DT hasn't been unflattened yet, we have to work with the flat blob */
+ dt_root = of_get_flat_dt_root();
+ psci_node = of_get_flat_dt_subnode_by_name(dt_root, "psci");
+ if (psci_node <= 0)
+ return false;
+
+ method = of_get_flat_dt_prop(psci_node, "method", &len);
+ if (!method)
+ return false;
+
+ return (conduit == SMCCC_CONDUIT_SMC && strncmp(method, "smc", len) == 0) ||
+ (conduit == SMCCC_CONDUIT_HVC && strncmp(method, "hvc", len) == 0);
+}
+
#ifdef CONFIG_ACPI
/*
* We use PSCI 0.2+ when ACPI is deployed on ARM64 and it's
@@ -45,8 +45,13 @@ struct psci_0_1_function_ids get_psci_0_1_function_ids(void);
#if defined(CONFIG_ARM_PSCI_FW)
int __init psci_dt_init(void);
+bool __init psci_early_test_conduit(enum arm_smccc_conduit conduit);
#else
static inline int psci_dt_init(void) { return 0; }
+static inline bool psci_early_test_conduit(enum arm_smccc_conduit conduit)
+{
+ return false;
+}
#endif
#if defined(CONFIG_ARM_PSCI_FW) && defined(CONFIG_ACPI)