/**
  * struct clkctrl_provider - clkctrl provider mapping data
- * @addr: base address for the provider
- * @size: size of the provider address space
- * @offset: offset of the provider from PRCM instance base
+ * @num_addrs: number of base address ranges for the provider
+ * @addr: base address(es) for the provider
+ * @size: size(s) of the provider address space(s)
  * @node: device node associated with the provider
  * @link: list link
  */
 struct clkctrl_provider {
-       u32                     addr;
-       u32                     size;
-       u16                     offset;
+       int                     num_addrs;
+       u32                     *addr;
+       u32                     *size;
        struct device_node      *node;
        struct list_head        link;
 };
        const __be32 *addrp;
        struct clkctrl_provider *provider;
        u64 size;
+       int i;
 
        provider = memblock_virt_alloc(sizeof(*provider), 0);
        if (!provider)
                return -ENOMEM;
 
-       addrp = of_get_address(np, 0, &size, NULL);
-       provider->addr = (u32)of_translate_address(np, addrp);
-       addrp = of_get_address(np->parent, 0, NULL, NULL);
-       provider->offset = provider->addr -
-                          (u32)of_translate_address(np->parent, addrp);
-       provider->addr &= ~0xff;
-       provider->size = size | 0xff;
        provider->node = np;
 
-       pr_debug("%s: %s: %x...%x [+%x]\n", __func__, np->parent->name,
-                provider->addr, provider->addr + provider->size,
-                provider->offset);
+       provider->num_addrs =
+               of_property_count_elems_of_size(np, "reg", sizeof(u32)) / 2;
+
+       provider->addr =
+               memblock_virt_alloc(sizeof(void *) * provider->num_addrs, 0);
+       if (!provider->addr)
+               return -ENOMEM;
+
+       provider->size =
+               memblock_virt_alloc(sizeof(u32) * provider->num_addrs, 0);
+       if (!provider->size)
+               return -ENOMEM;
+
+       for (i = 0; i < provider->num_addrs; i++) {
+               addrp = of_get_address(np, i, &size, NULL);
+               provider->addr[i] = (u32)of_translate_address(np, addrp);
+               provider->size[i] = size;
+               pr_debug("%s: %pOF: %x...%x\n", __func__, np, provider->addr[i],
+                        provider->addr[i] + provider->size[i]);
+       }
 
        list_add(&provider->link, &clkctrl_providers);
 
        pr_debug("%s: %s: addr=%x\n", __func__, oh->name, addr);
 
        list_for_each_entry(provider, &clkctrl_providers, link) {
-               if (provider->addr <= addr &&
-                   provider->addr + provider->size >= addr) {
-                       struct of_phandle_args clkspec;
+               int i;
 
-                       clkspec.np = provider->node;
-                       clkspec.args_count = 2;
-                       clkspec.args[0] = addr - provider->addr -
-                                         provider->offset;
-                       clkspec.args[1] = 0;
+               for (i = 0; i < provider->num_addrs; i++) {
+                       if (provider->addr[i] <= addr &&
+                           provider->addr[i] + provider->size[i] > addr) {
+                               struct of_phandle_args clkspec;
 
-                       clk = of_clk_get_from_provider(&clkspec);
+                               clkspec.np = provider->node;
+                               clkspec.args_count = 2;
+                               clkspec.args[0] = addr - provider->addr[0];
+                               clkspec.args[1] = 0;
 
-                       pr_debug("%s: %s got %p (offset=%x, provider=%s)\n",
-                                __func__, oh->name, clk, clkspec.args[0],
-                                provider->node->parent->name);
+                               clk = of_clk_get_from_provider(&clkspec);
 
-                       return clk;
+                               pr_debug("%s: %s got %p (offset=%x, provider=%pOF)\n",
+                                        __func__, oh->name, clk,
+                                        clkspec.args[0], provider->node);
+
+                               return clk;
+                       }
                }
        }