@@ -6,8 +6,8 @@ to gate power to one or more peripherals on the processor.
Required Properties:
- 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.
+- pd-offset: this gives the offset of PM power domain register from
+ the PMU base address.
- #power-domain-cells: number of cells in power domain specifier;
must be 0.
@@ -30,13 +30,13 @@ Example:
lcd0: power-domain-lcd0 {
compatible = "samsung,exynos4210-pd";
- reg = <0x10023C00 0x10>;
+ pd-offset = <0x3C00>;
#power-domain-cells = <0>;
};
mfc_pd: power-domain@10044060 {
compatible = "samsung,exynos4210-pd";
- reg = <0x10044060 0x20>;
+ pd-offset = <0x4060>;
clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MOUT_SW_ACLK333>,
<&clock CLK_MOUT_USER_ACLK333>;
clock-names = "oscclk", "pclk0", "clk0";
@@ -22,6 +22,7 @@
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/sched.h>
+#include <linux/mfd/samsung/exynos-pmu.h>
#define INT_LOCAL_PWR_EN 0x7
#define MAX_CLK_PER_DOMAIN 4
@@ -105,33 +106,41 @@ static int exynos_pd_power_off(struct generic_pm_domain *domain)
return exynos_pd_power(domain, false);
}
-static __init int exynos4_pm_init_power_domain(void)
+static int exynos_power_domain_probe(struct platform_device *pdev)
{
- struct platform_device *pdev;
struct device_node *np;
+ struct pmu_dev_client_data *pdata = NULL;
+ void __iomem *pmu_base_addr;
+ unsigned int offset;
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata) {
+ dev_err(&pdev->dev, "No platform data passed\n");
+ return -EINVAL;
+ }
+
+ pmu_base_addr = pdata->mem_base_addr;
for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") {
struct exynos_pm_domain *pd;
int on, i;
- struct device *dev;
- pdev = of_find_device_by_node(np);
- dev = &pdev->dev;
-
- pd = kzalloc(sizeof(*pd), GFP_KERNEL);
- if (!pd) {
- pr_err("%s: failed to allocate memory for domain\n",
- __func__);
+ pd = devm_kzalloc(&pdev->dev, sizeof(*pd), GFP_KERNEL);
+ if (!pd)
return -ENOMEM;
- }
pd->pd.name = kstrdup(np->name, GFP_KERNEL);
pd->name = pd->pd.name;
- pd->base = of_iomap(np, 0);
+ if (of_property_read_u32(np, "pd-offset", &offset)) {
+ pr_err("%s: failed to find offset for power domain\n",
+ __func__);
+ return -EINVAL;
+ }
+ pd->base = pmu_base_addr + offset;
pd->pd.power_off = exynos_pd_power_off;
pd->pd.power_on = exynos_pd_power_on;
- pd->oscclk = clk_get(dev, "oscclk");
+ pd->oscclk = of_clk_get_by_name(np, "oscclk");
if (IS_ERR(pd->oscclk))
goto no_clk;
@@ -139,11 +148,11 @@ static __init int exynos4_pm_init_power_domain(void)
char clk_name[8];
snprintf(clk_name, sizeof(clk_name), "clk%d", i);
- pd->clk[i] = clk_get(dev, clk_name);
+ pd->clk[i] = of_clk_get_by_name(np, clk_name);
if (IS_ERR(pd->clk[i]))
break;
snprintf(clk_name, sizeof(clk_name), "pclk%d", i);
- pd->pclk[i] = clk_get(dev, clk_name);
+ pd->pclk[i] = of_clk_get_by_name(np, clk_name);
if (IS_ERR(pd->pclk[i])) {
clk_put(pd->clk[i]);
pd->clk[i] = ERR_PTR(-EINVAL);
@@ -163,4 +172,22 @@ no_clk:
return 0;
}
-arch_initcall(exynos4_pm_init_power_domain);
+
+static const struct platform_device_id exynos_power_domain_id[] = {
+ { "exynos-pmu-domain"},
+ { },
+};
+
+static struct platform_driver exynos_power_domain_driver = {
+ .driver = {
+ .name = "exynos-pd",
+ },
+ .probe = exynos_power_domain_probe,
+ .id_table = exynos_power_domain_id,
+};
+
+static int __init exynos_power_domain_init(void)
+{
+ return platform_driver_register(&exynos_power_domain_driver);
+}
+postcore_initcall(exynos_power_domain_init);