diff options
| -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 bbc69df3bf3..a02ca30423d 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);  extern int omap2_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id,  				      u8 idlest_shift); -extern int omap4_cm_wait_module_ready(u32 prcm_mod, u8 prcm_dev_offs); +extern int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg);  static inline u32 cm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)  { diff --git a/arch/arm/mach-omap2/cm4xxx.c b/arch/arm/mach-omap2/cm4xxx.c index af32a457a46..b101091e95d 100644 --- a/arch/arm/mach-omap2/cm4xxx.c +++ b/arch/arm/mach-omap2/cm4xxx.c @@ -21,19 +21,41 @@  #include <asm/atomic.h> +#include <plat/common.h> +  #include "cm.h"  #include "cm-regbits-44xx.h"  /** - * omap4_cm_wait_idlest_ready - wait for a module to leave idle or standby - * @prcm_mod: PRCM module offset (XXX example) - * @prcm_dev_offs: PRCM device offset (e.g. MCASP XXX example) + * omap4_cm_wait_module_ready - wait for a module to be in 'func' state + * @clkctrl_reg: CLKCTRL module address + * + * Wait for the module IDLEST to be functional. If the idle state is in any + * the non functional state (trans, idle or disabled), module and thus the + * sysconfig cannot be accessed and will probably lead to an "imprecise + * external abort" + * + * Module idle state: + *   0x0 func:     Module is fully functional, including OCP + *   0x1 trans:    Module is performing transition: wakeup, or sleep, or sleep + *                 abortion + *   0x2 idle:     Module is in Idle mode (only OCP part). It is functional if + *                 using separate functional clock + *   0x3 disabled: Module is disabled and cannot be accessed   * - * XXX document + * TODO: Need to handle module accessible in idle state   */ -int omap4_cm_wait_idlest_ready(u32 prcm_mod, u8 prcm_dev_offs) +int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg)  { -	/* FIXME: Add clock manager related code */ -	return 0; +	int i = 0; + +	if (!clkctrl_reg) +		return 0; + +	omap_test_timeout(((__raw_readl(clkctrl_reg) & +			    OMAP4430_IDLEST_MASK) == 0), +			  MAX_MODULE_READY_TIME, i); + +	return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;  } diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index e436dcb1979..4a134c4d227 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)  		ret = omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs,  						 oh->prcm.omap2.idlest_reg_id,  						 oh->prcm.omap2.idlest_idle_bit); -#if 0  	} else if (cpu_is_omap44xx()) { -		ret = omap4_cm_wait_module_ready(oh->prcm.omap4.module_offs, -						 oh->prcm.omap4.device_offs); -#endif +		ret = omap4_cm_wait_module_ready(oh->prcm.omap4.clkctrl_reg);  	} else {  		BUG();  	}; @@ -912,16 +909,21 @@ static int _enable(struct omap_hwmod *oh)  	_add_initiator_dep(oh, mpu_oh);  	_enable_clocks(oh); -	if (oh->class->sysc) { -		if (!(oh->_int_flags & _HWMOD_SYSCONFIG_LOADED)) -			_update_sysc_cache(oh); -		_sysc_enable(oh); -	} -  	r = _wait_target_ready(oh); -	if (!r) +	if (!r) {  		oh->_state = _HWMOD_STATE_ENABLED; +		/* Access the sysconfig only if the target is ready */ +		if (oh->class->sysc) { +			if (!(oh->_int_flags & _HWMOD_SYSCONFIG_LOADED)) +				_update_sysc_cache(oh); +			_sysc_enable(oh); +		} +	} else { +		pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n", +			 oh->name, r); +	} +  	return r;  } @@ -999,7 +1001,7 @@ static int _shutdown(struct omap_hwmod *oh)  static int _setup(struct omap_hwmod *oh)  {  	struct omap_hwmod_ocp_if *os; -	int i; +	int i, r;  	if (!oh)  		return -EINVAL; @@ -1023,7 +1025,12 @@ static int _setup(struct omap_hwmod *oh)  	oh->_state = _HWMOD_STATE_INITIALIZED; -	_enable(oh); +	r = _enable(oh); +	if (r) { +		pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n", +			   oh->name, oh->_state); +		return 0; +	}  	if (!(oh->flags & HWMOD_INIT_NO_RESET)) {  		/*  |