diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-23 16:22:12 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-23 16:22:12 -0700 | 
| commit | fde75430278130505cac21997cd9f90b7bb2670a (patch) | |
| tree | 909f659117f5fa8bf1b9b46809f4dc655aee0d34 /arch/arm/mach-omap2/omap_hwmod.c | |
| parent | 1a4120bc101bdc25ec7258937b5071bf34b19cc5 (diff) | |
| parent | db3c47a3af96e8109b1bb114c32f0854259d5970 (diff) | |
| download | olio-linux-3.10-fde75430278130505cac21997cd9f90b7bb2670a.tar.xz olio-linux-3.10-fde75430278130505cac21997cd9f90b7bb2670a.zip  | |
Merge tag 'cleanup2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull arm-soc cleanups, part 2, from Arnd Bergmann:
 "These omap cleanups have dependencies on earlier omap branches that in
  turn depend on other cleanups, so they could not go into the same
  branch."
* tag 'cleanup2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc:
  ARM: OMAP: sdrc: Fix the build break for OMAP4 only builds
  ARM: OMAP2+: dmtimer: cleanup fclk usage
  ARM: OMAP2+: Fix mismerge for omap_hwmod_get_main_clk() API
  ARM: OMAP2+: Remove unnecessary ifdef around __omap2_set_globals
  ARM: OMAP2+: am33xx: Change cpu_is_am33xx to soc_is_am33xx
  ARM: OMAP2+: am33xx: Make am33xx as a separate class
  ARM: OMAP2+: Move omap3 dpll ops to dpll3xxx.c
  ARM: OMAP2+: All OMAP2PLUS uses omap-device.o target so add one entry
  ARM: OMAP: dmtimer: use devm_ API and do some cleanup in probe()
  ARM: OMAP2+: hwmod code: add support to set dmadisable in hwmod framework
  ARM: OMAP2+: PRM/CM: Move the stubbed prm and cm functions to prcm.c file and make them __weak
  ARM: OMAP2+: hwmod: add omap_hwmod_get_main_clk() API
  ARM: OMAP3+: dpll: optimize noncore dpll locking logic
  ARM: OMAP3: control: add definition for CONTROL_CAMERA_PHY_CTRL
  ARM: OMAP2+: powerdomain code: Fix Wake-up power domain power status
  ARM: OMAP4: clockdomain/CM code: Update supported transition modes
  ARM: OMAP3/4: omap_hwmod: Add rstst_offs field to struct omap_hwmod_omap4_prcm
  ARM: OMAP2+: hwmod: Add new sysc_type3 into omap_hwmod required for am33xx
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
| -rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 76 | 
1 files changed, 71 insertions, 5 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index bdc1ec2edb4..5d82bfca38c 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -416,6 +416,49 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v)  }  /** + * _set_dmadisable: set OCP_SYSCONFIG.DMADISABLE bit in @v + * @oh: struct omap_hwmod * + * + * The DMADISABLE bit is a semi-automatic bit present in sysconfig register + * of some modules. When the DMA must perform read/write accesses, the + * DMADISABLE bit is cleared by the hardware. But when the DMA must stop + * for power management, software must set the DMADISABLE bit back to 1. + * + * Set the DMADISABLE bit in @v for hwmod @oh.  Returns -EINVAL upon + * error or 0 upon success. + */ +static int _set_dmadisable(struct omap_hwmod *oh) +{ +	u32 v; +	u32 dmadisable_mask; + +	if (!oh->class->sysc || +	    !(oh->class->sysc->sysc_flags & SYSC_HAS_DMADISABLE)) +		return -EINVAL; + +	if (!oh->class->sysc->sysc_fields) { +		WARN(1, "omap_hwmod: %s: offset struct for sysconfig not provided in class\n", oh->name); +		return -EINVAL; +	} + +	/* clocks must be on for this operation */ +	if (oh->_state != _HWMOD_STATE_ENABLED) { +		pr_warn("omap_hwmod: %s: dma can be disabled only from enabled state\n", oh->name); +		return -EINVAL; +	} + +	pr_debug("omap_hwmod: %s: setting DMADISABLE\n", oh->name); + +	v = oh->_sysc_cache; +	dmadisable_mask = +		(0x1 << oh->class->sysc->sysc_fields->dmadisable_shift); +	v |= dmadisable_mask; +	_write_sysconfig(v, oh); + +	return 0; +} + +/**   * _set_module_autoidle: set the OCP_SYSCONFIG AUTOIDLE field in @v   * @oh: struct omap_hwmod *   * @autoidle: desired AUTOIDLE bitfield value (0 or 1) @@ -1668,11 +1711,17 @@ dis_opt_clks:   * therefore have no OCP header registers to access.  Others (like the   * IVA) have idiosyncratic reset sequences.  So for these relatively   * rare cases, custom reset code can be supplied in the struct - * omap_hwmod_class .reset function pointer.  Passes along the return - * value from either _ocp_softreset() or the custom reset function - - * these must return -EINVAL if the hwmod cannot be reset this way or - * if the hwmod is in the wrong state, -ETIMEDOUT if the module did - * not reset in time, or 0 upon success. + * omap_hwmod_class .reset function pointer. + * + * _set_dmadisable() is called to set the DMADISABLE bit so that it + * does not prevent idling of the system. This is necessary for cases + * where ROMCODE/BOOTLOADER uses dma and transfers control to the + * kernel without disabling dma. + * + * Passes along the return value from either _ocp_softreset() or the + * custom reset function - these must return -EINVAL if the hwmod + * cannot be reset this way or if the hwmod is in the wrong state, + * -ETIMEDOUT if the module did not reset in time, or 0 upon success.   */  static int _reset(struct omap_hwmod *oh)  { @@ -1694,6 +1743,8 @@ static int _reset(struct omap_hwmod *oh)  		}  	} +	_set_dmadisable(oh); +  	/*  	 * OCP_SYSCONFIG bits need to be reprogrammed after a  	 * softreset.  The _enable() function should be split to avoid @@ -3598,3 +3649,18 @@ void __init omap_hwmod_init(void)  	inited = true;  } + +/** + * omap_hwmod_get_main_clk - get pointer to main clock name + * @oh: struct omap_hwmod * + * + * Returns the main clock name assocated with @oh upon success, + * or NULL if @oh is NULL. + */ +const char *omap_hwmod_get_main_clk(struct omap_hwmod *oh) +{ +	if (!oh) +		return NULL; + +	return oh->main_clk; +}  |