Changes in v2:
- Fix the ACPI patch, it didn't even compile for CONFIG_ACPI.
- Updated some comments in code and in commit messages.
- Fixed the dev_pm_domain_attach API to handle EPROBE_DEFER properly.
- Rebased the ARM Exynos patch.
- Added some Tested-by tags.
This patchset has a bit of a history and some parts of it has been posted
earlier.
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-June/262725.html
In the first revision I intentially didn't increase version number of the
patches, since I think it would have cause more confusion than clarity.
A summary of changes in V1 and since the last patchset, from the link above:
- Instead of letting driver core handling the device to power domain
binding/unbinding, follow the behavior of how the ACPI power domain
is handled.
This is a summary of what these patches are intended to do:
1)
Add generic power domain OF-based support which also includes APIs to handle
attach/detach of generic power domains to devices.
2)
Adding a common API to attach/detach power domains and include support for the
ACPI and the generic power domain in there.
3)
From subsystem level code, at probe/remove, convert from invoking the ACPI
specific power domain attach/detach functions to the new common attach/detach
APIs.
4)
Add support for the AMBA bus to attach/detach power domains, using the new
common APIs.
5)
Convert Exynos to use the new generic power domain OF support.
Obviously, there are dependencies througout this patchset, which means if they
get accepted the all need to go together. It might also be convenient to share
them through an immutable branch.
Tomasz Figa (2):
PM / Domains: Add generic OF-based power domain look-up
ARM: exynos: Move to generic power domain bindings
Ulf Hansson (7):
ACPI / PM: Let acpi_dev_pm_detach() return an error code
PM / Domains: Add APIs to attach/detach a PM domain for a device
drivercore / platform: Convert to dev_pm_domain_attach|detach()
i2c: core: Convert to dev_pm_domain_attach|detach()
mmc: sdio: Convert to dev_pm_domain_attach|detach()
spi: core: Convert to dev_pm_domain_attach|detach()
amba: Add support for attach/detach of power domains
.../bindings/arm/exynos/power_domain.txt | 13 +-
.../devicetree/bindings/power/power_domain.txt | 51 ++++
arch/arm/mach-exynos/pm_domains.c | 78 +-----
drivers/acpi/device_pm.c | 8 +-
drivers/amba/bus.c | 10 +-
drivers/base/platform.c | 15 +-
drivers/base/power/common.c | 56 ++++
drivers/base/power/domain.c | 291 +++++++++++++++++++++
drivers/i2c/i2c-core.c | 13 +-
drivers/mmc/core/sdio_bus.c | 4 +-
drivers/spi/spi.c | 12 +-
include/linux/acpi.h | 7 +-
include/linux/pm.h | 14 +
include/linux/pm_domain.h | 46 ++++
kernel/power/Kconfig | 4 +
15 files changed, 515 insertions(+), 107 deletions(-)
create mode 100644 Documentation/devicetree/bindings/power/power_domain.txt
--
1.9.1
Hi Ulf, Tomasz,
On Thu, Aug 28, 2014 at 10:38 AM, Ulf Hansson [off-list ref] wrote:
From: Tomasz Figa <redacted>
This patch introduces generic code to perform power domain look-up using
Should "power domain" be replaced by "PM domain" here (and everywhere else
in this patch), too, cfr. Rafael's earlier comment?
quoted hunk
+++ b/Documentation/devicetree/bindings/power/power_domain.txt
@@ -0,0 +1,51 @@
+* Generic power domains
+
+System on chip designs are often divided into multiple power domains that
+can be used for power gating of selected IP blocks for power saving by
+reduced leakage current.
+
+This device tree binding can be used to bind power domain consumer devices
+with their power domains provided by power domain providers. A power domain
+provider can be represented by any node in the device tree and can provide
+one or more power domains. A consumer node can refer to the provider by
+a phandle and a set of phandle arguments (so called power domain specifier)
specifiers
+of length specified by #power-domain-cells property in the power domain
the #power-domain-cells property
+provider node.
+
+==Power domain providers==
+
+Required properties:
+ - #power-domain-cells : Number of cells in a power domain specifier;
+ Typically 0 for nodes representing a single power domain and 1 for nodes
+ providing multiple power domains (e.g. power controllers), but can be
+ any value as specified by device tree binding documentation of particular
+ provider.
+
+Example:
+
+ power: power-controller at 12340000 {
+ compatible = "foo,power-controller";
+ reg = <0x12340000 0x1000>;
+ #power-domain-cells = <1>;
+ };
+
+The node above defines a power controller that is a power domain provider
+and expects one cell as its phandle argument.
+
+==Power domain consumers==
+
+Required properties:
+ - power-domains : A phandle and power domain specifier as defined by bindings
+ of power controller specified by phandle.
the power controller
+
+Example:
+
+ leaky-device at 12350000 {
+ compatible = "foo,i-leak-current";
+ reg = <0x12350000 0x1000>;
+ power-domains = <&power 0>;
+ };
+
+The node above defines a typical power domain consumer device, which is located
+inside power domain with index 0 of power controller represented by node with
the power domain ... the power controller ... the node
+label "power".
quoted hunk
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
+#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
+/*
+ * Device Tree based power domain providers.
+ *
+ * The code below implements generic device tree based power domain providers
+ * that bind device tree nodes with generic power domains registered in the
+ * system.
+ *
+ * Any driver that registers generic power domains and need to support binding
needs
+ * of devices to these domains is supposed to register a power domain provider,
+ * which maps a power domain specifier retrieved from device tree to a power
the device tree
+/**
+ * of_genpd_xlate_onecell() - Xlate function for providers using single index.
a single index
+ * @genpdspec: OF phandle args to map into a power domain
+ * @data: xlate function private data - pointer to struct genpd_onecell_data
+ *
+ * This is a generic xlate function that can be used to model simple power
+ * domain controllers that have one device tree node and provide multiple
+ * power domains. A single cell is used as an index to an array of power
an index into
+ * domains specified in genpd_onecell_data struct when registering the
the genpd_onecell_data struct
+ * provider.
+ */
+struct generic_pm_domain *of_genpd_xlate_onecell(
+ struct of_phandle_args *genpdspec,
+ void *data)
+{
+ struct genpd_onecell_data *genpd_data = data;
+ unsigned int idx = genpdspec->args[0];
+
+ if (genpdspec->args_count != 1)
+ return ERR_PTR(-EINVAL);
+
+ if (idx >= genpd_data->domain_num) {
+ pr_err("%s: invalid domain index %d\n", __func__, idx);
%u for unsigned int idx
+ return ERR_PTR(-EINVAL);
+ }
+
+ return genpd_data->domains[idx];
This assumes ->domains[] is a contiguous array.
I'd add a NULL check here, to translate NULL to ERR_PTR(-Esomething),
so it can support sparse power domain spaces.
E.g. indexed by the "bit_shift" value of struct rmobile_pm_domain, which
is the actual bit number to use to power up/down an R-Mobile domain.
Different members of the R-Mobile family have different numbers of
domains, and use more or less bits in the same power up/down registers.
This would be similar to the sparse clock-indices handling in
renesas,cpg-mstp-clocks.
+}
+EXPORT_SYMBOL_GPL(of_genpd_xlate_onecell);
+
+/**
+ * of_genpd_add_provider() - Register a domain provider for a node
+ * @np: Device node pointer associated with domain provider.
the domain provider
+/**
+ * of_genpd_del_provider() - Remove a previously registered domain provider
+ * @np: Device node pointer associated with domain provider
the domain provider
+/**
+ * of_genpd_get_from_provider() - Look-up power domain
+ * @genpdspec: OF phandle args to use for look-up
+ *
+ * Looks for domain provider under node specified by @genpdspec and if found
a domain provider ... under the node
+ * uses xlate function of the provider to map phandle args to a power domain.
+/**
+ * genpd_dev_pm_attach - Attach a device to it's power domain using DT.
its
+ * @dev: Device to attach.
+/**
+ * genpd_dev_pm_detach - Detach a device from it's power domain.
its
+ * @dev: Device to attach.
+ *
+ * Try to locate a corresponding generic power domain, which the device
+ * then previously were attached to. If found the device is detached from
"was attached to previously"?
+ * the power domain.
quoted hunk
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index 7c1d252..5989758 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -310,4 +310,50 @@ static inline void pm_genpd_syscore_poweron(struct device *dev)
pm_genpd_syscore_switch(dev, false);
}
+/* OF power domain providers */
+struct of_device_id;
+
+struct genpd_onecell_data {
+ struct generic_pm_domain **domains;
+ unsigned int domain_num;
This is the number of domains: "num_domains"?
+};
+
+typedef struct generic_pm_domain *(*genpd_xlate_t)(struct of_phandle_args *args,
+ void *data);
+
+#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
+int of_genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,
+ void *data);
+void of_genpd_del_provider(struct device_node *np);
+
+struct generic_pm_domain *of_genpd_xlate_simple(
+ struct of_phandle_args *genpdspec,
+ void *data);
+struct generic_pm_domain *of_genpd_xlate_onecell(
+ struct of_phandle_args *genpdspec,
+ void *data);
+
+int genpd_dev_pm_attach(struct device *dev);
+int genpd_dev_pm_detach(struct device *dev);
+#else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
+static inline int of_genpd_add_provider(struct device_node *np,
+ genpd_xlate_t xlate, void *data)
+{
+ return 0;
+}
+static inline void of_genpd_del_provider(struct device_node *np) {}
+
+#define of_genpd_xlate_simple NULL
+#define of_genpd_xlate_onecell NULL
+
+static inline int genpd_dev_pm_attach(struct device *dev)
+{
+ return -ENODEV;
+}
+static inline int genpd_dev_pm_detach(struct device *dev)
+{
+ return -ENODEV;
+}
+#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
As of_genpd_add_provider() provides no compile-time type-checking for
"void *data", I propose to prepend a double underscore to
of_genpd_add_provider(), and to the xlate helpers of_genpd_xlate_simple()
and of_genpd_xlate_onecell(), and provide type-checking wrappers:
static inline int of_genpd_add_provider_simple(struct device_node *np,
struct generic_pm_domain *genpd)
{
return __of_genpd_add_provider(np, __of_genpd_xlate_simple, genpd);
}
static inline int of_genpd_add_provider_onecell(struct device_node *np,
struct genpd_onecell_data *data)
{
return __of_genpd_add_provider(np, __of_genpd_xlate_onecell, data);
}
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
On 2 September 2014 20:28, Geert Uytterhoeven [off-list ref] wrote:
Hi Ulf, Tomasz,
On Thu, Aug 28, 2014 at 10:38 AM, Ulf Hansson [off-list ref] wrote:
quoted
From: Tomasz Figa <redacted>
This patch introduces generic code to perform power domain look-up using
Should "power domain" be replaced by "PM domain" here (and everywhere else
in this patch), too, cfr. Rafael's earlier comment?
Hi Geert,
Thanks for reviewing!
I changed some of the other patches according to Rafael's earlier
comment, but decided to keep this as is. The reason is that in
drivers/base/power/domain.c there are already a mix between using
"power domain" and "PM domain", thus I couldn't decide which way to
go.
I have no strong opinion of what terminology we use, I am happy to
change this patch. Since I anyway will be sending new version, I will
update to "PM domain".
quoted
+++ b/Documentation/devicetree/bindings/power/power_domain.txt
@@ -0,0 +1,51 @@
+* Generic power domains
+
+System on chip designs are often divided into multiple power domains that
+can be used for power gating of selected IP blocks for power saving by
+reduced leakage current.
+
+This device tree binding can be used to bind power domain consumer devices
+with their power domains provided by power domain providers. A power domain
+provider can be represented by any node in the device tree and can provide
+one or more power domains. A consumer node can refer to the provider by
+a phandle and a set of phandle arguments (so called power domain specifier)
specifiers
quoted
+of length specified by #power-domain-cells property in the power domain
the #power-domain-cells property
quoted
+provider node.
+
+==Power domain providers==
+
+Required properties:
+ - #power-domain-cells : Number of cells in a power domain specifier;
+ Typically 0 for nodes representing a single power domain and 1 for nodes
+ providing multiple power domains (e.g. power controllers), but can be
+ any value as specified by device tree binding documentation of particular
+ provider.
+
+Example:
+
+ power: power-controller at 12340000 {
+ compatible = "foo,power-controller";
+ reg = <0x12340000 0x1000>;
+ #power-domain-cells = <1>;
+ };
+
+The node above defines a power controller that is a power domain provider
+and expects one cell as its phandle argument.
+
+==Power domain consumers==
+
+Required properties:
+ - power-domains : A phandle and power domain specifier as defined by bindings
+ of power controller specified by phandle.
the power controller
quoted
+
+Example:
+
+ leaky-device at 12350000 {
+ compatible = "foo,i-leak-current";
+ reg = <0x12350000 0x1000>;
+ power-domains = <&power 0>;
+ };
+
+The node above defines a typical power domain consumer device, which is located
+inside power domain with index 0 of power controller represented by node with
the power domain ... the power controller ... the node
quoted
+label "power".
quoted
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
quoted
+#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
+/*
+ * Device Tree based power domain providers.
+ *
+ * The code below implements generic device tree based power domain providers
+ * that bind device tree nodes with generic power domains registered in the
+ * system.
+ *
+ * Any driver that registers generic power domains and need to support binding
needs
quoted
+ * of devices to these domains is supposed to register a power domain provider,
+ * which maps a power domain specifier retrieved from device tree to a power
the device tree
quoted
+/**
+ * of_genpd_xlate_onecell() - Xlate function for providers using single index.
a single index
quoted
+ * @genpdspec: OF phandle args to map into a power domain
+ * @data: xlate function private data - pointer to struct genpd_onecell_data
+ *
+ * This is a generic xlate function that can be used to model simple power
+ * domain controllers that have one device tree node and provide multiple
+ * power domains. A single cell is used as an index to an array of power
an index into
quoted
+ * domains specified in genpd_onecell_data struct when registering the
the genpd_onecell_data struct
quoted
+ * provider.
+ */
+struct generic_pm_domain *of_genpd_xlate_onecell(
+ struct of_phandle_args *genpdspec,
+ void *data)
+{
+ struct genpd_onecell_data *genpd_data = data;
+ unsigned int idx = genpdspec->args[0];
+
+ if (genpdspec->args_count != 1)
+ return ERR_PTR(-EINVAL);
+
+ if (idx >= genpd_data->domain_num) {
+ pr_err("%s: invalid domain index %d\n", __func__, idx);
%u for unsigned int idx
quoted
+ return ERR_PTR(-EINVAL);
+ }
+
+ return genpd_data->domains[idx];
This assumes ->domains[] is a contiguous array.
I'd add a NULL check here, to translate NULL to ERR_PTR(-Esomething),
so it can support sparse power domain spaces.
E.g. indexed by the "bit_shift" value of struct rmobile_pm_domain, which
is the actual bit number to use to power up/down an R-Mobile domain.
Different members of the R-Mobile family have different numbers of
domains, and use more or less bits in the same power up/down registers.
This would be similar to the sparse clock-indices handling in
renesas,cpg-mstp-clocks.
OK, will do!
quoted
+}
+EXPORT_SYMBOL_GPL(of_genpd_xlate_onecell);
+
+/**
+ * of_genpd_add_provider() - Register a domain provider for a node
+ * @np: Device node pointer associated with domain provider.
the domain provider
quoted
+/**
+ * of_genpd_del_provider() - Remove a previously registered domain provider
+ * @np: Device node pointer associated with domain provider
the domain provider
quoted
+/**
+ * of_genpd_get_from_provider() - Look-up power domain
+ * @genpdspec: OF phandle args to use for look-up
+ *
+ * Looks for domain provider under node specified by @genpdspec and if found
a domain provider ... under the node
quoted
+ * uses xlate function of the provider to map phandle args to a power domain.
quoted
+/**
+ * genpd_dev_pm_attach - Attach a device to it's power domain using DT.
its
quoted
+ * @dev: Device to attach.
quoted
+/**
+ * genpd_dev_pm_detach - Detach a device from it's power domain.
its
quoted
+ * @dev: Device to attach.
+ *
+ * Try to locate a corresponding generic power domain, which the device
+ * then previously were attached to. If found the device is detached from
"was attached to previously"?
quoted
+ * the power domain.
quoted
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index 7c1d252..5989758 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -310,4 +310,50 @@ static inline void pm_genpd_syscore_poweron(struct device *dev)
pm_genpd_syscore_switch(dev, false);
}
+/* OF power domain providers */
+struct of_device_id;
+
+struct genpd_onecell_data {
+ struct generic_pm_domain **domains;
+ unsigned int domain_num;
This is the number of domains: "num_domains"?
OK, that describes it better.
quoted
+};
+
+typedef struct generic_pm_domain *(*genpd_xlate_t)(struct of_phandle_args *args,
+ void *data);
+
+#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
+int of_genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,
+ void *data);
+void of_genpd_del_provider(struct device_node *np);
+
+struct generic_pm_domain *of_genpd_xlate_simple(
+ struct of_phandle_args *genpdspec,
+ void *data);
+struct generic_pm_domain *of_genpd_xlate_onecell(
+ struct of_phandle_args *genpdspec,
+ void *data);
+
+int genpd_dev_pm_attach(struct device *dev);
+int genpd_dev_pm_detach(struct device *dev);
+#else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
+static inline int of_genpd_add_provider(struct device_node *np,
+ genpd_xlate_t xlate, void *data)
+{
+ return 0;
+}
+static inline void of_genpd_del_provider(struct device_node *np) {}
+
+#define of_genpd_xlate_simple NULL
+#define of_genpd_xlate_onecell NULL
+
+static inline int genpd_dev_pm_attach(struct device *dev)
+{
+ return -ENODEV;
+}
+static inline int genpd_dev_pm_detach(struct device *dev)
+{
+ return -ENODEV;
+}
+#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
As of_genpd_add_provider() provides no compile-time type-checking for
"void *data", I propose to prepend a double underscore to
of_genpd_add_provider(), and to the xlate helpers of_genpd_xlate_simple()
and of_genpd_xlate_onecell(), and provide type-checking wrappers:
Good idea, I will give it a try in next version.
static inline int of_genpd_add_provider_simple(struct device_node *np,
struct generic_pm_domain *genpd)
{
return __of_genpd_add_provider(np, __of_genpd_xlate_simple, genpd);
}
static inline int of_genpd_add_provider_onecell(struct device_node *np,
struct genpd_onecell_data *data)
{
return __of_genpd_add_provider(np, __of_genpd_xlate_onecell, data);
}
Thanks for all the grammar/English corrections as well. Will update.
Kind regards
Uffe