[RFC] ARM: OMAP2+: hwmod: add an option to disable a module

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



If a module is not available, omap_hwmod will still try to access the
registers if it is present in the hwmod_list. If the module is not
powered at all (e.g. rtc) then linux can't start. It is possible
to disable the module by setting the state to disabled and to assign
ti,hwmods an empty string but this leads to the following warning:
[    0.188255] omap_hwmod: rtc missing dt data
[    0.188273] omap_hwmod: rtc: no MPU register target found
[    0.188287] omap_hwmod: rtc: no dt node
[    0.188300] ------------[ cut here ]------------
[    0.188330] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/omap_hwmod.c:2493 _init+0x1fc/0x45c()
[    0.188344] omap_hwmod: rtc: doesn't have mpu register target base
[    0.188357] Modules linked in:
[    0.188388] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.4.0-00004-g17704c9-dirty #24
[    0.188402] Hardware name: Generic AM33XX (Flattened Device Tree)
[    0.188445] [<c0017c24>] (unwind_backtrace) from [<c0013f88>] (show_stack+0x10/0x14)
[    0.188474] [<c0013f88>] (show_stack) from [<c0347860>] (dump_stack+0x84/0x9c)
[    0.188508] [<c0347860>] (dump_stack) from [<c003ca40>] (warn_slowpath_common+0x78/0xb4)
[    0.188534] [<c003ca40>] (warn_slowpath_common) from [<c003caac>] (warn_slowpath_fmt+0x30/0x40)
[    0.188558] [<c003caac>] (warn_slowpath_fmt) from [<c08b76e0>] (_init+0x1fc/0x45c)
[    0.188589] [<c08b76e0>] (_init) from [<c0027844>] (omap_hwmod_for_each+0x34/0x60)
[    0.188613] [<c0027844>] (omap_hwmod_for_each) from [<c08b7d04>] (__omap_hwmod_setup_all+0x24/0x40)
[    0.188638] [<c08b7d04>] (__omap_hwmod_setup_all) from [<c00098a4>] (do_one_initcall+0x80/0x1e0)
[    0.188675] [<c00098a4>] (do_one_initcall) from [<c08a9ec0>] (kernel_init_freeable+0x214/0x2e4)
[    0.188707] [<c08a9ec0>] (kernel_init_freeable) from [<c0642f4c>] (kernel_init+0x8/0xec)
[    0.188737] [<c0642f4c>] (kernel_init) from [<c000f810>] (ret_from_fork+0x14/0x24)
[    0.188919] ---[ end trace 9e6a5f1c3af2b60d ]---

Unfortunately we cannot check of_device_is_available because timers are
set to disabled. In this case we would not setup the timer module
what leads to a crash during boot.

For this reason a new ti,hwmod-disabled option was added that prevents
omap_hwmod to setup the module.

Signed-off-by: Stefan Eichenberger <stefan.eichenberger@xxxxxxxxxxxxx>
---
 Documentation/devicetree/bindings/arm/omap/omap.txt |  3 +++
 arch/arm/mach-omap2/omap_hwmod.c                    | 15 +++++++++++++++
 arch/arm/mach-omap2/omap_hwmod.h                    |  1 +
 3 files changed, 19 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
index 94b57f2..bc79fe1 100644
--- a/Documentation/devicetree/bindings/arm/omap/omap.txt
+++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
@@ -21,6 +21,9 @@ Required properties:
 Optional properties:
 - ti,no_idle_on_suspend: When present, it prevents the PM to idle the module
   during suspend.
+- ti,hwmod-disabled: When present, it will not try to initialize the module.
+  This is necessary if e.g. the rtc is not powered at all and the registers
+  are not accessible.
 - ti,no-reset-on-init: When present, the module should not be reset at init
 - ti,no-idle-on-init: When present, the module should not be idled at init
 - ti,no-idle: When present, the module is never allowed to idle.
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 83cb527..476e3ef 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2080,6 +2080,9 @@ static int _enable(struct omap_hwmod *oh)
 	int r;
 	int hwsup = 0;
 
+	if (oh->_state == _HWMOD_STATE_NOT_AVAILABLE)
+		return 0;
+
 	pr_debug("omap_hwmod: %s: enabling\n", oh->name);
 
 	/*
@@ -2200,6 +2203,9 @@ static int _enable(struct omap_hwmod *oh)
  */
 static int _idle(struct omap_hwmod *oh)
 {
+	if (oh->_state == _HWMOD_STATE_NOT_AVAILABLE)
+		return 0;
+
 	if (oh->flags & HWMOD_NO_IDLE) {
 		oh->_int_flags |= _HWMOD_SKIP_ENABLE;
 		return 0;
@@ -2491,6 +2497,15 @@ static int __init _init(struct omap_hwmod *oh, void *data)
 				oh->name, np->name);
 	}
 
+	if (np) {
+		if (of_find_property(np, "ti,hwmod-disabled", NULL)) {
+			pr_debug("omap_hwomd: %s is disabled, set to not available\n",
+				oh->name);
+			oh->_state = _HWMOD_STATE_NOT_AVAILABLE;
+			return 0;
+		}
+	}
+
 	r = _init_mpu_rt_base(oh, NULL, index, np);
 	if (r < 0) {
 		WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n",
diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h
index 4041bad..df0e83b 100644
--- a/arch/arm/mach-omap2/omap_hwmod.h
+++ b/arch/arm/mach-omap2/omap_hwmod.h
@@ -573,6 +573,7 @@ struct omap_hwmod_omap4_prcm {
 #define _HWMOD_STATE_ENABLED			4
 #define _HWMOD_STATE_IDLE			5
 #define _HWMOD_STATE_DISABLED			6
+#define _HWMOD_STATE_NOT_AVAILABLE		7
 
 /**
  * struct omap_hwmod_class - the type of an IP block
-- 
2.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux