diff options
author | Benoit Cousson <b-cousson@ti.com> | 2010-05-20 14:31:08 -0400 |
---|---|---|
committer | Paul Walmsley <paul@pwsan.com> | 2010-05-20 14:31:08 -0400 |
commit | 9a23dfe12806920a8dfadec5ea5b83e5ca5378c9 (patch) | |
tree | 491129978e63b080cbc7f6656387f03bd2564d49 /arch/arm | |
parent | d9e6625c70ff007ae246c9d62f8cdec8d08b2457 (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.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/cm4xxx.c | 36 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 33 |
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 | ||
113 | extern int omap2_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, | 113 | extern int omap2_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, |
114 | u8 idlest_shift); | 114 | u8 idlest_shift); |
115 | extern int omap4_cm_wait_module_ready(u32 prcm_mod, u8 prcm_dev_offs); | 115 | extern int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg); |
116 | 116 | ||
117 | static inline u32 cm_set_mod_reg_bits(u32 bits, s16 module, s16 idx) | 117 | static 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 | */ |
34 | int omap4_cm_wait_idlest_ready(u32 prcm_mod, u8 prcm_dev_offs) | 48 | int 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) | |||
999 | static int _setup(struct omap_hwmod *oh) | 1001 | static 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 | /* |