diff options
| -rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 45 | 
1 files changed, 42 insertions, 3 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index e5cafed8ef2..ff729706c5a 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -138,6 +138,8 @@  #include <linux/spinlock.h>  #include <linux/slab.h>  #include <linux/bootmem.h> +#include <linux/of.h> +#include <linux/of_address.h>  #include <asm/system_misc.h> @@ -2346,6 +2348,34 @@ static int _shutdown(struct omap_hwmod *oh)  }  /** + * of_dev_hwmod_lookup - look up needed hwmod from dt blob + * @np: struct device_node * + * @oh: struct omap_hwmod * + * + * Parse the dt blob and find out needed hwmod. Recursive function is + * implemented to take care hierarchical dt blob parsing. + * Return: The device node on success or NULL on failure. + */ +static struct device_node *of_dev_hwmod_lookup(struct device_node *np, +						struct omap_hwmod *oh) +{ +	struct device_node *np0 = NULL, *np1 = NULL; +	const char *p; + +	for_each_child_of_node(np, np0) { +		if (of_find_property(np0, "ti,hwmods", NULL)) { +			p = of_get_property(np0, "ti,hwmods", NULL); +			if (!strcmp(p, oh->name)) +				return np0; +			np1 = of_dev_hwmod_lookup(np0, oh); +			if (np1) +				return np1; +		} +	} +	return NULL; +} + +/**   * _init_mpu_rt_base - populate the virtual address for a hwmod   * @oh: struct omap_hwmod * to locate the virtual address   * @@ -2357,7 +2387,8 @@ static int _shutdown(struct omap_hwmod *oh)  static void __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data)  {  	struct omap_hwmod_addr_space *mem; -	void __iomem *va_start; +	void __iomem *va_start = NULL; +	struct device_node *np;  	if (!oh)  		return; @@ -2371,10 +2402,18 @@ static void __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data)  	if (!mem) {  		pr_debug("omap_hwmod: %s: no MPU register target found\n",  			 oh->name); -		return; + +		/* Extract the IO space from device tree blob */ +		if (!of_have_populated_dt()) +			return; + +		np = of_dev_hwmod_lookup(of_find_node_by_name(NULL, "ocp"), oh); +		if (np) +			va_start = of_iomap(np, 0); +	} else { +		va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start);  	} -	va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start);  	if (!va_start) {  		pr_err("omap_hwmod: %s: Could not ioremap\n", oh->name);  		return;  |