summaryrefslogtreecommitdiff
path: root/arch/arm/mach-omap2/omap_hwmod.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-07 11:06:17 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-07 11:06:17 -0700
commit38f56f33ca381751f9b8910f67e7a805ec0b68cb (patch)
tree202f2ce60f3f43a948607ec76c8cc48c1cf73a4b /arch/arm/mach-omap2/omap_hwmod.c
parentfcba914542082b272f31c8e4c40000b88ed3208d (diff)
parent4183bef2e093a2f0aab45f2d5fed82b0e02aeacf (diff)
Merge tag 'dt-for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC device tree updates (part 2) from Arnd Bergmann: "These are mostly new device tree bindings for existing drivers, as well as changes to the device tree source files to add support for those devices, and a couple of new boards, most notably Samsung's Exynos5 based Chromebook. The changes depend on earlier platform specific updates and touch the usual platforms: omap, exynos, tegra, mxs, mvebu and davinci." * tag 'dt-for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (169 commits) ARM: exynos: dts: cros5250: add EC device ARM: dts: Add sbs-battery for exynos5250-snow ARM: dts: Add i2c-arbitrator bus for exynos5250-snow ARM: dts: add mshc controller node for Exynos4x12 SoCs ARM: dts: Add chip-id controller node on Exynos4/5 SoC ARM: EXYNOS: Create virtual I/O mapping for Chip-ID controller using device tree ARM: davinci: da850-evm: add SPI flash support ARM: davinci: da850: override SPI DT node device name ARM: davinci: da850: add SPI1 DT node spi/davinci: add DT binding documentation spi/davinci: no wildcards in DT compatible property ARM: dts: mvebu: Convert mvebu device tree files to 64 bits ARM: dts: mvebu: introduce internal-regs node ARM: dts: mvebu: Convert all the mvebu files to use the range property ARM: dts: mvebu: move all peripherals inside soc ARM: dts: mvebu: fix cpus section indentation ARM: davinci: da850: add EHRPWM & ECAP DT node ARM/dts: OMAP3: fix pinctrl-single configuration ARM: dts: Add OMAP3430 SDP NOR flash memory binding ARM: dts: Add NOR flash bindings for OMAP2420 H4 ...
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c48
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 93f213b6a784..d25a95fe9921 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) {