Skip to contentSkip to conversation

ARM: EXYNOS: Power domain DT support extension

PATCH New Tomasz Figa 3 participants 10 messages Sep 6, 2012 – Sep 19, 2012

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

cover ARM: EXYNOS: Power domain DT support extension

This patch series fixes two issues with existing DT support for Exynos power domains and extends it with the ability of binding devices to domains, basically making it possible to use power domains when using DT.

Tomasz Figa (3):
ARM: EXYNOS: pm_domain: Detect domain state on registration from DT
ARM: EXYNOS: pm_domain: Fix power domain name initialization
ARM: EXYNOS: pm_domain: Bind devices to power domains using DT

 .../bindings/arm/exynos/power_domain.txt           | 15 +++-
 arch/arm/mach-exynos/pm_domains.c                  | 93 +++++++++++++++++++++-
 2 files changed, 100 insertions(+), 8 deletions(-)
Signature · 1 line
1.7.12
#1 lore raw

PATCH 1/3 ARM: EXYNOS: pm_domain: Detect domain state on registration from DT

Initial state of power domains might vary on different boards and with different bootloaders. This patch adds detection of initial state of power domains when being registered from DT.

---
 Documentation/devicetree/bindings/arm/exynos/power_domain.txt | 4 ----
 arch/arm/mach-exynos/pm_domains.c                             | 8 +++++---
 2 files changed, 5 insertions(+), 7 deletions(-)
Documentation/devicetree/bindings/arm/exynos/power_domain.txt +0 -4
index 6528e21..843b546 100644
@@ -9,10 +9,6 @@ Required Properties:
 - reg: physical base address of the controller and length of memory mapped
     region.
 
-Optional Properties:
-- samsung,exynos4210-pd-off: Specifies that the power domain is in turned-off
-    state during boot and remains to be turned-off until explicitly turned-on.
-
 Example:
 
 	lcd0: power-domain-lcd0 {
arch/arm/mach-exynos/pm_domains.c +5 -3
index c0bc83a..d1abc1a 100644
@@ -89,6 +89,7 @@ static __init int exynos_pm_dt_parse_domains(void)
 
 	for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") {
 		struct exynos_pm_domain *pd;
+		int on;
 
 		pd = kzalloc(sizeof(*pd), GFP_KERNEL);
 		if (!pd) {
@@ -97,14 +98,15 @@ static __init int exynos_pm_dt_parse_domains(void)
 			return -ENOMEM;
 		}
 
-		if (of_get_property(np, "samsung,exynos4210-pd-off", NULL))
-			pd->is_off = true;
 		pd->name = np->name;
 		pd->base = of_iomap(np, 0);
 		pd->pd.power_off = exynos_pd_power_off;
 		pd->pd.power_on = exynos_pd_power_on;
 		pd->pd.of_node = np;
-		pm_genpd_init(&pd->pd, NULL, false);
+
+		on = __raw_readl(pd->base + 0x4) & S5P_INT_LOCAL_PWR_EN;
+
+		pm_genpd_init(&pd->pd, NULL, !on);
 	}
 	return 0;
 }
Signature · 1 line
1.7.12
#2 lore raw

PATCH 1/3 ARM: EXYNOS: pm_domain: Detect domain state on registration from DT

Quoted 47 lines · Tomasz Figa

Initial state of power domains might vary on different boards and with different bootloaders. This patch adds detection of initial state of power domains when being registered from DT.

---
 Documentation/devicetree/bindings/arm/exynos/power_domain.txt | 4 ----
 arch/arm/mach-exynos/pm_domains.c                             | 8 +++++---
 2 files changed, 5 insertions(+), 7 deletions(-)
Documentation/devicetree/bindings/arm/exynos/power_domain.txt +0 -4
index 6528e21..843b546 100644
@@ -9,10 +9,6 @@ Required Properties:
 - reg: physical base address of the controller and length of memory mapped
     region.
 
