aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2018-09-28 11:57:27 -0400
committerArnd Bergmann <arnd@arndb.de>2018-09-28 11:57:58 -0400
commit3a60f1182bce850c2f12343a78e157d40af7b1a0 (patch)
tree37c535121ac6c994cded769a35b62405b63e8ba0
parent8e2649d00a8a7b292bd6410cbf976a3d957faa60 (diff)
parent6e77137927639fad66e17c06b50fd319d6b59833 (diff)
Merge tag 'omap-for-v4.20/soc-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/soc
SoC changes for omap variants These changes improve support for clkctrl clocks to deal with split memory ranges for clkctrl providers. And to use %pOFn instead of device_node.name. * tag 'omap-for-v4.20/soc-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: ARM: OMAP2+: Convert to using %pOFn instead of device_node.name ARM: OMAP2+: hwmod_core: improve the support for clkctrl clocks Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c88
1 files changed, 51 insertions, 37 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index cd65ea4e9c54..56a1fe90d394 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -188,16 +188,16 @@
188 188
189/** 189/**
190 * struct clkctrl_provider - clkctrl provider mapping data 190 * struct clkctrl_provider - clkctrl provider mapping data
191 * @addr: base address for the provider 191 * @num_addrs: number of base address ranges for the provider
192 * @size: size of the provider address space 192 * @addr: base address(es) for the provider
193 * @offset: offset of the provider from PRCM instance base 193 * @size: size(s) of the provider address space(s)
194 * @node: device node associated with the provider 194 * @node: device node associated with the provider
195 * @link: list link 195 * @link: list link
196 */ 196 */
197struct clkctrl_provider { 197struct clkctrl_provider {
198 u32 addr; 198 int num_addrs;
199 u32 size; 199 u32 *addr;
200 u16 offset; 200 u32 *size;
201 struct device_node *node; 201 struct device_node *node;
202 struct list_head link; 202 struct list_head link;
203}; 203};
@@ -724,23 +724,34 @@ static int __init _setup_clkctrl_provider(struct device_node *np)
724 const __be32 *addrp; 724 const __be32 *addrp;
725 struct clkctrl_provider *provider; 725 struct clkctrl_provider *provider;
726 u64 size; 726 u64 size;
727 int i;
727 728
728 provider = memblock_virt_alloc(sizeof(*provider), 0); 729 provider = memblock_virt_alloc(sizeof(*provider), 0);
729 if (!provider) 730 if (!provider)
730 return -ENOMEM; 731 return -ENOMEM;
731 732
732 addrp = of_get_address(np, 0, &size, NULL);
733 provider->addr = (u32)of_translate_address(np, addrp);
734 addrp = of_get_address(np->parent, 0, NULL, NULL);
735 provider->offset = provider->addr -
736 (u32)of_translate_address(np->parent, addrp);
737 provider->addr &= ~0xff;
738 provider->size = size | 0xff;
739 provider->node = np; 733 provider->node = np;
740 734
741 pr_debug("%s: %s: %x...%x [+%x]\n", __func__, np->parent->name, 735 provider->num_addrs =
742 provider->addr, provider->addr + provider->size, 736 of_property_count_elems_of_size(np, "reg", sizeof(u32)) / 2;
743 provider->offset); 737
738 provider->addr =
739 memblock_virt_alloc(sizeof(void *) * provider->num_addrs, 0);
740 if (!provider->addr)
741 return -ENOMEM;
742
743 provider->size =
744 memblock_virt_alloc(sizeof(u32) * provider->num_addrs, 0);
745 if (!provider->size)
746 return -ENOMEM;
747
748 for (i = 0; i < provider->num_addrs; i++) {
749 addrp = of_get_address(np, i, &size, NULL);
750 provider->addr[i] = (u32)of_translate_address(np, addrp);
751 provider->size[i] = size;
752 pr_debug("%s: %pOF: %x...%x\n", __func__, np, provider->addr[i],
753 provider->addr[i] + provider->size[i]);
754 }
744 755
745 list_add(&provider->link, &clkctrl_providers); 756 list_add(&provider->link, &clkctrl_providers);
746 757
@@ -787,23 +798,26 @@ static struct clk *_lookup_clkctrl_clk(struct omap_hwmod *oh)
787 pr_debug("%s: %s: addr=%x\n", __func__, oh->name, addr); 798 pr_debug("%s: %s: addr=%x\n", __func__, oh->name, addr);
788 799
789 list_for_each_entry(provider, &clkctrl_providers, link) { 800 list_for_each_entry(provider, &clkctrl_providers, link) {
790 if (provider->addr <= addr && 801 int i;
791 provider->addr + provider->size >= addr) {
792 struct of_phandle_args clkspec;
793 802
794 clkspec.np = provider->node; 803 for (i = 0; i < provider->num_addrs; i++) {
795 clkspec.args_count = 2; 804 if (provider->addr[i] <= addr &&
796 clkspec.args[0] = addr - provider->addr - 805 provider->addr[i] + provider->size[i] > addr) {
797 provider->offset; 806 struct of_phandle_args clkspec;
798 clkspec.args[1] = 0;
799 807
800 clk = of_clk_get_from_provider(&clkspec); 808 clkspec.np = provider->node;
809 clkspec.args_count = 2;
810 clkspec.args[0] = addr - provider->addr[0];
811 clkspec.args[1] = 0;
801 812
802 pr_debug("%s: %s got %p (offset=%x, provider=%s)\n", 813 clk = of_clk_get_from_provider(&clkspec);
803 __func__, oh->name, clk, clkspec.args[0],
804 provider->node->parent->name);
805 814
806 return clk; 815 pr_debug("%s: %s got %p (offset=%x, provider=%pOF)\n",
816 __func__, oh->name, clk,
817 clkspec.args[0], provider->node);
818
819 return clk;
820 }
807 } 821 }
808 } 822 }
809 823
@@ -2107,8 +2121,8 @@ static int of_dev_find_hwmod(struct device_node *np,
2107 if (res) 2121 if (res)
2108 continue; 2122 continue;
2109 if (!strcmp(p, oh->name)) { 2123 if (!strcmp(p, oh->name)) {
2110 pr_debug("omap_hwmod: dt %s[%i] uses hwmod %s\n", 2124 pr_debug("omap_hwmod: dt %pOFn[%i] uses hwmod %s\n",
2111 np->name, i, oh->name); 2125 np, i, oh->name);
2112 return i; 2126 return i;
2113 } 2127 }
2114 } 2128 }
@@ -2241,8 +2255,8 @@ int omap_hwmod_parse_module_range(struct omap_hwmod *oh,
2241 return -ENOENT; 2255 return -ENOENT;
2242 2256
2243 if (nr_addr != 1 || nr_size != 1) { 2257 if (nr_addr != 1 || nr_size != 1) {
2244 pr_err("%s: invalid range for %s->%s\n", __func__, 2258 pr_err("%s: invalid range for %s->%pOFn\n", __func__,
2245 oh->name, np->name); 2259 oh->name, np);
2246 return -EINVAL; 2260 return -EINVAL;
2247 } 2261 }
2248 2262
@@ -2250,8 +2264,8 @@ int omap_hwmod_parse_module_range(struct omap_hwmod *oh,
2250 base = of_translate_address(np, ranges++); 2264 base = of_translate_address(np, ranges++);
2251 size = be32_to_cpup(ranges); 2265 size = be32_to_cpup(ranges);
2252 2266
2253 pr_debug("omap_hwmod: %s %s at 0x%llx size 0x%llx\n", 2267 pr_debug("omap_hwmod: %s %pOFn at 0x%llx size 0x%llx\n",
2254 oh ? oh->name : "", np->name, base, size); 2268 oh->name, np, base, size);
2255 2269
2256 if (oh && oh->mpu_rt_idx) { 2270 if (oh && oh->mpu_rt_idx) {
2257 omap_hwmod_fix_mpu_rt_idx(oh, np, res); 2271 omap_hwmod_fix_mpu_rt_idx(oh, np, res);
@@ -2359,8 +2373,8 @@ static int __init _init(struct omap_hwmod *oh, void *data)
2359 if (r) 2373 if (r)
2360 pr_debug("omap_hwmod: %s missing dt data\n", oh->name); 2374 pr_debug("omap_hwmod: %s missing dt data\n", oh->name);
2361 else if (np && index) 2375 else if (np && index)
2362 pr_warn("omap_hwmod: %s using broken dt data from %s\n", 2376 pr_warn("omap_hwmod: %s using broken dt data from %pOFn\n",
2363 oh->name, np->name); 2377 oh->name, np);
2364 2378
2365 r = _init_mpu_rt_base(oh, NULL, index, np); 2379 r = _init_mpu_rt_base(oh, NULL, index, np);
2366 if (r < 0) { 2380 if (r < 0) {