summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2018-03-06 13:17:00 +0100
committerUlf Hansson <ulf.hansson@linaro.org>2019-10-30 15:05:29 +0100
commit41abb68148c0d31a23c4b63fb8a6faf0405d49c6 (patch)
treed8f27591c2d0925b3adc301770f15fa8812b97d6
parent9e9aff9e68fb0ebb7ec6f2d355164ffc37742844 (diff)
drivers: firmware: psci: Introduce psci_dt_topology_init()
To be able to initiate the PM domain data structures for PSCI at a specific point during boot, let's export a new init function, psci_dt_topology_init(). If CONFIG_CPU_IDLE is set, it calls psci_dt_init_pm_domains(), which performs the actual initialization. Note that, it may seem like feasible idea to hook into the existing psci_dt_init() function, rather than adding a new separate init function. However, this doesn't work because psci_dt_init() is called early in the boot sequence, when allocating dynamic data structures isn't yet possible. Subsequent changes calls this new init function. Finally, following changes on top needs to know whether the hierarchical PM domain topology is used or not. Therefore, let's store this information in an internal PSCI flag. Co-developed-by: Lina Iyer <lina.iyer@linaro.org> Signed-off-by: Lina Iyer <lina.iyer@linaro.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/firmware/psci/psci.c30
-rw-r--r--include/linux/psci.h2
2 files changed, 32 insertions, 0 deletions
diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
index 307d976c30be..466047b0034b 100644
--- a/drivers/firmware/psci/psci.c
+++ b/drivers/firmware/psci/psci.c
@@ -290,6 +290,7 @@ static int __init psci_features(u32 psci_func_id)
#ifdef CONFIG_CPU_IDLE
static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
static DEFINE_PER_CPU(u32, domain_state);
+static bool psci_dt_topology;
static inline u32 psci_get_domain_state(void)
{
@@ -473,6 +474,19 @@ static const struct cpuidle_ops psci_cpuidle_ops __initconst = {
CPUIDLE_METHOD_OF_DECLARE(psci, "psci", &psci_cpuidle_ops);
#endif
+
+static int __init _psci_dt_topology_init(struct device_node *np)
+{
+ int ret;
+
+ /* Initialize the CPU PM domains based on topology described in DT. */
+ ret = psci_dt_init_pm_domains(np);
+ psci_dt_topology = ret > 0;
+
+ return ret;
+}
+#else
+static inline int _psci_dt_topology_init(struct device_node *np) { return 0; }
#endif
static int psci_system_suspend(unsigned long unused)
@@ -751,6 +765,22 @@ int __init psci_dt_init(void)
return ret;
}
+int __init psci_dt_topology_init(void)
+{
+ struct device_node *np;
+ int ret;
+
+ np = of_find_matching_node_and_match(NULL, psci_of_match, NULL);
+ if (!np)
+ return -ENODEV;
+
+ /* Initialize the topology described in DT. */
+ ret = _psci_dt_topology_init(np);
+
+ of_node_put(np);
+ return ret;
+}
+
#ifdef CONFIG_ACPI
/*
* We use PSCI 0.2+ when ACPI is deployed on ARM64 and it's
diff --git a/include/linux/psci.h b/include/linux/psci.h
index 931c7cf6c5f4..63f1091c51ab 100644
--- a/include/linux/psci.h
+++ b/include/linux/psci.h
@@ -48,8 +48,10 @@ extern struct psci_operations psci_ops;
#if defined(CONFIG_ARM_PSCI_FW)
int __init psci_dt_init(void);
+int __init psci_dt_topology_init(void);
#else
static inline int psci_dt_init(void) { return 0; }
+static inline int psci_dt_topology_init(void) { return 0; }
#endif
#if defined(CONFIG_ARM_PSCI_FW) && defined(CONFIG_ACPI)