-Optional Properties:
-- samsung,exynos4210-pd-off: Specifies that the power domain is in turned-off
-    state during boot and remains to be turned-off until explicitly turned-on.
-
 Example:
 
        lcd0: power-domain-lcd0 {
arch/arm/mach-exynos/pm_domains.c +1 -2
index c0bc83a..d1abc1a 100644
@@ -89,6 +89,7 @@ static __init int exynos_pm_dt_parse_domains(void)
 
        for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") {
                struct exynos_pm_domain *pd;
+               int on;
 
                pd = kzalloc(sizeof(*pd), GFP_KERNEL);
                if (!pd) {
@@ -97,14 +98,15 @@ static __init int exynos_pm_dt_parse_domains(void)
                        return -ENOMEM;
                }
 
-               if (of_get_property(np, "samsung,exynos4210-pd-off", NULL))
-                       pd->is_off = true;
                pd->name = np->name;
                pd->base = of_iomap(np, 0);
                pd->pd.power_off = exynos_pd_power_off;

arch/arm/mach-exynos/pm_domains.c static __init int exynos_pm_dt_parse_domains(void) · line 112

Quoted 10 lines
arch/arm/mach-exynos/pm_domains.c +4 -1
                pd->pd.power_on = exynos_pd_power_on;
                pd->pd.of_node = np;
-               pm_genpd_init(&pd->pd, NULL, false);
+
+               on = __raw_readl(pd->base + 0x4) & S5P_INT_LOCAL_PWR_EN;
+
+               pm_genpd_init(&pd->pd, NULL, !on);
        }
        return 0;
 }
#3 lore raw

PATCH 2/3 ARM: EXYNOS: pm_domain: Fix power domain name initialization

In reply to Tomasz Figa

This patch adds initialization of name field in generic power domain struct.

---
 arch/arm/mach-exynos/pm_domains.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
arch/arm/mach-exynos/pm_domains.c +2 -1
index d1abc1a..5b7ce7e 100644
@@ -98,7 +98,8 @@ static __init int exynos_pm_dt_parse_domains(void)
 			return -ENOMEM;
 		}
 
-		pd->name = np->name;
+		pd->pd.name = kstrdup(np->name, GFP_KERNEL);
+		pd->name = pd->pd.name;
 		pd->base = of_iomap(np, 0);
 		pd->pd.power_off = exynos_pd_power_off;
 		pd->pd.power_on = exynos_pd_power_on;
Signature · 1 line
1.7.12
#4 lore raw

PATCH 2/3 ARM: EXYNOS: pm_domain: Fix power domain name initialization

Quoted 14 lines · Tomasz Figa

This patch adds initialization of name field in generic power domain struct.

---
 arch/arm/mach-exynos/pm_domains.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
arch/arm/mach-exynos/pm_domains.c +0 -0
index d1abc1a..5b7ce7e 100644

arch/arm/mach-exynos/pm_domains.c static __init int exynos_pm_dt_parse_domains(void) · line 102

Quoted 6 lines
arch/arm/mach-exynos/pm_domains.c +2 -1
@@ -98,7 +98,8 @@ static __init int exynos_pm_dt_parse_domains(void)
                        return -ENOMEM;
                }
 
-               pd->name = np->name;
+               pd->pd.name = kstrdup(np->name, GFP_KERNEL);
+               pd->name = pd->pd.name;

Since device tree blob is always resident, why not just use np->name instead of copying it to a new place?

Quoted 6 lines
arch/arm/mach-exynos/pm_domains.c +0 -1
                pd->base = of_iomap(np, 0);
                pd->pd.power_off = exynos_pd_power_off;
                pd->pd.power_on = exynos_pd_power_on;
--

1.7.12

#5 lore raw

PATCH 2/3 ARM: EXYNOS: pm_domain: Fix power domain name initialization

Hi Thomas,

Quoted 6 lines · On Saturday 08 of September 2012 13:37:59 Thomas Abraham wrote:

arch/arm/mach-exynos/pm_domains.c static __init int exynos_pm_dt_parse_domains(void) · line 102

Quoted 3 lines
arch/arm/mach-exynos/pm_domains.c +2 -1
-               pd->name = np->name;
+               pd->pd.name = kstrdup(np->name, GFP_KERNEL);
+               pd->name = pd->pd.name;

Since device tree blob is always resident, why not just use np->name instead of copying it to a new place?

