diff options
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
| -rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 48 | 
1 files changed, 44 insertions, 4 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 93f213b6a78..d25a95fe992 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -139,6 +139,8 @@  #include <linux/slab.h>  #include <linux/bootmem.h>  #include <linux/cpu.h> +#include <linux/of.h> +#include <linux/of_address.h>  #include <asm/system_misc.h> @@ -2350,6 +2352,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   * @@ -2361,7 +2391,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; @@ -2375,10 +2406,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; @@ -2410,7 +2449,8 @@ static int __init _init(struct omap_hwmod *oh, void *data)  	if (oh->_state != _HWMOD_STATE_REGISTERED)  		return 0; -	_init_mpu_rt_base(oh, NULL); +	if (oh->class->sysc) +		_init_mpu_rt_base(oh, NULL);  	r = _init_clocks(oh, NULL);  	if (r < 0) {  |