From: ulf.hansson@linaro.org (Ulf Hansson)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 8/9] PM / Domains: Add support for multi PM domains per device to genpd
Date: Fri, 18 May 2018 12:31:29 +0200 [thread overview]
Message-ID: <1526639490-12167-9-git-send-email-ulf.hansson@linaro.org> (raw)
In-Reply-To: <1526639490-12167-1-git-send-email-ulf.hansson@linaro.org>
To support devices being partitioned across multiple PM domains, let's
start by extending genpd to cope with these configurations.
More precisely, add a new exported function, genpd_dev_pm_attach_by_id(),
similar to genpd_dev_pm_attach(), but the new function also allows the
caller to provide an index to what PM domain it wants to attach.
Furthermore, let genpd register a new virtual struct device via calling
device_register() and attach it to the corresponding PM domain, which is
looked up via calling the existing genpd OF functions. Note that the new
device is needed, because only one PM domain can be attached per device. At
successful attachment, genpd_dev_pm_attach_by_id() returns the new device,
allowing the caller to operate on it to deal with power management.
To deal with detaching of a PM domain for multiple PM domain case, we can
still re-use the existing genpd_dev_pm_detach() function, although we need
to extend it to cover cleanup of the earlier registered device, via calling
device_unregister().
An important note, genpd_dev_pm_attach_by_id() shall only be called by the
driver core / PM core, similar to how genpd_dev_pm_attach() is used.
Following changes deploys this.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/base/power/domain.c | 79 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/pm_domain.h | 8 +++++
2 files changed, 87 insertions(+)
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index d538640..ffeb6ea 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -2171,6 +2171,15 @@ struct generic_pm_domain *of_genpd_remove_last(struct device_node *np)
}
EXPORT_SYMBOL_GPL(of_genpd_remove_last);
+static void genpd_release_dev(struct device *dev)
+{
+ kfree(dev);
+}
+
+static struct bus_type genpd_bus_type = {
+ .name = "genpd",
+};
+
/**
* genpd_dev_pm_detach - Detach a device from its PM domain.
* @dev: Device to detach.
@@ -2208,6 +2217,10 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off)
/* Check if PM domain can be powered off after removing this device. */
genpd_queue_power_off_work(pd);
+
+ /* Unregister the device if it was created by genpd. */
+ if (dev->bus == &genpd_bus_type)
+ device_unregister(dev);
}
static void genpd_dev_pm_sync(struct device *dev)
@@ -2298,6 +2311,66 @@ int genpd_dev_pm_attach(struct device *dev)
}
EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);
+/**
+ * genpd_dev_pm_attach_by_id() - Attach a device to one of its PM domain.
+ * @dev: Device to attach.
+ * @index: The index of the PM domain.
+ *
+ * Parse device's OF node to find a PM domain specifier at the provided @index.
+ * If such is found, allocates a new device and attaches it to retrieved
+ * pm_domain ops.
+ *
+ * Returns the allocated device if successfully attached PM domain, NULL when
+ * the device don't need a PM domain or have a single PM domain, else PTR_ERR()
+ * in case of failures. Note that if a power-domain exists for the device, but
+ * cannot be found or turned on, then return PTR_ERR(-EPROBE_DEFER) to ensure
+ * that the device is not probed and to re-try again later.
+ */
+struct device *genpd_dev_pm_attach_by_id(struct device *dev,
+ unsigned int index)
+{
+ struct device *genpd_dev;
+ int num_domains;
+ int ret;
+
+ if (!dev->of_node)
+ return NULL;
+
+ /* Deal only with devices using multiple PM domains. */
+ num_domains = of_count_phandle_with_args(dev->of_node, "power-domains",
+ "#power-domain-cells");
+ if (num_domains < 2 || index >= num_domains)
+ return NULL;
+
+ /* Allocate and register device on the genpd bus. */
+ genpd_dev = kzalloc(sizeof(*genpd_dev), GFP_KERNEL);
+ if (!genpd_dev)
+ return ERR_PTR(-ENOMEM);
+
+ dev_set_name(genpd_dev, "genpd:%u:%s", index, dev_name(dev));
+ genpd_dev->bus = &genpd_bus_type;
+ genpd_dev->release = genpd_release_dev;
+
+ ret = device_register(genpd_dev);
+ if (ret) {
+ kfree(genpd_dev);
+ return ERR_PTR(ret);
+ }
+
+ /* Try to attach the device to the PM domain at the specified index. */
+ ret = __genpd_dev_pm_attach(genpd_dev, dev->of_node, index);
+ if (ret < 1) {
+ device_unregister(genpd_dev);
+ return ret ? ERR_PTR(ret) : NULL;
+ }
+
+ pm_runtime_set_active(genpd_dev);
+ pm_runtime_enable(genpd_dev);
+
+ return genpd_dev;
+}
+EXPORT_SYMBOL_GPL(genpd_dev_pm_attach_by_id);
+
static const struct of_device_id idle_state_match[] = {
{ .compatible = "domain-idle-state", },
{ }
@@ -2456,6 +2529,12 @@ unsigned int of_genpd_opp_to_performance_state(struct device *dev,
}
EXPORT_SYMBOL_GPL(of_genpd_opp_to_performance_state);
+static int __init genpd_bus_init(void)
+{
+ return bus_register(&genpd_bus_type);
+}
+core_initcall(genpd_bus_init);
+
#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index 42e0d64..82458e8 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -237,6 +237,8 @@ unsigned int of_genpd_opp_to_performance_state(struct device *dev,
struct device_node *opp_node);
int genpd_dev_pm_attach(struct device *dev);
+struct device *genpd_dev_pm_attach_by_id(struct device *dev,
+ unsigned int index);
#else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
static inline int of_genpd_add_provider_simple(struct device_node *np,
struct generic_pm_domain *genpd)
@@ -282,6 +284,12 @@ static inline int genpd_dev_pm_attach(struct device *dev)
return 0;
}
+static inline struct device *genpd_dev_pm_attach_by_id(struct device *dev,
+ unsigned int index)
+{
+ return NULL;
+}
+
static inline
struct generic_pm_domain *of_genpd_remove_last(struct device_node *np)
{
--
2.7.4
next prev parent reply other threads:[~2018-05-18 10:31 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-05-18 10:31 [PATCH 0/9] PM / Domains: Add support for multi PM domains per device Ulf Hansson
2018-05-18 10:31 ` [PATCH 1/9] PM / Domains: Drop extern declarations of functions in pm_domain.h Ulf Hansson
2018-05-18 10:31 ` [PATCH 2/9] PM / Domains: Drop __pm_genpd_add_device() Ulf Hansson
2018-05-18 10:31 ` [PATCH 3/9] PM / Domains: Drop genpd as in-param for pm_genpd_remove_device() Ulf Hansson
2018-05-18 10:31 ` [PATCH 4/9] PM / Domains: Drop unused parameter in genpd_allocate_dev_data() Ulf Hansson
2018-05-18 10:31 ` [PATCH 5/9] PM / Domains: dt: Allow power-domain property to be a list of phandles Ulf Hansson
2018-05-18 10:46 ` Geert Uytterhoeven
2018-05-18 10:31 ` [PATCH 6/9] PM / Domains: Don't attach devices in genpd with multi PM domains Ulf Hansson
2018-05-18 10:31 ` [PATCH 7/9] PM / Domains: Split genpd_dev_pm_attach() Ulf Hansson
2018-05-18 10:31 ` Ulf Hansson [this message]
2018-05-22 14:31 ` [PATCH 8/9] PM / Domains: Add support for multi PM domains per device to genpd Jon Hunter
2018-05-22 14:47 ` Ulf Hansson
2018-05-22 20:55 ` Jon Hunter
2018-05-23 4:51 ` Rajendra Nayak
2018-05-23 6:12 ` Ulf Hansson
2018-05-23 9:07 ` Jon Hunter
2018-05-23 9:27 ` Rajendra Nayak
2018-05-23 9:33 ` Ulf Hansson
2018-05-23 9:45 ` Jon Hunter
2018-05-23 9:47 ` Ulf Hansson
2018-05-23 10:22 ` Jon Hunter
2018-05-24 7:04 ` Ulf Hansson
2018-05-24 9:36 ` Jon Hunter
2018-05-24 12:17 ` Ulf Hansson
2018-05-24 14:34 ` Jon Hunter
2018-05-24 21:21 ` Ulf Hansson
2018-05-25 8:22 ` Jon Hunter
2018-05-18 10:31 ` [PATCH 9/9] PM / Domains: Add dev_pm_domain_attach_by_id() to manage multi PM domains Ulf Hansson
2018-05-24 15:48 ` Jon Hunter
2018-05-24 21:11 ` Ulf Hansson
2018-05-25 8:31 ` Jon Hunter
2018-05-25 10:45 ` Ulf Hansson
2018-05-25 11:07 ` Jon Hunter
2018-05-25 12:34 ` Ulf Hansson
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=1526639490-12167-9-git-send-email-ulf.hansson@linaro.org \
--to=ulf.hansson@linaro.org \
--cc=linux-arm-kernel@lists.infradead.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: 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;
as well as URLs for NNTP newsgroup(s).