The problem is that np->name is const, while pd->pd.name is not.

--
Best regards,
Tomasz Figa

#6 lore raw

PATCH 3/3 ARM: EXYNOS: pm_domain: Bind devices to power domains using DT

In reply to Tomasz Figa

This patch adds a way to specify bindings between devices and power domains using device tree.

A device can be bound to particular power domain by adding a power-domain property containing a phandle to the domain. The device will be bound to the domain before binding a driver to it and unbound after unbinding a driver from it.

---
 .../bindings/arm/exynos/power_domain.txt           | 13 +++-
 arch/arm/mach-exynos/pm_domains.c                  | 82 ++++++++++++++++++++++
 2 files changed, 94 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/arm/exynos/power_domain.txt +12 -1
index 843b546..8ed914f 100644
@@ -4,14 +4,25 @@ Exynos processors include support for multiple power domains which are used
 to gate power to one or more peripherals on the processor.
 
 Required Properties:
-- compatiable: should be one of the following.
+- compatible: should be one of the following.
     * samsung,exynos4210-pd - for exynos4210 type power domain.
 - reg: physical base address of the controller and length of memory mapped
     region.
 
+Node of a device using power domains must have a power-domain property defined
+with a phandle to respective power domain.
+
 Example:
 
 	lcd0: power-domain-lcd0 {
 		compatible = "samsung,exynos4210-pd";
 		reg = <0x10023C00 0x10>;
 	};
+
+Example of the node using power domain:
+
+	node {
+		/* ... */
+		power-domain = <&lcd0>;
+		/* ... */
+	};
arch/arm/mach-exynos/pm_domains.c +82 -0

112 lines not on this page · raw message

Signature · 1 line
1.7.12
#7 lore raw

PATCH 3/3 ARM: EXYNOS: pm_domain: Bind devices to power domains using DT

Quoted 36 lines · Tomasz Figa

This patch adds a way to specify bindings between devices and power domains using device tree.

A device can be bound to particular power domain by adding a power-domain property containing a phandle to the domain. The device will be bound to the domain before binding a driver to it and unbound after unbinding a driver from it.

---
 .../bindings/arm/exynos/power_domain.txt           | 13 +++-
 arch/arm/mach-exynos/pm_domains.c                  | 82 ++++++++++++++++++++++
 2 files changed, 94 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/arm/exynos/power_domain.txt +4 -1
index 843b546..8ed914f 100644
@@ -4,14 +4,25 @@ Exynos processors include support for multiple power domains which are used
 to gate power to one or more peripherals on the processor.
 
 Required Properties:
-- compatiable: should be one of the following.
+- compatible: should be one of the following.
     * samsung,exynos4210-pd - for exynos4210 type power domain.
 - reg: physical base address of the controller and length of memory mapped
     region.
 
+Node of a device using power domains must have a power-domain property defined
+with a phandle to respective power domain.
+
 Example:
 
        lcd0: power-domain-lcd0 {
                compatible = "samsung,exynos4210-pd";

Documentation/devicetree/bindings/arm/exynos/power_domain.txt Exynos processors include support for multiple power domains which are used · line 28

Quoted 10 lines
Documentation/devicetree/bindings/arm/exynos/power_domain.txt +8 -0
                reg = <0x10023C00 0x10>;
        };
+
+Example of the node using power domain:
+
+       node {
+               /* ... */
+               power-domain = <&lcd0>;
+               /* ... */
+       };

Since the value of power-domain property is mostly samsung specific, should this be "samsung,power-domain" ?

Quoted 54 lines
arch/arm/mach-exynos/pm_domains.c +39 -0
index 5b7ce7e..7b3b8a3 100644
@@ -19,6 +19,8 @@
 #include <linux/pm_domain.h>
 #include <linux/delay.h>
 #include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/sched.h>
 
 #include <mach/regs-pmu.h>
 #include <plat/devs.h>
@@ -83,14 +85,89 @@ static struct exynos_pm_domain PD = {                       \
 }
 
 #ifdef CONFIG_OF
