From 8d9f3526529d857376c661c21820a0049c2e62de Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sat, 12 Jan 2019 08:07:43 -0800 Subject: [PATCH] soc: bcm: bcm2835-pm: Fix error paths of initialization. The clock driver may probe after ours and so we need to pass the -EPROBE_DEFER out. Fix the other error path while we're here. v2: Use dom->name instead of dom->gov as the flag for initialized domains, since we aren't setting up a governor. Make sure to clear ->clk when no clk is present in the DT. Signed-off-by: Eric Anholt Fixes: 670c672608a1 ("soc: bcm: bcm2835-pm: Add support for power domains under a new binding.") --- drivers/soc/bcm/bcm2835-power.c | 35 ++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) --- a/drivers/soc/bcm/bcm2835-power.c +++ b/drivers/soc/bcm/bcm2835-power.c @@ -485,7 +485,7 @@ static int bcm2835_power_pd_power_off(st } } -static void +static int bcm2835_init_power_domain(struct bcm2835_power *power, int pd_xlate_index, const char *name) { @@ -493,6 +493,17 @@ bcm2835_init_power_domain(struct bcm2835 struct bcm2835_power_domain *dom = &power->domains[pd_xlate_index]; dom->clk = devm_clk_get(dev->parent, name); + if (IS_ERR(dom->clk)) { + int ret = PTR_ERR(dom->clk); + + if (ret == -EPROBE_DEFER) + return ret; + + /* Some domains don't have a clk, so make sure that we + * don't deref an error pointer later. + */ + dom->clk = NULL; + } dom->base.name = name; dom->base.power_on = bcm2835_power_pd_power_on; @@ -505,6 +516,8 @@ bcm2835_init_power_domain(struct bcm2835 pm_genpd_init(&dom->base, NULL, true); power->pd_xlate.domains[pd_xlate_index] = &dom->base; + + return 0; } /** bcm2835_reset_reset - Resets a block that has a reset line in the @@ -602,7 +615,7 @@ static int bcm2835_power_probe(struct pl { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM0 }, { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM1 }, }; - int ret, i; + int ret = 0, i; u32 id; power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL); @@ -629,8 +642,11 @@ static int bcm2835_power_probe(struct pl power->pd_xlate.num_domains = ARRAY_SIZE(power_domain_names); - for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) - bcm2835_init_power_domain(power, i, power_domain_names[i]); + for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) { + ret = bcm2835_init_power_domain(power, i, power_domain_names[i]); + if (ret) + goto fail; + } for (i = 0; i < ARRAY_SIZE(domain_deps); i++) { pm_genpd_add_subdomain(&power->domains[domain_deps[i].parent].base, @@ -644,12 +660,21 @@ static int bcm2835_power_probe(struct pl ret = devm_reset_controller_register(dev, &power->reset); if (ret) - return ret; + goto fail; of_genpd_add_provider_onecell(dev->parent->of_node, &power->pd_xlate); dev_info(dev, "Broadcom BCM2835 power domains driver"); return 0; + +fail: + for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) { + struct generic_pm_domain *dom = &power->domains[i].base; + + if (dom->name) + pm_genpd_remove(dom); + } + return ret; } static int bcm2835_power_remove(struct platform_device *pdev)