diff options
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
| -rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 126 | 
1 files changed, 93 insertions, 33 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 87cc6d058de..3f3bf323e20 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -130,7 +130,7 @@  #include <linux/kernel.h>  #include <linux/errno.h>  #include <linux/io.h> -#include <linux/clk.h> +#include <linux/clk-provider.h>  #include <linux/delay.h>  #include <linux/err.h>  #include <linux/list.h> @@ -139,27 +139,25 @@  #include <linux/slab.h>  #include <linux/bootmem.h> -#include <plat/clock.h> -#include <plat/omap_hwmod.h> -#include <plat/prcm.h> +#include "clock.h" +#include "omap_hwmod.h"  #include "soc.h"  #include "common.h"  #include "clockdomain.h"  #include "powerdomain.h" -#include "cm2xxx_3xxx.h" +#include "cm2xxx.h" +#include "cm3xxx.h"  #include "cminst44xx.h"  #include "cm33xx.h" -#include "prm2xxx_3xxx.h" +#include "prm.h" +#include "prm3xxx.h"  #include "prm44xx.h"  #include "prm33xx.h"  #include "prminst44xx.h"  #include "mux.h"  #include "pm.h" -/* Maximum microseconds to wait for OMAP module to softreset */ -#define MAX_MODULE_SOFTRESET_WAIT	10000 -  /* Name of the OMAP hwmod for the MPU */  #define MPU_INITIATOR_NAME		"mpu" @@ -648,6 +646,19 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)  	return 0;  } +static struct clockdomain *_get_clkdm(struct omap_hwmod *oh) +{ +	struct clk_hw_omap *clk; + +	if (oh->clkdm) { +		return oh->clkdm; +	} else if (oh->_clk) { +		clk = to_clk_hw_omap(__clk_get_hw(oh->_clk)); +		return  clk->clkdm; +	} +	return NULL; +} +  /**   * _add_initiator_dep: prevent @oh from smart-idling while @init_oh is active   * @oh: struct omap_hwmod * @@ -663,13 +674,18 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)   */  static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)  { -	if (!oh->_clk) +	struct clockdomain *clkdm, *init_clkdm; + +	clkdm = _get_clkdm(oh); +	init_clkdm = _get_clkdm(init_oh); + +	if (!clkdm || !init_clkdm)  		return -EINVAL; -	if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS) +	if (clkdm && clkdm->flags & CLKDM_NO_AUTODEPS)  		return 0; -	return clkdm_add_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm); +	return clkdm_add_sleepdep(clkdm, init_clkdm);  }  /** @@ -687,13 +703,18 @@ static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)   */  static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)  { -	if (!oh->_clk) +	struct clockdomain *clkdm, *init_clkdm; + +	clkdm = _get_clkdm(oh); +	init_clkdm = _get_clkdm(init_oh); + +	if (!clkdm || !init_clkdm)  		return -EINVAL; -	if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS) +	if (clkdm && clkdm->flags & CLKDM_NO_AUTODEPS)  		return 0; -	return clkdm_del_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm); +	return clkdm_del_sleepdep(clkdm, init_clkdm);  }  /** @@ -727,7 +748,7 @@ static int _init_main_clk(struct omap_hwmod *oh)  	 */  	clk_prepare(oh->_clk); -	if (!oh->_clk->clkdm) +	if (!_get_clkdm(oh))  		pr_debug("omap_hwmod: %s: missing clockdomain for %s.\n",  			   oh->name, oh->main_clk); @@ -1310,6 +1331,7 @@ static void _enable_sysc(struct omap_hwmod *oh)  	u8 idlemode, sf;  	u32 v;  	bool clkdm_act; +	struct clockdomain *clkdm;  	if (!oh->class->sysc)  		return; @@ -1329,11 +1351,9 @@ static void _enable_sysc(struct omap_hwmod *oh)  	v = oh->_sysc_cache;  	sf = oh->class->sysc->sysc_flags; +	clkdm = _get_clkdm(oh);  	if (sf & SYSC_HAS_SIDLEMODE) { -		clkdm_act = ((oh->clkdm && -			      oh->clkdm->flags & CLKDM_ACTIVE_WITH_MPU) || -			     (oh->_clk && oh->_clk->clkdm && -			      oh->_clk->clkdm->flags & CLKDM_ACTIVE_WITH_MPU)); +		clkdm_act = (clkdm && clkdm->flags & CLKDM_ACTIVE_WITH_MPU);  		if (clkdm_act && !(oh->class->sysc->idlemodes &  				   (SIDLE_SMART | SIDLE_SMART_WKUP)))  			idlemode = HWMOD_IDLEMODE_FORCE; @@ -1535,11 +1555,12 @@ static int _init_clocks(struct omap_hwmod *oh, void *data)  	pr_debug("omap_hwmod: %s: looking up clocks\n", oh->name); +	if (soc_ops.init_clkdm) +		ret |= soc_ops.init_clkdm(oh); +  	ret |= _init_main_clk(oh);  	ret |= _init_interface_clks(oh);  	ret |= _init_opt_clks(oh); -	if (soc_ops.init_clkdm) -		ret |= soc_ops.init_clkdm(oh);  	if (!ret)  		oh->_state = _HWMOD_STATE_CLKS_INITED; @@ -2095,7 +2116,8 @@ static int _enable(struct omap_hwmod *oh)  			_enable_sysc(oh);  		}  	} else { -		_omap4_disable_module(oh); +		if (soc_ops.disable_module) +			soc_ops.disable_module(oh);  		_disable_clocks(oh);  		pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",  			 oh->name, r); @@ -2703,7 +2725,34 @@ static int __init _alloc_linkspace(struct omap_hwmod_ocp_if **ois)  /* Static functions intended only for use in soc_ops field function pointers */  /** - * _omap2_wait_target_ready - wait for a module to leave slave idle + * _omap2xxx_wait_target_ready - wait for a module to leave slave idle + * @oh: struct omap_hwmod * + * + * Wait for a module @oh to leave slave idle.  Returns 0 if the module + * does not have an IDLEST bit or if the module successfully leaves + * slave idle; otherwise, pass along the return value of the + * appropriate *_cm*_wait_module_ready() function. + */ +static int _omap2xxx_wait_target_ready(struct omap_hwmod *oh) +{ +	if (!oh) +		return -EINVAL; + +	if (oh->flags & HWMOD_NO_IDLEST) +		return 0; + +	if (!_find_mpu_rt_port(oh)) +		return 0; + +	/* XXX check module SIDLEMODE, hardreset status, enabled clocks */ + +	return omap2xxx_cm_wait_module_ready(oh->prcm.omap2.module_offs, +					     oh->prcm.omap2.idlest_reg_id, +					     oh->prcm.omap2.idlest_idle_bit); +} + +/** + * _omap3xxx_wait_target_ready - wait for a module to leave slave idle   * @oh: struct omap_hwmod *   *   * Wait for a module @oh to leave slave idle.  Returns 0 if the module @@ -2711,7 +2760,7 @@ static int __init _alloc_linkspace(struct omap_hwmod_ocp_if **ois)   * slave idle; otherwise, pass along the return value of the   * appropriate *_cm*_wait_module_ready() function.   */ -static int _omap2_wait_target_ready(struct omap_hwmod *oh) +static int _omap3xxx_wait_target_ready(struct omap_hwmod *oh)  {  	if (!oh)  		return -EINVAL; @@ -2724,9 +2773,9 @@ static int _omap2_wait_target_ready(struct omap_hwmod *oh)  	/* XXX check module SIDLEMODE, hardreset status, enabled clocks */ -	return omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs, -					  oh->prcm.omap2.idlest_reg_id, -					  oh->prcm.omap2.idlest_idle_bit); +	return omap3xxx_cm_wait_module_ready(oh->prcm.omap2.module_offs, +					     oh->prcm.omap2.idlest_reg_id, +					     oh->prcm.omap2.idlest_idle_bit);  }  /** @@ -3565,10 +3614,15 @@ struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh)  {  	struct clk *c;  	struct omap_hwmod_ocp_if *oi; +	struct clockdomain *clkdm; +	struct clk_hw_omap *clk;  	if (!oh)  		return NULL; +	if (oh->clkdm) +		return oh->clkdm->pwrdm.ptr; +  	if (oh->_clk) {  		c = oh->_clk;  	} else { @@ -3578,11 +3632,12 @@ struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh)  		c = oi->_clk;  	} -	if (!c->clkdm) +	clk = to_clk_hw_omap(__clk_get_hw(c)); +	clkdm = clk->clkdm; +	if (!clkdm)  		return NULL; -	return c->clkdm->pwrdm.ptr; - +	return clkdm->pwrdm.ptr;  }  /** @@ -3994,8 +4049,13 @@ int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx)   */  void __init omap_hwmod_init(void)  { -	if (cpu_is_omap24xx() || cpu_is_omap34xx()) { -		soc_ops.wait_target_ready = _omap2_wait_target_ready; +	if (cpu_is_omap24xx()) { +		soc_ops.wait_target_ready = _omap2xxx_wait_target_ready; +		soc_ops.assert_hardreset = _omap2_assert_hardreset; +		soc_ops.deassert_hardreset = _omap2_deassert_hardreset; +		soc_ops.is_hardreset_asserted = _omap2_is_hardreset_asserted; +	} else if (cpu_is_omap34xx()) { +		soc_ops.wait_target_ready = _omap3xxx_wait_target_ready;  		soc_ops.assert_hardreset = _omap2_assert_hardreset;  		soc_ops.deassert_hardreset = _omap2_deassert_hardreset;  		soc_ops.is_hardreset_asserted = _omap2_is_hardreset_asserted;  |