+static void exynos_add_device_to_domain(struct exynos_pm_domain *pd,
+                                                       struct device *dev)
+{
+       int ret;
+
+       dev_dbg(dev, "adding to power domain %s\n", pd->pd.name);
+
+       while(1) {
+               ret = pm_genpd_add_device(&pd->pd, dev);
+               if (ret != -EAGAIN)
+                       break;
+               cond_resched();
+       }
+
+       pm_genpd_dev_need_restore(dev, true);
+}
+
+static void exynos_remove_device_from_domain(struct device *dev)
+{
+       struct generic_pm_domain *genpd = dev_to_genpd(dev);
+       int ret;
+
+       dev_dbg(dev, "removing from power domain %s\n", genpd->name);
+
+       while(1) {
+               ret = pm_genpd_remove_device(genpd, dev);
+               if (ret != -EAGAIN)
+                       break;
+               cond_resched();
+       }
+}
+
+static void exynos_read_domain_from_dt(struct device *dev)
+{
+       struct platform_device *pd_pdev;
+       struct exynos_pm_domain *pd;
+       struct device_node *node;

arch/arm/mach-exynos/pm_domains.c static struct exynos_pm_domain PD = { \ · line 134

Quoted 10 lines
arch/arm/mach-exynos/pm_domains.c +10 -0
+
+       node = of_parse_phandle(dev->of_node, "power-domain", 0);
+       if (!node)
+               return;
+       pd_pdev = of_find_device_by_node(node);
+       if (!pd_pdev)
+               return;
+       pd = platform_get_drvdata(pd_pdev);
+       exynos_add_device_to_domain(pd, dev);
+}

The function "exynos_read_domain_from_dt" does more than reading the domain from dt. It associates a device with a power domain. So should it be renamed accordingly?

Quoted 14 lines
arch/arm/mach-exynos/pm_domains.c +14 -0
+
+static int exynos_pm_notifier_call(struct notifier_block *nb,
+                                   unsigned long event, void *data)
+{
+       struct device *dev = data;
+
+       switch (event) {
+       case BUS_NOTIFY_BIND_DRIVER:
+               if (dev->of_node)
+                       exynos_read_domain_from_dt(dev);
+
+               break;
+
+       case BUS_NOTIFY_UNBOUND_DRIVER:

arch/arm/mach-exynos/pm_domains.c static struct exynos_pm_domain PD = { \ · line 158

Quoted 10 lines
arch/arm/mach-exynos/pm_domains.c +10 -0
+               exynos_remove_device_from_domain(dev);
+
+               break;
+       }
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block platform_nb = {
+       .notifier_call = exynos_pm_notifier_call,
+};

All the functions above are so generic (or can be made generic with minor modifications) that it can be placed outside of mach-exynos. Or better still, reusable for all platforms.

Quoted 32 lines
arch/arm/mach-exynos/pm_domains.c +9 -1
+
 static __init int exynos_pm_dt_parse_domains(void)
 {
+       struct platform_device *pdev;
        struct device_node *np;
 
        for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") {
                struct exynos_pm_domain *pd;
                int on;
 
+               pdev = of_find_device_by_node(np);
+
                pd = kzalloc(sizeof(*pd), GFP_KERNEL);
                if (!pd) {
                        pr_err("%s: failed to allocate memory for domain\n",
@@ -105,10 +182,15 @@ static __init int exynos_pm_dt_parse_domains(void)
                pd->pd.power_on = exynos_pd_power_on;
                pd->pd.of_node = np;
 
+               platform_set_drvdata(pdev, pd);
+
                on = __raw_readl(pd->base + 0x4) & S5P_INT_LOCAL_PWR_EN;
 
                pm_genpd_init(&pd->pd, NULL, !on);
        }
+
+       bus_register_notifier(&platform_bus_type, &platform_nb);
+
        return 0;
 }
 #else
--
Quoted 2 lines

1.7.12

This patch looks so nice. I learned a thing or two from this patch.

#8 lore raw

PATCH 3/3 ARM: EXYNOS: pm_domain: Bind devices to power domains using DT

Hi Thomas,

Quoted 10 lines · On Saturday 08 of September 2012 13:48:24 Thomas Abraham wrote:

Documentation/devicetree/bindings/arm/exynos/power_domain.txt Exynos processors include support for multiple power domains which are used · line 28

Quoted 7 lines
Documentation/devicetree/bindings/arm/exynos/power_domain.txt +7 -0
+Example of the node using power domain:
+
+       node {
+               /* ... */
+               power-domain = <&lcd0>;
+               /* ... */
+       };

Since the value of power-domain property is mostly samsung specific, should this be "samsung,power-domain" ?

Is there a convention of naming that defines such scheme? I have seen platform-specific properties without a prefix indicating the platform.

Quoted 11 lines
Quoted 11 lines
arch/arm/mach-exynos/pm_domains.c +11 -0
+static void exynos_read_domain_from_dt(struct device *dev)
+{
+       struct platform_device *pd_pdev;
+       struct exynos_pm_domain *pd;
+       struct device_node *node;
+
+       node = of_parse_phandle(dev->of_node, "power-domain", 0);
+       if (!node)
+               return;
+       pd_pdev = of_find_device_by_node(node);
+       if (!pd_pdev)
Quoted 8 lines

arch/arm/mach-exynos/pm_domains.c static struct exynos_pm_domain PD = { \ · line 134

Quoted 4 lines
arch/arm/mach-exynos/pm_domains.c +4 -0
+               return;
+       pd = platform_get_drvdata(pd_pdev);
+       exynos_add_device_to_domain(pd, dev);
+}

The function "exynos_read_domain_from_dt" does more than reading the domain from dt. It associates a device with a power domain. So should it be renamed accordingly?

Hmm, do you have an idea for a better name? I'm not good at inventing names.

Quoted 20 lines
Quoted 20 lines
arch/arm/mach-exynos/pm_domains.c +20 -0
+
+static int exynos_pm_notifier_call(struct notifier_block *nb,
+                                   unsigned long event, void *data)
+{
+       struct device *dev = data;
+
+       switch (event) {
+       case BUS_NOTIFY_BIND_DRIVER:
+               if (dev->of_node)
+                       exynos_read_domain_from_dt(dev);
+
+               break;
+
+       case BUS_NOTIFY_UNBOUND_DRIVER:
+               exynos_remove_device_from_domain(dev);
+
+               break;
+       }
+       return NOTIFY_DONE;
+}
Quoted 8 lines

arch/arm/mach-exynos/pm_domains.c static struct exynos_pm_domain PD = { \ · line 158

Quoted 4 lines
arch/arm/mach-exynos/pm_domains.c +4 -0
+
+static struct notifier_block platform_nb = {
+       .notifier_call = exynos_pm_notifier_call,
+};

All the functions above are so generic (or can be made generic with minor modifications) that it can be placed outside of mach-exynos. Or better still, reusable for all platforms.

Right, I have considered this and even CC'ed Rafael with this patchset, but I forgot to mention about it in patch description.

Maybe I should send a separate RFC with a generic variant?

Quoted 6 lines
Quoted 3 lines

--
1.7.12

This patch looks so nice. I learned a thing or two from this patch.

Thanks ;)

--
Best regards,
Tomasz Figa

#9 lore raw

cover ARM: EXYNOS: Power domain DT support extension

In reply to Tomasz Figa

Hi,

Quoted 10 lines · On Thursday 06 of September 2012 11:38:03 Tomasz Figa wrote:

This patch series fixes two issues with existing DT support for Exynos power domains and extends it with the ability of binding devices to domains, basically making it possible to use power domains when using DT.

Tomasz Figa (3):
ARM: EXYNOS: pm_domain: Detect domain state on registration from DT
ARM: EXYNOS: pm_domain: Fix power domain name initialization
ARM: EXYNOS: pm_domain: Bind devices to power domains using DT

Quoted 4 lines
 .../bindings/arm/exynos/power_domain.txt           | 15 +++-
 arch/arm/mach-exynos/pm_domains.c                  | 93

+++++++++++++++++++++- 2 files changed, 100 insertions(+), 8 deletions(-)

Any further comments for this series? Could we merge it for 3.7?

Best regards,

Signature · 2 lines
Tomasz Figa
Samsung Poland R&D Center