From: Marc Titinger <mtitinger@baylibre.com>
To: khilman@kernel.org, rjw@rjwysocki.net
Cc: linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org,
ahaslam@baylibre.com, bcousson@baylibre.com,
lina.iyer@linaro.org, Marc Titinger <mtitinger@baylibre.com>
Subject: [RFC 4/7] PM / Domains: introduce power-states consistent with c-states.
Date: Fri, 25 Sep 2015 15:04:06 +0200 [thread overview]
Message-ID: <1443186249-14596-5-git-send-email-mtitinger+renesas@baylibre.com> (raw)
In-Reply-To: <1443186249-14596-1-git-send-email-mtitinger+renesas@baylibre.com>
From: Marc Titinger <mtitinger@baylibre.com>
This patch allows cluster-level C-states to being soaked in as generic
domain power states, in order for the domain governor to chose the most
efficient power state compatible with the device constraints. Similarly,
devices can register power-states into the cluster domain, in a manner
consistent with c-states.
With Juno, in this example the c-state 'cluster-sleep-0 ' is known from
each cluster generic domain, as the deepest sate.
cat /sys/kernel/debug/pm_genpd/*
Domain State name Enter (ns) / Exit (ns)
-------------------------------------------------------------
a53_pd cluster-sleep-0 1500000 / 800000
a57_pd cluster-sleep-0 1500000 / 800000
domain status pstate slaves
/device runtime status
-----------------------------------------------------------------------
a53_pd on
/devices/system/cpu/cpu0 active
/devices/system/cpu/cpu3 suspended
/devices/system/cpu/cpu4 suspended
/devices/system/cpu/cpu5 suspended
/devices/platform/D1 suspended
a57_pd cluster-sleep-0
/devices/system/cpu/cpu1 suspended
/devices/system/cpu/cpu2 suspended
Signed-off-by: Marc Titinger <mtitinger@baylibre.com>
---
.../devicetree/bindings/arm/idle-states.txt | 21 ++++-
.../devicetree/bindings/power/power_domain.txt | 29 ++++++
arch/arm/common/domains.c | 5 ++
arch/arm64/boot/dts/arm/juno.dts | 10 ++-
drivers/base/power/domain.c | 100 +++++++++++++++++++++
include/linux/pm_domain.h | 3 +
6 files changed, 163 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/arm/idle-states.txt b/Documentation/devicetree/bindings/arm/idle-states.txt
index a8274ea..18fdeaf 100644
--- a/Documentation/devicetree/bindings/arm/idle-states.txt
+++ b/Documentation/devicetree/bindings/arm/idle-states.txt
@@ -270,7 +270,8 @@ follows:
- compatible
Usage: Required
Value type: <stringlist>
- Definition: Must be "arm,idle-state".
+ Definition: Must be "arm,idle-state",
+ or "arm,power-state" (see section 5)
- local-timer-stop
Usage: See definition
@@ -680,7 +681,23 @@ cpus {
};
===========================================
-5 - References
+5 - power state
+===========================================
+
+Device in a generic power domain may expose an intermediate retention
+state that can be opted to by the domain governor when the last-man
+CPU is powered off. Those power-states will not be entered by the
+cpuidle.ops based on a state index, but instead can be elected by the
+domain governor and entered to by the generic domain.
+
+ - compatible
+ Usage: Required
+ Value type: <stringlist>
+ Definition: Must be "arm,power-state".
+
+
+===========================================
+6 - References
===========================================
[1] ARM Linux Kernel documentation - CPUs bindings
diff --git a/Documentation/devicetree/bindings/power/power_domain.txt b/Documentation/devicetree/bindings/power/power_domain.txt
index 0f8ed37..d437385 100644
--- a/Documentation/devicetree/bindings/power/power_domain.txt
+++ b/Documentation/devicetree/bindings/power/power_domain.txt
@@ -29,6 +29,16 @@ Optional properties:
specified by this binding. More details about power domain specifier are
available in the next section.
+ - power-states : a phandle of an idle-state that shall be soaked into a
+ generic domain power state.
+ CPU domains: Deep c-states that match a cluster power-off can be delegated to the
+ generic power domain. Device other than CPUs may have register intermediate
+ power states in the same domain. The domain governor can do a good job in
+ electing a power state when the last cpu is powered off as devices in the
+ same genpd may register intermediate states.
+ Devices : a device may register an intermediate c-state matching a memory
+ retention feature for instance.
+
Example:
power: power-controller@12340000 {
@@ -55,6 +65,25 @@ Example 2:
#power-domain-cells = <1>;
};
+Example 3:
+
+ pm-domains {
+ a57_pd: a57_pd@ {
+ /* will have a57 platform ARM_PD_METHOD_OF_DECLARE*/
+ compatible = "arm,pd","arm,cortex-a57";
+ #power-domain-cells = <0>;
+ power-states = <&CLUSTER_SLEEP_0>;
+ };
+
+ a53_pd: a53_pd@ {
+ /* will have a a53 platform ARM_PD_METHOD_OF_DECLARE*/
+ compatible = "arm,pd","arm,cortex-a53";
+ #power-domain-cells = <0>;
+ power-states = <&CLUSTER_SLEEP_0>;
+ };
+ };
+
+
The nodes above define two power controllers: 'parent' and 'child'.
Domains created by the 'child' power controller are subdomains of '0' power
domain provided by the 'parent' power controller.
diff --git a/arch/arm/common/domains.c b/arch/arm/common/domains.c
index 68908d4..6684776 100644
--- a/arch/arm/common/domains.c
+++ b/arch/arm/common/domains.c
@@ -191,6 +191,11 @@ static int __init arm_domain_init(void)
pm_genpd_init(&pd->genpd, &simple_qos_governor, NULL, 0, false);
of_genpd_add_provider_simple(np, &pd->genpd);
+ /* if a cpuidle-state is declared in this domain node, it will
+ be the domain's job to enter/exit this state, if the defice
+ /subdomain constraints are compatible */
+ of_genpd_device_parse_states(np, &pd->genpd);
+
count++;
}
diff --git a/arch/arm64/boot/dts/arm/juno.dts b/arch/arm64/boot/dts/arm/juno.dts
index 499f035..cadc5de 100644
--- a/arch/arm64/boot/dts/arm/juno.dts
+++ b/arch/arm64/boot/dts/arm/juno.dts
@@ -47,7 +47,7 @@
};
CLUSTER_SLEEP_0: cluster-sleep-0 {
- compatible = "arm,idle-state";
+ compatible = "arm,idle-state","arm,power-state";
arm,psci-suspend-param = <0x1010000>;
local-timer-stop;
entry-latency-us = <800>;
@@ -128,13 +128,17 @@
pm-domains {
a57_pd: a57_pd@ {
- compatible = "arm,pd";
+ /* will have the a53 platform ARM_PD_METHOD_OF_DECLARE*/
+ compatible = "arm,pd","arm,cortex-a57";
#power-domain-cells = <0>;
+ power-states = <&CLUSTER_SLEEP_0>;
};
a53_pd: a53_pd@ {
- compatible = "arm,pd";
+ /* will have the a53 platform ARM_PD_METHOD_OF_DECLARE*/
+ compatible = "arm,pd","arm,cortex-a57";
#power-domain-cells = <0>;
+ power-states = <&CLUSTER_SLEEP_0>;
};
};
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 8c8ea94..8259654 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -2285,6 +2285,104 @@ static void genpd_dev_pm_sync(struct device *dev)
genpd_queue_power_off_work(pd);
}
+static int dt_cpuidle_to_genpd_power_state(struct genpd_power_state
+ *genpd_state,
+ const struct of_device_id *matches,
+ struct device_node *state_node)
+{
+ const struct of_device_id *match_id;
+ int err = 0;
+ u32 latency;
+
+ match_id = of_match_node(matches, state_node);
+ if (!match_id)
+ return -ENODEV;
+
+ err = of_property_read_u32(state_node, "wakeup-latency-us", &latency);
+ if (err) {
+ u32 entry_latency, exit_latency;
+
+ 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;
+ }
+ /*
+ * If wakeup-latency-us is missing, default to entry+exit
+ * latencies as defined in idle states bindings
+ */
+ latency = entry_latency + exit_latency;
+ }
+
+ genpd_state->power_on_latency_ns = 1000 * latency;
+
+ err = of_property_read_u32(state_node, "entry-latency-us", &latency);
+ if (err) {
+ pr_debug(" * %s missing min-residency-us property\n",
+ state_node->full_name);
+ return -EINVAL;
+ }
+
+ genpd_state->power_off_latency_ns = 1000 * latency;
+
+ return 0;
+}
+
+static const struct of_device_id power_state_match[] = {
+ {.compatible = "arm,power-state",
+ },
+};
+
+int of_genpd_device_parse_states(struct device_node *np,
+ struct generic_pm_domain *genpd)
+{
+ struct device_node *state_node;
+ int i, err = 0;
+
+ for (i = 0;; i++) {
+ struct genpd_power_state genpd_state;
+
+ state_node = of_parse_phandle(np, "power-states", i);
+ if (!state_node)
+ break;
+
+ err = dt_cpuidle_to_genpd_power_state(&genpd_state,
+ power_state_match,
+ state_node);
+ if (err) {
+ pr_err
+ ("Parsing idle state node %s failed with err %d\n",
+ state_node->full_name, err);
+ err = -EINVAL;
+ break;
+ }
+#ifdef CONFIG_PM_ADVANCED_DEBUG
+ genpd_state.name = kstrndup(state_node->name,
+ GENPD_MAX_NAME_SIZE, GFP_KERNEL);
+ if (!genpd_state.name)
+ err = -ENOMEM;
+#endif
+ of_node_put(state_node);
+ err = pm_genpd_insert_state(genpd, &genpd_state);
+ if (err)
+ break;
+#ifdef CONFIG_PM_ADVANCED_DEBUG
+ kfree(genpd_state.name);
+#endif
+ }
+ return err;
+}
+
/**
* genpd_dev_pm_attach - Attach a device to its PM domain using DT.
* @dev: Device to attach.
@@ -2353,6 +2451,8 @@ int genpd_dev_pm_attach(struct device *dev)
return ret;
}
+ of_genpd_device_parse_states(dev->of_node, pd);
+
dev->pm_domain->detach = genpd_dev_pm_detach;
dev->pm_domain->sync = genpd_dev_pm_sync;
pm_genpd_poweron(pd);
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index 39dda2c..b0bff93 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -306,6 +306,9 @@ struct generic_pm_domain *__of_genpd_xlate_onecell(
struct of_phandle_args *genpdspec,
void *data);
+int of_genpd_device_parse_states(struct device_node *np,
+ struct generic_pm_domain *genpd);
+
int genpd_dev_pm_attach(struct device *dev);
#else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
static inline int __of_genpd_add_provider(struct device_node *np,
--
1.9.1
next prev parent reply other threads:[~2015-09-25 13:04 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-09-25 13:04 [RFC 0/7] Managing cluser-level c-states with generic power domains Marc Titinger
2015-09-25 13:04 ` [RFC 1/7] arm64: pm/domains: try mutualize CPU domains init between arm/arm64 Marc Titinger
2015-10-06 2:27 ` Lina Iyer
2015-10-06 8:52 ` Marc Titinger
2015-10-06 14:27 ` [RFC v2 0/6] Managing cluser-level c-states with generic power domains Marc Titinger
2015-10-06 14:27 ` [RFC v2 1/6] arm64: Juno: declare generic power domains for both clusters Marc Titinger
2015-10-06 14:27 ` [RFC v2 2/6] PM / Domains: prepare for devices that might register a power state Marc Titinger
2015-10-08 16:11 ` Lina Iyer
2015-10-09 9:39 ` Marc Titinger
2015-10-09 18:22 ` Lina Iyer
2015-10-13 10:29 ` Marc Titinger
2015-10-13 21:03 ` Kevin Hilman
2015-10-06 14:27 ` [RFC v2 3/6] PM / Domains: introduce power-states consistent with c-states Marc Titinger
2015-10-08 16:27 ` Lina Iyer
2015-10-09 10:04 ` Marc Titinger
2015-10-06 14:27 ` [RFC v2 4/6] PM / Domains: succeed & warn when attaching non-irqsafe devices to an irq-safe domain Marc Titinger
2015-10-06 14:27 ` [RFC v2 5/6] arm: cpuidle: let genpd handle the cluster power transition with 'power-states' Marc Titinger
2015-11-11 9:10 ` Zhaoyang Huang
2015-11-11 17:27 ` Lina Iyer
2015-10-06 14:27 ` [RFC v2 6/6] PM / Domains: add debugfs 'states' and 'timings' seq files Marc Titinger
2015-10-13 23:10 ` [RFC v2 0/6] Managing cluser-level c-states with generic power domains Kevin Hilman
2015-10-14 8:10 ` Axel Haslam
2015-10-19 20:58 ` Lina Iyer
2015-10-20 9:10 ` Marc Titinger
2015-10-27 17:40 ` [RFC v3 0/7] Managing cluser-level idle-states " Marc Titinger
2015-10-27 17:40 ` [RFC v3 1/7] PM / Domains: prepare for devices that might register a power state Marc Titinger
2015-10-27 17:40 ` [RFC v3 2/7] PM / Domains: support idle-states as genpd multiple-state Marc Titinger
2015-11-13 5:56 ` Zhaoyang Huang
2015-10-27 17:40 ` [RFC v3 3/7] arm64: dts: Add idle-states for Juno Marc Titinger
2015-10-27 17:40 ` [RFC v3 4/7] arm64: Juno: declare generic power domains for both clusters Marc Titinger
2015-10-27 17:40 ` [RFC v3 5/7] drivers: cpu-pd: allow calling of_cpu_pd_init from platform code Marc Titinger
2015-10-27 17:40 ` [RFC v3 6/7] arm64: PM /Domains: Initialize CPU-domains from DT Marc Titinger
2015-10-27 17:40 ` [RFC v3 7/7] arm64: Juno: declare idle-state cluster-sleep-0 as genpd state Marc Titinger
2015-09-25 13:04 ` [RFC 2/7] arm64: Juno: declare generic power domains for both clusters Marc Titinger
2015-09-25 13:04 ` [RFC 3/7] PM / Domains: prepare for devices that might register a power state Marc Titinger
2015-09-25 13:04 ` Marc Titinger [this message]
2015-09-25 13:04 ` [RFC 5/7] PM / Domains: succeed & warn when attaching non-irqsafe devices to an irq-safe domain Marc Titinger
2015-09-25 13:04 ` [RFC 6/7] arm: cpuidle: let genpd handle the cluster power transition with 'power-states' Marc Titinger
2015-09-25 13:04 ` [RFC 7/7] PM / Domains: add debugfs 'states' and 'timings' seq files Marc Titinger
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=1443186249-14596-5-git-send-email-mtitinger+renesas@baylibre.com \
--to=mtitinger@baylibre.com \
--cc=ahaslam@baylibre.com \
--cc=bcousson@baylibre.com \
--cc=khilman@kernel.org \
--cc=lina.iyer@linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=rjw@rjwysocki.net \
/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: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®