diff options
author | Olof Johansson <olof@lixom.net> | 2012-11-26 00:06:23 -0800 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2012-11-26 00:06:23 -0800 |
commit | d408c5dcc524dfc8e687c443719a3d6be86e2ea0 (patch) | |
tree | 0fee3f9936e9950d3b0db7d4f466b2b89718a2bb /arch/arm/mach-exynos | |
parent | 8d2282a77bf0977e7033d8ea5970f369bc28f0f0 (diff) | |
parent | d80162eccd56c40228e1232de8a203e8553b20a4 (diff) | |
download | op-kernel-dev-d408c5dcc524dfc8e687c443719a3d6be86e2ea0.zip op-kernel-dev-d408c5dcc524dfc8e687c443719a3d6be86e2ea0.tar.gz |
Merge branch 'next/dt-samsung-2' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung into next/dt
From Kukjin Kim:
Here is second Samsung DT stuff for v3.8.
This is including power domain DT support for exynos and Google ARM
Chromebook, Snow board and exynos4210-origen updates.
* 'next/dt-samsung-2' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung:
ARM: dts: Use drive strength 3 for SD pins for exynos4
ARM: dts: Set up power domains for exynos4
ARM: EXYNOS: Bind devices to power domains using DT
ARM: EXYNOS: Fix power domain name initialization
ARM: EXYNOS: Detect power domain state on registration from DT
ARM: dts: Add vmmc fixed voltage regulator for exynos4210-origen
ARM: dts: Update sdhci nodes for current bindings for exynos4210-origen
ARM: dts: Update for pinctrl-samsung driver for exynos4210-origen
ARM: dts: Split memory sections for exynos4210-origen
ARM: EXYNOS: add all i2c busses to auxdata for DT
ARM: dts: Add aliases for i2c controller for exynos4
ARM: dts: Add board dts file for Snow board (ARM Chromebook)
ARM: dts: Move the dwmmc aliases from smdk5250 dts to exynos
Add/add conflicts resolved in arch/arm/boot/dts/exynos5250-smdk5250.dts
and arch/arm/mach-exynos/mach-exynos5-dt.c.
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch/arm/mach-exynos')
-rw-r--r-- | arch/arm/mach-exynos/mach-exynos5-dt.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-exynos/pm_domains.c | 93 |
2 files changed, 99 insertions, 4 deletions
diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c index 28146f2..25f464c 100644 --- a/arch/arm/mach-exynos/mach-exynos5-dt.c +++ b/arch/arm/mach-exynos/mach-exynos5-dt.c @@ -52,6 +52,16 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = { "s3c2440-i2c.1", NULL), OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(2), "s3c2440-i2c.2", NULL), + OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(3), + "s3c2440-i2c.3", NULL), + OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(4), + "s3c2440-i2c.4", NULL), + OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(5), + "s3c2440-i2c.5", NULL), + OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(6), + "s3c2440-i2c.6", NULL), + OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(7), + "s3c2440-i2c.7", NULL), OF_DEV_AUXDATA("samsung,s3c2440-hdmiphy-i2c", EXYNOS5_PA_IIC(8), "s3c2440-hdmiphy-i2c", NULL), OF_DEV_AUXDATA("samsung,exynos5250-dw-mshc", EXYNOS5_PA_DWMCI0, diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c index c0bc83a..9f1351d 100644 --- a/arch/arm/mach-exynos/pm_domains.c +++ b/arch/arm/mach-exynos/pm_domains.c @@ -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,12 +85,88 @@ 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) { @@ -97,15 +175,22 @@ 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->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; pd->pd.of_node = np; - pm_genpd_init(&pd->pd, NULL, false); + + 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 |