From: Lina Iyer <lina.iyer@linaro.org> To: ulf.hansson@linaro.org, khilman@kernel.org, rjw@rjwysocki.net, linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: andy.gross@linaro.org, sboyd@codeaurora.org, linux-arm-msm@vger.kernel.org, Axel Haslam <ahaslam+renesas@baylibre.com>, Marc Titinger <mtitinger+renesas@baylibre.com>, Lina Iyer <lina.iyer@linaro.org> Subject: [PATCH v3 01/15] PM / Domains: Allow domain power states to be read from DT Date: Thu, 4 Aug 2016 17:04:48 -0600 [thread overview] Message-ID: <1470351902-43103-2-git-send-email-lina.iyer@linaro.org> (raw) In-Reply-To: <1470351902-43103-1-git-send-email-lina.iyer@linaro.org> From: Axel Haslam <ahaslam+renesas@baylibre.com> 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. Calling of_pm_genpd_init() will read the idle states and initialize the genpd for the domain. In addition to the entry and exit latency for idle state, also add residency_ns, param and of_node property to each state. A domain idling in a state is only power effecient if it stays idle for a certain period in that state. The residency provides this minimum time for the idle state to provide power benefits. The param is a state specific u32 value that the platform may use for that idle state. Signed-off-by: Marc Titinger <mtitinger+renesas@baylibre.com> Signed-off-by: Lina Iyer <lina.iyer@linaro.org> [Lina: Added state properties, removed state names, wakeup-latency, added of_pm_genpd_init() API, pruned commit text] Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> [Ulf: Moved around code to make it compile properly, rebased on top of multiple state support,changed to use pm_genpd_init()] --- drivers/base/power/domain.c | 92 ++++++++++++++++++++++++++++++++++++++++++++- include/linux/pm_domain.h | 11 +++++- 2 files changed, 101 insertions(+), 2 deletions(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index a1f2aff..3aecac3 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1253,6 +1253,90 @@ out: } EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain); +static const struct of_device_id arm_idle_state_match[] = { + { .compatible = "arm,idle-state", }, + { } +}; + +static int genpd_of_get_power_state(struct genpd_power_state *genpd_state, + struct device_node *state_node) +{ + int err = 0; + u32 latency; + u32 residency; + u32 entry_latency, exit_latency; + const struct of_device_id *match_id; + + match_id = of_match_node(arm_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; + + latency = entry_latency + exit_latency; + genpd_state->power_on_latency_ns = 1000 * latency; + genpd_state->power_off_latency_ns = 1000 * entry_latency; + genpd_state->of_node = state_node; + + return 0; +} + +int pm_genpd_of_parse_power_states(struct generic_pm_domain *genpd) +{ + struct device_node *np; + int i, err = 0; + + for (i = 0; i < GENPD_MAX_NUM_STATES; i++) { + np = of_parse_phandle(genpd->of_node, "domain-idle-states", i); + if (!np) + break; + + err = genpd_of_get_power_state(&genpd->states[i], np); + if (err) { + pr_err + ("Parsing idle state node %s failed with err %d\n", + np->full_name, err); + err = -EINVAL; + of_node_put(np); + break; + } + of_node_put(np); + } + + if (err) + return err; + + genpd->state_count = i; + return 0; +} +EXPORT_SYMBOL(pm_genpd_of_parse_power_states); + +static int genpd_of_parse(struct generic_pm_domain *genpd) +{ + if (!genpd->of_node || (genpd->state_count > 0)) + return 0; + + return pm_genpd_of_parse_power_states(genpd); +} + /** * pm_genpd_init - Initialize a generic I/O PM domain object. * @genpd: PM domain object to initialize. @@ -1262,8 +1346,10 @@ EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain); * Returns 0 on successful initialization, else a negative error code. */ int pm_genpd_init(struct generic_pm_domain *genpd, - struct dev_power_governor *gov, bool is_off) + struct dev_power_governor *gov, bool is_off) { + int ret; + if (IS_ERR_OR_NULL(genpd)) return -EINVAL; @@ -1306,6 +1392,10 @@ int pm_genpd_init(struct generic_pm_domain *genpd, genpd->dev_ops.start = pm_clk_resume; } + ret = genpd_of_parse(genpd); + if (ret) + return ret; + if (genpd->state_idx >= GENPD_MAX_NUM_STATES) { pr_warn("Initial state index out of bounds.\n"); genpd->state_idx = GENPD_MAX_NUM_STATES - 1; diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 31fec85..c5d14b9 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -40,6 +40,9 @@ struct gpd_dev_ops { struct genpd_power_state { s64 power_off_latency_ns; s64 power_on_latency_ns; + s64 residency_ns; + u32 param; + struct device_node *of_node; }; struct generic_pm_domain { @@ -51,6 +54,7 @@ struct generic_pm_domain { struct mutex lock; struct dev_power_governor *gov; struct work_struct power_off_work; + struct device_node *of_node; /* Device node of the PM domain */ const char *name; atomic_t sd_count; /* Number of subdomains with power "on" */ enum gpd_status status; /* Current state of the domain */ @@ -129,7 +133,7 @@ extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, struct generic_pm_domain *target); extern int pm_genpd_init(struct generic_pm_domain *genpd, struct dev_power_governor *gov, bool is_off); - +extern int pm_genpd_of_parse_power_states(struct generic_pm_domain *genpd); extern struct dev_power_governor simple_qos_governor; extern struct dev_power_governor pm_domain_always_on_gov; #else @@ -168,6 +172,11 @@ static inline int pm_genpd_init(struct generic_pm_domain *genpd, { return -ENOSYS; } +static inline int pm_genpd_of_parse_power_states( + struct generic_pm_domain *genpd) +{ + return -ENODEV; +} #endif static inline int pm_genpd_add_device(struct generic_pm_domain *genpd, -- 2.7.4
WARNING: multiple messages have this Message-ID (diff)
From: lina.iyer@linaro.org (Lina Iyer) To: linux-arm-kernel@lists.infradead.org Subject: [PATCH v3 01/15] PM / Domains: Allow domain power states to be read from DT Date: Thu, 4 Aug 2016 17:04:48 -0600 [thread overview] Message-ID: <1470351902-43103-2-git-send-email-lina.iyer@linaro.org> (raw) In-Reply-To: <1470351902-43103-1-git-send-email-lina.iyer@linaro.org> From: Axel Haslam <ahaslam+renesas@baylibre.com> 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. Calling of_pm_genpd_init() will read the idle states and initialize the genpd for the domain. In addition to the entry and exit latency for idle state, also add residency_ns, param and of_node property to each state. A domain idling in a state is only power effecient if it stays idle for a certain period in that state. The residency provides this minimum time for the idle state to provide power benefits. The param is a state specific u32 value that the platform may use for that idle state. Signed-off-by: Marc Titinger <mtitinger+renesas@baylibre.com> Signed-off-by: Lina Iyer <lina.iyer@linaro.org> [Lina: Added state properties, removed state names, wakeup-latency, added of_pm_genpd_init() API, pruned commit text] Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> [Ulf: Moved around code to make it compile properly, rebased on top of multiple state support,changed to use pm_genpd_init()] --- drivers/base/power/domain.c | 92 ++++++++++++++++++++++++++++++++++++++++++++- include/linux/pm_domain.h | 11 +++++- 2 files changed, 101 insertions(+), 2 deletions(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index a1f2aff..3aecac3 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1253,6 +1253,90 @@ out: } EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain); +static const struct of_device_id arm_idle_state_match[] = { + { .compatible = "arm,idle-state", }, + { } +}; + +static int genpd_of_get_power_state(struct genpd_power_state *genpd_state, + struct device_node *state_node) +{ + int err = 0; + u32 latency; + u32 residency; + u32 entry_latency, exit_latency; + const struct of_device_id *match_id; + + match_id = of_match_node(arm_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; + + latency = entry_latency + exit_latency; + genpd_state->power_on_latency_ns = 1000 * latency; + genpd_state->power_off_latency_ns = 1000 * entry_latency; + genpd_state->of_node = state_node; + + return 0; +} + +int pm_genpd_of_parse_power_states(struct generic_pm_domain *genpd) +{ + struct device_node *np; + int i, err = 0; + + for (i = 0; i < GENPD_MAX_NUM_STATES; i++) { + np = of_parse_phandle(genpd->of_node, "domain-idle-states", i); + if (!np) + break; + + err = genpd_of_get_power_state(&genpd->states[i], np); + if (err) { + pr_err + ("Parsing idle state node %s failed with err %d\n", + np->full_name, err); + err = -EINVAL; + of_node_put(np); + break; + } + of_node_put(np); + } + + if (err) + return err; + + genpd->state_count = i; + return 0; +} +EXPORT_SYMBOL(pm_genpd_of_parse_power_states); + +static int genpd_of_parse(struct generic_pm_domain *genpd) +{ + if (!genpd->of_node || (genpd->state_count > 0)) + return 0; + + return pm_genpd_of_parse_power_states(genpd); +} + /** * pm_genpd_init - Initialize a generic I/O PM domain object. * @genpd: PM domain object to initialize. @@ -1262,8 +1346,10 @@ EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain); * Returns 0 on successful initialization, else a negative error code. */ int pm_genpd_init(struct generic_pm_domain *genpd, - struct dev_power_governor *gov, bool is_off) + struct dev_power_governor *gov, bool is_off) { + int ret; + if (IS_ERR_OR_NULL(genpd)) return -EINVAL; @@ -1306,6 +1392,10 @@ int pm_genpd_init(struct generic_pm_domain *genpd, genpd->dev_ops.start = pm_clk_resume; } + ret = genpd_of_parse(genpd); + if (ret) + return ret; + if (genpd->state_idx >= GENPD_MAX_NUM_STATES) { pr_warn("Initial state index out of bounds.\n"); genpd->state_idx = GENPD_MAX_NUM_STATES - 1; diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 31fec85..c5d14b9 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -40,6 +40,9 @@ struct gpd_dev_ops { struct genpd_power_state { s64 power_off_latency_ns; s64 power_on_latency_ns; + s64 residency_ns; + u32 param; + struct device_node *of_node; }; struct generic_pm_domain { @@ -51,6 +54,7 @@ struct generic_pm_domain { struct mutex lock; struct dev_power_governor *gov; struct work_struct power_off_work; + struct device_node *of_node; /* Device node of the PM domain */ const char *name; atomic_t sd_count; /* Number of subdomains with power "on" */ enum gpd_status status; /* Current state of the domain */ @@ -129,7 +133,7 @@ extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, struct generic_pm_domain *target); extern int pm_genpd_init(struct generic_pm_domain *genpd, struct dev_power_governor *gov, bool is_off); - +extern int pm_genpd_of_parse_power_states(struct generic_pm_domain *genpd); extern struct dev_power_governor simple_qos_governor; extern struct dev_power_governor pm_domain_always_on_gov; #else @@ -168,6 +172,11 @@ static inline int pm_genpd_init(struct generic_pm_domain *genpd, { return -ENOSYS; } +static inline int pm_genpd_of_parse_power_states( + struct generic_pm_domain *genpd) +{ + return -ENODEV; +} #endif static inline int pm_genpd_add_device(struct generic_pm_domain *genpd, -- 2.7.4
next prev parent reply other threads:[~2016-08-04 23:04 UTC|newest] Thread overview: 83+ messages / expand[flat|nested] mbox.gz Atom feed top 2016-08-04 23:04 [PATCH v3 00/15] PM: SoC idle support using PM domains Lina Iyer 2016-08-04 23:04 ` Lina Iyer 2016-08-04 23:04 ` Lina Iyer [this message] 2016-08-04 23:04 ` [PATCH v3 01/15] PM / Domains: Allow domain power states to be read from DT Lina Iyer 2016-08-04 23:04 ` [PATCH v3 02/15] dt/bindings: Update binding for PM domain idle states Lina Iyer 2016-08-04 23:04 ` Lina Iyer 2016-08-09 23:55 ` Rob Herring 2016-08-09 23:55 ` Rob Herring 2016-08-10 15:14 ` Sudeep Holla 2016-08-10 15:14 ` Sudeep Holla 2016-08-10 16:40 ` Lina Iyer 2016-08-10 16:40 ` Lina Iyer [not found] ` <20160810164034.GA1401-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> 2016-08-10 18:09 ` Sudeep Holla 2016-08-10 18:09 ` Sudeep Holla 2016-08-10 18:13 ` Sudeep Holla 2016-08-10 18:13 ` Sudeep Holla [not found] ` <5e59874c-bbb7-270a-199c-da1ff5932554-5wv7dgnIgG8@public.gmane.org> 2016-08-11 21:10 ` Lina Iyer 2016-08-11 21:10 ` Lina Iyer [not found] ` <20160811211023.GC1401-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> 2016-08-12 9:47 ` Brendan Jackman 2016-08-12 9:47 ` Brendan Jackman 2016-08-12 10:08 ` Sudeep Holla 2016-08-12 10:08 ` Sudeep Holla 2016-08-15 16:08 ` Lina Iyer 2016-08-15 16:08 ` Lina Iyer 2016-08-15 16:14 ` Sudeep Holla 2016-08-15 16:14 ` Sudeep Holla 2016-08-15 22:40 ` Lina Iyer 2016-08-15 22:40 ` Lina Iyer [not found] ` <20160815224014.GF1401-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> 2016-08-16 8:34 ` Brendan Jackman 2016-08-16 8:34 ` Brendan Jackman 2016-08-16 8:41 ` Brendan Jackman 2016-08-16 8:41 ` Brendan Jackman 2016-08-16 9:19 ` Sudeep Holla 2016-08-16 9:19 ` Sudeep Holla 2016-08-12 12:35 ` Brendan Jackman 2016-08-12 12:35 ` Brendan Jackman 2016-08-15 16:06 ` Lina Iyer 2016-08-15 16:06 ` Lina Iyer 2016-08-19 18:10 ` Kevin Hilman 2016-08-19 18:10 ` Kevin Hilman 2016-08-24 14:07 ` Sudeep Holla 2016-08-24 14:07 ` Sudeep Holla [not found] ` <1470351902-43103-3-git-send-email-lina.iyer-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> 2016-08-24 13:48 ` [RFC 0/6] Illustration of using domain-idle-states for CPU " Brendan Jackman 2016-08-24 13:48 ` [RFC 1/6] cpuidle: Rename cpuidle_get_{cpu->dev}_driver Brendan Jackman 2016-08-24 13:48 ` [RFC 2/6] cpuidle: Add public funcion to get driver from CPU index Brendan Jackman [not found] ` <20160824134822.3591-1-brendan.jackman-5wv7dgnIgG8@public.gmane.org> 2016-08-24 13:48 ` [RFC 3/6] cpuidle: Add device_node pointer in cpuidle_state Brendan Jackman 2016-08-24 13:48 ` [RFC 6/6] arm64: dts: Add domain-idle-states for Juno r0 power domains Brendan Jackman 2016-08-24 13:48 ` [RFC 4/6] cpuidle: dt: Add support for reading states from " Brendan Jackman 2016-08-24 13:48 ` [RFC 5/6] arm64: dts: Add Juno r0 CPU power domain tree Brendan Jackman 2016-08-04 23:04 ` [PATCH v3 03/15] PM / Domains: Abstract genpd locking Lina Iyer 2016-08-04 23:04 ` Lina Iyer 2016-08-04 23:04 ` [PATCH v3 04/15] PM / Domains: Support IRQ safe PM domains Lina Iyer 2016-08-04 23:04 ` Lina Iyer 2016-08-04 23:04 ` [PATCH v3 05/15] PM / doc: Update device documentation for devices in " Lina Iyer 2016-08-04 23:04 ` Lina Iyer 2016-08-04 23:04 ` [PATCH v3 06/15] PM / cpu_domains: Setup PM domains for CPUs/clusters Lina Iyer 2016-08-04 23:04 ` Lina Iyer 2016-08-04 23:04 ` [PATCH v3 07/15] ARM: cpuidle: Add runtime PM support for CPUs Lina Iyer 2016-08-04 23:04 ` Lina Iyer 2016-08-04 23:04 ` [PATCH v3 08/15] timer: Export next wake up of a CPU Lina Iyer 2016-08-04 23:04 ` Lina Iyer 2016-08-04 23:04 ` [PATCH v3 09/15] PM / cpu_domains: Add PM Domain governor for CPUs Lina Iyer 2016-08-04 23:04 ` Lina Iyer 2016-08-04 23:04 ` [PATCH v3 10/15] doc / cpu_domains: Describe CPU PM domains setup and governor Lina Iyer 2016-08-04 23:04 ` Lina Iyer 2016-08-04 23:04 ` [PATCH v3 11/15] drivers: firmware: psci: Allow OS Initiated suspend mode Lina Iyer 2016-08-04 23:04 ` Lina Iyer 2016-08-04 23:04 ` [PATCH v3 12/15] drivers: firmware: psci: Support cluster idle states for OS-Initiated Lina Iyer 2016-08-04 23:04 ` Lina Iyer 2016-08-04 23:05 ` [PATCH v3 13/15] dt/bindings: Add PSCI OS-Initiated PM Domains bindings Lina Iyer 2016-08-04 23:05 ` Lina Iyer 2016-08-05 14:44 ` Lina Iyer 2016-08-05 14:44 ` Lina Iyer 2016-08-04 23:05 ` [PATCH v3 14/15] ARM64: dts: Add PSCI cpuidle support for MSM8916 Lina Iyer 2016-08-04 23:05 ` Lina Iyer [not found] ` <1470351902-43103-1-git-send-email-lina.iyer-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> 2016-08-04 23:05 ` [PATCH v3 15/15] ARM64: dts: Define CPU power domain " Lina Iyer 2016-08-04 23:05 ` Lina Iyer 2016-08-10 15:27 ` Sudeep Holla 2016-08-10 15:27 ` Sudeep Holla 2016-08-10 17:35 ` Lina Iyer 2016-08-10 17:35 ` Lina Iyer 2016-08-11 9:30 ` Sudeep Holla 2016-08-11 9:30 ` Sudeep Holla
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1470351902-43103-2-git-send-email-lina.iyer@linaro.org \ --to=lina.iyer@linaro.org \ --cc=ahaslam+renesas@baylibre.com \ --cc=andy.gross@linaro.org \ --cc=khilman@kernel.org \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-arm-msm@vger.kernel.org \ --cc=linux-pm@vger.kernel.org \ --cc=mtitinger+renesas@baylibre.com \ --cc=rjw@rjwysocki.net \ --cc=sboyd@codeaurora.org \ --cc=ulf.hansson@linaro.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.