brcm2708: update to latest patches from RPi Foundation
[openwrt/staging/dedeckeh.git] / target / linux / brcm2708 / patches-4.19 / 950-0485-soc-bcm-bcm2835-pm-Fix-error-paths-of-initialization.patch
diff --git a/target/linux/brcm2708/patches-4.19/950-0485-soc-bcm-bcm2835-pm-Fix-error-paths-of-initialization.patch b/target/linux/brcm2708/patches-4.19/950-0485-soc-bcm-bcm2835-pm-Fix-error-paths-of-initialization.patch
new file mode 100644 (file)
index 0000000..0f3ea9a
--- /dev/null
@@ -0,0 +1,103 @@
+From 8d9f3526529d857376c661c21820a0049c2e62de Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+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 <eric@anholt.net>
+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)