aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorBenoit Cousson <b-cousson@ti.com>2010-05-20 14:31:08 -0400
committerPaul Walmsley <paul@pwsan.com>2010-05-20 14:31:08 -0400
commit9a23dfe12806920a8dfadec5ea5b83e5ca5378c9 (patch)
tree491129978e63b080cbc7f6656387f03bd2564d49 /arch/arm
parentd9e6625c70ff007ae246c9d62f8cdec8d08b2457 (diff)
OMAP4: hwmod & CM: Implement the omap4_cm_wait_module_ready function
The return of the omap4_cm_wait_module_ready function is checked in order to avoid accessing the sysconfig register if the module is not in the correct state. In that case the _setup will exit without trying to reset using sysconfig. For the moment a warning is printed. A proper management of fclk and module reset will have to be done in order to init correctly the problematic IPs listed below. <4>omap_hwmod: ivahd: cannot be enabled (3) <4>omap_hwmod: iss: cannot be enabled (3) <4>omap_hwmod: tesla: cannot be enabled (3) <4>omap_hwmod: sdma: cannot be enabled (3) <4>omap_hwmod: sl2: cannot be enabled (3) <4>omap_hwmod: sad2d: cannot be enabled (3) <4>omap_hwmod: ducati: cannot be enabled (3) Signed-off-by: Benoit Cousson <b-cousson@ti.com> Signed-off-by: Paul Walmsley <paul@pwsan.com>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-omap2/cm.h2
-rw-r--r--arch/arm/mach-omap2/cm4xxx.c36
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c33
3 files changed, 50 insertions, 21 deletions
diff --git a/arch/arm/mach-omap2/cm.h b/arch/arm/mach-omap2/cm.h
index bbc69df3bf3d..a02ca30423dc 100644
--- a/arch/arm/mach-omap2/cm.h
+++ b/arch/arm/mach-omap2/cm.h
@@ -112,7 +112,7 @@ extern u32 cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
112 112
113extern int omap2_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, 113extern int omap2_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id,
114 u8 idlest_shift); 114 u8 idlest_shift);
115extern int omap4_cm_wait_module_ready(u32 prcm_mod, u8 prcm_dev_offs); 115extern int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg);
116 116
117static inline u32 cm_set_mod_reg_bits(u32 bits, s16 module, s16 idx) 117static inline u32 cm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
118{ 118{
diff --git a/arch/arm/mach-omap2/cm4xxx.c b/arch/arm/mach-omap2/cm4xxx.c
index af32a457a46b..b101091e95d6 100644
--- a/arch/arm/mach-omap2/cm4xxx.c
+++ b/arch/arm/mach-omap2/cm4xxx.c
@@ -21,19 +21,41 @@
21 21
22#include <asm/atomic.h> 22#include <asm/atomic.h>
23 23
24#include <plat/common.h>
25
24#include "cm.h" 26#include "cm.h"
25#include "cm-regbits-44xx.h" 27#include "cm-regbits-44xx.h"
26 28
27/** 29/**
28 * omap4_cm_wait_idlest_ready - wait for a module to leave idle or standby 30 * omap4_cm_wait_module_ready - wait for a module to be in 'func' state
29 * @prcm_mod: PRCM module offset (XXX example) 31 * @clkctrl_reg: CLKCTRL module address
30 * @prcm_dev_offs: PRCM device offset (e.g. MCASP XXX example) 32 *
33 * Wait for the module IDLEST to be functional. If the idle state is in any
34 * the non functional state (trans, idle or disabled), module and thus the
35 * sysconfig cannot be accessed and will probably lead to an "imprecise
36 * external abort"
37 *
38 * Module idle state:
39 * 0x0 func: Module is fully functional, including OCP
40 * 0x1 trans: Module is performing transition: wakeup, or sleep, or sleep
41 * abortion
42 * 0x2 idle: Module is in Idle mode (only OCP part). It is functional if
43 * using separate functional clock
44 * 0x3 disabled: Module is disabled and cannot be accessed
31 * 45 *
32 * XXX document 46 * TODO: Need to handle module accessible in idle state
33 */ 47 */
34int omap4_cm_wait_idlest_ready(u32 prcm_mod, u8 prcm_dev_offs) 48int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg)
35{ 49{
36 /* FIXME: Add clock manager related code */ 50 int i = 0;
37 return 0; 51
52 if (!clkctrl_reg)
53 return 0;
54
55 omap_test_timeout(((__raw_readl(clkctrl_reg) &
56 OMAP4430_IDLEST_MASK) == 0),
57 MAX_MODULE_READY_TIME, i);
58
59 return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
38} 60}
39 61
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index e436dcb19795..4a134c4d2271 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -819,11 +819,8 @@ static int _wait_target_ready(struct omap_hwmod *oh)
819 ret = omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs, 819 ret = omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs,
820 oh->prcm.omap2.idlest_reg_id, 820 oh->prcm.omap2.idlest_reg_id,
821 oh->prcm.omap2.idlest_idle_bit); 821 oh->prcm.omap2.idlest_idle_bit);
822#if 0
823 } else if (cpu_is_omap44xx()) { 822 } else if (cpu_is_omap44xx()) {
824 ret = omap4_cm_wait_module_ready(oh->prcm.omap4.module_offs, 823 ret = omap4_cm_wait_module_ready(oh->prcm.omap4.clkctrl_reg);
825 oh->prcm.omap4.device_offs);
826#endif
827 } else { 824 } else {
828 BUG(); 825 BUG();
829 }; 826 };
@@ -912,16 +909,21 @@ static int _enable(struct omap_hwmod *oh)
912 _add_initiator_dep(oh, mpu_oh); 909 _add_initiator_dep(oh, mpu_oh);
913 _enable_clocks(oh); 910 _enable_clocks(oh);
914 911
915 if (oh->class->sysc) {
916 if (!(oh->_int_flags & _HWMOD_SYSCONFIG_LOADED))
917 _update_sysc_cache(oh);
918 _sysc_enable(oh);
919 }
920
921 r = _wait_target_ready(oh); 912 r = _wait_target_ready(oh);
922 if (!r) 913 if (!r) {
923 oh->_state = _HWMOD_STATE_ENABLED; 914 oh->_state = _HWMOD_STATE_ENABLED;
924 915
916 /* Access the sysconfig only if the target is ready */
917 if (oh->class->sysc) {
918 if (!(oh->_int_flags & _HWMOD_SYSCONFIG_LOADED))
919 _update_sysc_cache(oh);
920 _sysc_enable(oh);
921 }
922 } else {
923 pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
924 oh->name, r);
925 }
926
925 return r; 927 return r;
926} 928}
927 929
@@ -999,7 +1001,7 @@ static int _shutdown(struct omap_hwmod *oh)
999static int _setup(struct omap_hwmod *oh) 1001static int _setup(struct omap_hwmod *oh)
1000{ 1002{
1001 struct omap_hwmod_ocp_if *os; 1003 struct omap_hwmod_ocp_if *os;
1002 int i; 1004 int i, r;
1003 1005
1004 if (!oh) 1006 if (!oh)
1005 return -EINVAL; 1007 return -EINVAL;
@@ -1023,7 +1025,12 @@ static int _setup(struct omap_hwmod *oh)
1023 1025
1024 oh->_state = _HWMOD_STATE_INITIALIZED; 1026 oh->_state = _HWMOD_STATE_INITIALIZED;
1025 1027
1026 _enable(oh); 1028 r = _enable(oh);
1029 if (r) {
1030 pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n",
1031 oh->name, oh->_state);
1032 return 0;
1033 }
1027 1034
1028 if (!(oh->flags & HWMOD_INIT_NO_RESET)) { 1035 if (!(oh->flags & HWMOD_INIT_NO_RESET)) {
1029 /* 1036 /*