Skip to content

Commit 6c72b35

Browse files
committed
ARM: OMAP2+: Parse module IO range from dts for legacy "ti,hwmods" support
When removing legacy platform data for IO ranges for the hwmod interconnect code, we still need to support the "ti,hwmods" property. And as we're going to use a generic sysc device driver to handle the interconnect target instances, we can parse the information needed for legacy "ti,hwmods" IO range from the dts. It's always the first range the interconnect target module provides. Note that we want to parse the range instead of the first child device IO regs as the child device may not always be defined. The child IP device node may not exist in cases where there is no driver binding for the device, or when the child IP block may not even be functional for some SoC revisions. But the IO range of the interconnect target module is always known. Cc: "Benoît Cousson" <[email protected]> Cc: Lokesh Vutla <[email protected]> Cc: Paul Walmsley <[email protected]> Cc: Tero Kristo <[email protected]> Signed-off-by: Tony Lindgren <[email protected]>
1 parent f09de60 commit 6c72b35

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

arch/arm/mach-omap2/omap_hwmod.c

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2393,6 +2393,75 @@ static int of_dev_hwmod_lookup(struct device_node *np,
23932393
return -ENODEV;
23942394
}
23952395

2396+
/**
2397+
* omap_hwmod_parse_module_range - map module IO range from device tree
2398+
* @oh: struct omap_hwmod *
2399+
* @np: struct device_node *
2400+
*
2401+
* Parse the device tree range an interconnect target module provides
2402+
* for it's child device IP blocks. This way we can support the old
2403+
* "ti,hwmods" property with just dts data without a need for platform
2404+
* data for IO resources. And we don't need all the child IP device
2405+
* nodes available in the dts.
2406+
*/
2407+
int omap_hwmod_parse_module_range(struct omap_hwmod *oh,
2408+
struct device_node *np,
2409+
struct resource *res)
2410+
{
2411+
struct property *prop;
2412+
const __be32 *ranges;
2413+
const char *name;
2414+
u32 nr_addr, nr_size;
2415+
u64 base, size;
2416+
int len, error;
2417+
2418+
if (!res)
2419+
return -EINVAL;
2420+
2421+
ranges = of_get_property(np, "ranges", &len);
2422+
if (!ranges)
2423+
return -ENOENT;
2424+
2425+
len /= sizeof(*ranges);
2426+
2427+
if (len < 3)
2428+
return -EINVAL;
2429+
2430+
of_property_for_each_string(np, "compatible", prop, name)
2431+
if (!strncmp("ti,sysc-", name, 8))
2432+
break;
2433+
2434+
if (!name)
2435+
return -ENOENT;
2436+
2437+
error = of_property_read_u32(np, "#address-cells", &nr_addr);
2438+
if (error)
2439+
return -ENOENT;
2440+
2441+
error = of_property_read_u32(np, "#size-cells", &nr_size);
2442+
if (error)
2443+
return -ENOENT;
2444+
2445+
if (nr_addr != 1 || nr_size != 1) {
2446+
pr_err("%s: invalid range for %s->%s\n", __func__,
2447+
oh->name, np->name);
2448+
return -EINVAL;
2449+
}
2450+
2451+
ranges++;
2452+
base = of_translate_address(np, ranges++);
2453+
size = be32_to_cpup(ranges);
2454+
2455+
pr_debug("omap_hwmod: %s %s at 0x%llx size 0x%llx\n",
2456+
oh->name, np->name, base, size);
2457+
2458+
res->start = base;
2459+
res->end = base + size - 1;
2460+
res->flags = IORESOURCE_MEM;
2461+
2462+
return 0;
2463+
}
2464+
23962465
/**
23972466
* _init_mpu_rt_base - populate the virtual address for a hwmod
23982467
* @oh: struct omap_hwmod * to locate the virtual address
@@ -2415,6 +2484,8 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data,
24152484
{
24162485
struct omap_hwmod_addr_space *mem;
24172486
void __iomem *va_start = NULL;
2487+
struct resource res;
2488+
int error;
24182489

24192490
if (!oh)
24202491
return -EINVAL;
@@ -2440,7 +2511,14 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data,
24402511
return -ENXIO;
24412512
}
24422513

2443-
va_start = of_iomap(np, index + oh->mpu_rt_idx);
2514+
/* Do we have a dts range for the interconnect target module? */
2515+
error = omap_hwmod_parse_module_range(oh, np, &res);
2516+
if (!error)
2517+
va_start = ioremap(res.start, resource_size(&res));
2518+
2519+
/* No ranges, rely on device reg entry */
2520+
if (!va_start)
2521+
va_start = of_iomap(np, index + oh->mpu_rt_idx);
24442522
} else {
24452523
va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start);
24462524
}

arch/arm/mach-omap2/omap_hwmod.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,11 +690,16 @@ struct omap_hwmod {
690690
struct omap_hwmod *parent_hwmod;
691691
};
692692

693+
struct device_node;
694+
693695
struct omap_hwmod *omap_hwmod_lookup(const char *name);
694696
int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
695697
void *data);
696698

697699
int __init omap_hwmod_setup_one(const char *name);
700+
int omap_hwmod_parse_module_range(struct omap_hwmod *oh,
701+
struct device_node *np,
702+
struct resource *res);
698703

699704
int omap_hwmod_enable(struct omap_hwmod *oh);
700705
int omap_hwmod_idle(struct omap_hwmod *oh);

0 commit comments

Comments
 (0)