]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
PM / Domains: Allow domain power states to be read from DT
authorLina Iyer <lina.iyer@linaro.org>
Fri, 14 Oct 2016 17:47:51 +0000 (10:47 -0700)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 21 Oct 2016 20:20:15 +0000 (22:20 +0200)
This patch allows domains to define idle states in the DT. SoC's can
define domain idle states in DT using the "domain-idle-states" property
of the domain provider. Add API to read the idle states from DT that can
be set in the genpd object.

This patch is based on the original patch by Marc Titinger.

Signed-off-by: Marc Titinger <mtitinger+renesas@baylibre.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Reviewed-by: Kevin Hilman <khilman@baylibre.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/base/power/domain.c
include/linux/pm_domain.h

index 37ab7f1ef178d2ba9fe9a6c58ee4def997b61be3..9af75ba0472a20399e7f38f5f3a646244bc236c5 100644 (file)
@@ -1916,6 +1916,100 @@ int genpd_dev_pm_attach(struct device *dev)
        return ret ? -EPROBE_DEFER : 0;
 }
 EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);
+
+static const struct of_device_id idle_state_match[] = {
+       { .compatible = "arm,idle-state", },
+       { }
+};
+
+static int genpd_parse_state(struct genpd_power_state *genpd_state,
+                                   struct device_node *state_node)
+{
+       int err;
+       u32 residency;
+       u32 entry_latency, exit_latency;
+       const struct of_device_id *match_id;
+
+       match_id = of_match_node(idle_state_match, state_node);
+       if (!match_id)
+               return -EINVAL;
+
+       err = of_property_read_u32(state_node, "entry-latency-us",
+                                               &entry_latency);
+       if (err) {
+               pr_debug(" * %s missing entry-latency-us property\n",
+                                               state_node->full_name);
+               return -EINVAL;
+       }
+
+       err = of_property_read_u32(state_node, "exit-latency-us",
+                                               &exit_latency);
+       if (err) {
+               pr_debug(" * %s missing exit-latency-us property\n",
+                                               state_node->full_name);
+               return -EINVAL;
+       }
+
+       err = of_property_read_u32(state_node, "min-residency-us", &residency);
+       if (!err)
+               genpd_state->residency_ns = 1000 * residency;
+
+       genpd_state->power_on_latency_ns = 1000 * exit_latency;
+       genpd_state->power_off_latency_ns = 1000 * entry_latency;
+
+       return 0;
+}
+
+/**
+ * of_genpd_parse_idle_states: Return array of idle states for the genpd.
+ *
+ * @dn: The genpd device node
+ * @states: The pointer to which the state array will be saved.
+ * @n: The count of elements in the array returned from this function.
+ *
+ * Returns the device states parsed from the OF node. The memory for the states
+ * is allocated by this function and is the responsibility of the caller to
+ * free the memory after use.
+ */
+int of_genpd_parse_idle_states(struct device_node *dn,
+                       struct genpd_power_state **states, int *n)
+{
+       struct genpd_power_state *st;
+       struct device_node *np;
+       int i = 0;
+       int err, ret;
+       int count;
+       struct of_phandle_iterator it;
+
+       count = of_count_phandle_with_args(dn, "domain-idle-states", NULL);
+       if (!count)
+               return -EINVAL;
+
+       st = kcalloc(count, sizeof(*st), GFP_KERNEL);
+       if (!st)
+               return -ENOMEM;
+
+       /* Loop over the phandles until all the requested entry is found */
+       of_for_each_phandle(&it, err, dn, "domain-idle-states", NULL, 0) {
+               np = it.node;
+               ret = genpd_parse_state(&st[i++], np);
+               if (ret) {
+                       pr_err
+                       ("Parsing idle state node %s failed with err %d\n",
+                                                       np->full_name, ret);
+                       of_node_put(np);
+                       kfree(st);
+                       return ret;
+               }
+       }
+
+       *n = count;
+       *states = st;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(of_genpd_parse_idle_states);
+
 #endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
 
 
index f4492eb71701e9f60aa13271ceed603bd6625864..b4894969fbeca275188f84fde0a3232fc5abd7c3 100644 (file)
@@ -205,6 +205,8 @@ extern int of_genpd_add_device(struct of_phandle_args *args,
 extern int of_genpd_add_subdomain(struct of_phandle_args *parent,
                                  struct of_phandle_args *new_subdomain);
 extern struct generic_pm_domain *of_genpd_remove_last(struct device_node *np);
+extern int of_genpd_parse_idle_states(struct device_node *dn,
+                       struct genpd_power_state **states, int *n);
 
 int genpd_dev_pm_attach(struct device *dev);
 #else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
@@ -234,6 +236,12 @@ static inline int of_genpd_add_subdomain(struct of_phandle_args *parent,
        return -ENODEV;
 }
 
+static inline int of_genpd_parse_idle_states(struct device_node *dn,
+                       struct genpd_power_state **states, int *n)
+{
+       return -ENODEV;
+}
+
 static inline int genpd_dev_pm_attach(struct device *dev)
 {
        return -ENODEV;