diff options
Diffstat (limited to 'drivers/cpufreq/s5pv210-cpufreq.c')
-rw-r--r-- | drivers/cpufreq/s5pv210-cpufreq.c | 67 |
1 files changed, 48 insertions, 19 deletions
diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c index dbecd7667db2..5b4289460bc9 100644 --- a/drivers/cpufreq/s5pv210-cpufreq.c +++ b/drivers/cpufreq/s5pv210-cpufreq.c @@ -584,7 +584,7 @@ static struct notifier_block s5pv210_cpufreq_reboot_notifier = { static int s5pv210_cpufreq_probe(struct platform_device *pdev) { struct device_node *np; - int id; + int id, result = 0; /* * HACK: This is a temporary workaround to get access to clock @@ -594,18 +594,39 @@ static int s5pv210_cpufreq_probe(struct platform_device *pdev) * this whole driver as soon as S5PV210 gets migrated to use * cpufreq-dt driver. */ + arm_regulator = regulator_get(NULL, "vddarm"); + if (IS_ERR(arm_regulator)) { + if (PTR_ERR(arm_regulator) == -EPROBE_DEFER) + pr_debug("vddarm regulator not ready, defer\n"); + else + pr_err("failed to get regulator vddarm\n"); + return PTR_ERR(arm_regulator); + } + + int_regulator = regulator_get(NULL, "vddint"); + if (IS_ERR(int_regulator)) { + if (PTR_ERR(int_regulator) == -EPROBE_DEFER) + pr_debug("vddint regulator not ready, defer\n"); + else + pr_err("failed to get regulator vddint\n"); + result = PTR_ERR(int_regulator); + goto err_int_regulator; + } + np = of_find_compatible_node(NULL, NULL, "samsung,s5pv210-clock"); if (!np) { pr_err("%s: failed to find clock controller DT node\n", __func__); - return -ENODEV; + result = -ENODEV; + goto err_clock; } clk_base = of_iomap(np, 0); of_node_put(np); if (!clk_base) { pr_err("%s: failed to map clock registers\n", __func__); - return -EFAULT; + result = -EFAULT; + goto err_clock; } for_each_compatible_node(np, NULL, "samsung,s5pv210-dmc") { @@ -614,7 +635,8 @@ static int s5pv210_cpufreq_probe(struct platform_device *pdev) pr_err("%s: failed to get alias of dmc node '%pOFn'\n", __func__, np); of_node_put(np); - return id; + result = id; + goto err_clk_base; } dmc_base[id] = of_iomap(np, 0); @@ -622,33 +644,40 @@ static int s5pv210_cpufreq_probe(struct platform_device *pdev) pr_err("%s: failed to map dmc%d registers\n", __func__, id); of_node_put(np); - return -EFAULT; + result = -EFAULT; + goto err_dmc; } } for (id = 0; id < ARRAY_SIZE(dmc_base); ++id) { if (!dmc_base[id]) { pr_err("%s: failed to find dmc%d node\n", __func__, id); - return -ENODEV; + result = -ENODEV; + goto err_dmc; } } - arm_regulator = regulator_get(NULL, "vddarm"); - if (IS_ERR(arm_regulator)) { - pr_err("failed to get regulator vddarm\n"); - return PTR_ERR(arm_regulator); - } - - int_regulator = regulator_get(NULL, "vddint"); - if (IS_ERR(int_regulator)) { - pr_err("failed to get regulator vddint\n"); - regulator_put(arm_regulator); - return PTR_ERR(int_regulator); - } - register_reboot_notifier(&s5pv210_cpufreq_reboot_notifier); return cpufreq_register_driver(&s5pv210_driver); + +err_dmc: + for (id = 0; id < ARRAY_SIZE(dmc_base); ++id) + if (dmc_base[id]) { + iounmap(dmc_base[id]); + dmc_base[id] = NULL; + } + +err_clk_base: + iounmap(clk_base); + +err_clock: + regulator_put(int_regulator); + +err_int_regulator: + regulator_put(arm_regulator); + + return result; } static struct platform_driver s5pv210_cpufreq_platdrv = { |