]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/commitdiff
bus: ti-sysc: Probe for l4_wkup and l4_cfg interconnect devices first
authorTony Lindgren <tony@atomide.com>
Mon, 8 Mar 2021 09:35:07 +0000 (11:35 +0200)
committerStefan Bader <stefan.bader@canonical.com>
Wed, 19 May 2021 08:59:35 +0000 (10:59 +0200)
BugLink: https://bugs.launchpad.net/bugs/1928825
[ Upstream commit 4700a00755fb5a4bb5109128297d6fd2d1272ee6 ]

We want to probe l4_wkup and l4_cfg interconnect devices first to avoid
issues with missing resources. Otherwise we attempt to probe l4_per
devices first causing pointless deferred probe and also annoyingh
renumbering of the MMC devices for example.

Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
drivers/bus/ti-sysc.c

index f9ff6d433dfe1d8656cdaf4f09fd01fbefc083c1..d59e1ca9990b65ee09bacf98efa1aa202d8a43a4 100644 (file)
@@ -602,6 +602,51 @@ static int sysc_parse_and_check_child_range(struct sysc *ddata)
        return 0;
 }
 
+/* Interconnect instances to probe before l4_per instances */
+static struct resource early_bus_ranges[] = {
+       /* am3/4 l4_wkup */
+       { .start = 0x44c00000, .end = 0x44c00000 + 0x300000, },
+       /* omap4/5 and dra7 l4_cfg */
+       { .start = 0x4a000000, .end = 0x4a000000 + 0x300000, },
+       /* omap4 l4_wkup */
+       { .start = 0x4a300000, .end = 0x4a300000 + 0x30000,  },
+       /* omap5 and dra7 l4_wkup without dra7 dcan segment */
+       { .start = 0x4ae00000, .end = 0x4ae00000 + 0x30000,  },
+};
+
+static atomic_t sysc_defer = ATOMIC_INIT(10);
+
+/**
+ * sysc_defer_non_critical - defer non_critical interconnect probing
+ * @ddata: device driver data
+ *
+ * We want to probe l4_cfg and l4_wkup interconnect instances before any
+ * l4_per instances as l4_per instances depend on resources on l4_cfg and
+ * l4_wkup interconnects.
+ */
+static int sysc_defer_non_critical(struct sysc *ddata)
+{
+       struct resource *res;
+       int i;
+
+       if (!atomic_read(&sysc_defer))
+               return 0;
+
+       for (i = 0; i < ARRAY_SIZE(early_bus_ranges); i++) {
+               res = &early_bus_ranges[i];
+               if (ddata->module_pa >= res->start &&
+                   ddata->module_pa <= res->end) {
+                       atomic_set(&sysc_defer, 0);
+
+                       return 0;
+               }
+       }
+
+       atomic_dec_if_positive(&sysc_defer);
+
+       return -EPROBE_DEFER;
+}
+
 static struct device_node *stdout_path;
 
 static void sysc_init_stdout_path(struct sysc *ddata)
@@ -826,6 +871,10 @@ static int sysc_map_and_check_registers(struct sysc *ddata)
        if (error)
                return error;
 
+       error = sysc_defer_non_critical(ddata);
+       if (error)
+               return error;
+
        sysc_check_children(ddata);
 
        error = sysc_parse_registers(ddata);