From 8ab08c0c4c39f36d3bf89e03a4bc3e6898e1563c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 4 Aug 2012 10:28:33 +0000 Subject: ARM: exynos: exynos_pm_add_dev_to_genpd may be unused exynos_pm_add_dev_to_genpd is used if one or more out of a large number of Kconfig symbols are enabled. However the new exynos_defconfig selects none of those, so the function becomes unused. Marking it so lets the compiler automatically discard it. Without this patch, building exynos_defconfig results in: arch/arm/mach-exynos/pm_domains.c:118:123: warning: 'exynos_pm_add_dev_to_genpd' defined but not used [-Wunused-function] Signed-off-by: Arnd Bergmann Acked-by: Thomas Abraham Acked-by: Kukjin Kim Cc: Rafael J. Wysocki --- arch/arm/mach-exynos/pm_domains.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/mach-exynos/pm_domains.c') diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c index 373c3c00d24..c0bc83a7663 100644 --- a/arch/arm/mach-exynos/pm_domains.c +++ b/arch/arm/mach-exynos/pm_domains.c @@ -115,7 +115,7 @@ static __init int exynos_pm_dt_parse_domains(void) } #endif /* CONFIG_OF */ -static __init void exynos_pm_add_dev_to_genpd(struct platform_device *pdev, +static __init __maybe_unused void exynos_pm_add_dev_to_genpd(struct platform_device *pdev, struct exynos_pm_domain *pd) { if (pdev->dev.bus) { -- cgit v1.2.3 From 2ed5f236716cbd20f51bdc87ddd91bad259c81a6 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Thu, 22 Nov 2012 00:21:08 +0900 Subject: ARM: EXYNOS: Detect power 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. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/pm_domains.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'arch/arm/mach-exynos/pm_domains.c') diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c index c0bc83a7663..d1abc1a94ec 100644 --- a/arch/arm/mach-exynos/pm_domains.c +++ b/arch/arm/mach-exynos/pm_domains.c @@ -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; } -- cgit v1.2.3 From 7add0ec0fef19d5b7a3ae38c5deb80819a065a17 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Thu, 22 Nov 2012 00:21:12 +0900 Subject: ARM: EXYNOS: Fix power domain name initialization This patch adds initialization of name field in generic power domain struct. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/pm_domains.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/arm/mach-exynos/pm_domains.c') diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c index d1abc1a94ec..5b7ce7ea6c6 100644 --- a/arch/arm/mach-exynos/pm_domains.c +++ b/arch/arm/mach-exynos/pm_domains.c @@ -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; -- cgit v1.2.3 From 8a65d2365df0635da13ae30c01e217c477c9ce3e Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Thu, 22 Nov 2012 00:21:17 +0900 Subject: ARM: EXYNOS: Bind devices to power domains using DT 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. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/pm_domains.c | 82 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) (limited to 'arch/arm/mach-exynos/pm_domains.c') diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c index 5b7ce7ea6c6..9f1351de52f 100644 --- a/arch/arm/mach-exynos/pm_domains.c +++ b/arch/arm/mach-exynos/pm_domains.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include @@ -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; + + node = of_parse_phandle(dev->of_node, "samsung,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); +} + +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; +} + +static struct notifier_block platform_nb = { + .notifier_call = exynos_pm_notifier_call, +}; + 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 -- cgit v1.2.3