| 
					
				 | 
			
			
				@@ -408,3 +408,150 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	if (!oh->class->sysc || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	    !(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	softrst_mask = (0x1 << oh->class->sysc->sysc_fields->srst_shift); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	*v |= softrst_mask; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * _wait_softreset_complete - wait for an OCP softreset to complete 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @oh: struct omap_hwmod * to wait on 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Wait until the IP block represented by @oh reports that its OCP 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * softreset is complete.  This can be triggered by software (see 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * _ocp_softreset()) or by hardware upon returning from off-mode (one 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * example is HSMMC).  Waits for up to MAX_MODULE_SOFTRESET_WAIT 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * microseconds.  Returns the number of microseconds waited. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int _wait_softreset_complete(struct omap_hwmod *oh) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	struct omap_hwmod_class_sysconfig *sysc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 softrst_mask; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int c = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	sysc = oh->class->sysc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (sysc->sysc_flags & SYSS_HAS_RESET_STATUS) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		omap_test_timeout((omap_hwmod_read(oh, sysc->syss_offs) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				   & SYSS_RESETDONE_MASK), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				  MAX_MODULE_SOFTRESET_WAIT, c); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	else if (sysc->sysc_flags & SYSC_HAS_RESET_STATUS) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		softrst_mask = (0x1 << sysc->sysc_fields->srst_shift); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		omap_test_timeout(!(omap_hwmod_read(oh, sysc->sysc_offs) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				    & softrst_mask), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				  MAX_MODULE_SOFTRESET_WAIT, c); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * _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) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @v: pointer to register contents to modify 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Update the module autoidle bit in @v to be @autoidle for the @oh 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * hwmod.  The autoidle bit controls whether the module can gate 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * internal clocks automatically when it isn't doing anything; the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * exact function of this bit varies on a per-module basis.  This 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * function does not write to the hardware.  Returns -EINVAL upon 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * error or 0 upon success. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				u32 *v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 autoidle_mask; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u8 autoidle_shift; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (!oh->class->sysc || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	    !(oh->class->sysc->sysc_flags & SYSC_HAS_AUTOIDLE)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	autoidle_shift = oh->class->sysc->sysc_fields->autoidle_shift; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	autoidle_mask = (0x1 << autoidle_shift); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	*v &= ~autoidle_mask; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	*v |= autoidle << autoidle_shift; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * _set_idle_ioring_wakeup - enable/disable IO pad wakeup on hwmod idle for mux 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @oh: struct omap_hwmod * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @set_wake: bool value indicating to set (true) or clear (false) wakeup enable 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Set or clear the I/O pad wakeup flag in the mux entries for the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * hwmod @oh.  This function changes the @oh->mux->pads_dynamic array 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * in memory.  If the hwmod is currently idled, and the new idle 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * values don't match the previous ones, this function will also 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * update the SCM PADCTRL registers.  Otherwise, if the hwmod is not 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * currently idled, this function won't touch the hardware: the new 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * mux settings are written to the SCM PADCTRL registers when the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * hwmod is idled.  No return value. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void _set_idle_ioring_wakeup(struct omap_hwmod *oh, bool set_wake) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	struct omap_device_pad *pad; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	bool change = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u16 prev_idle; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int j; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (!oh->mux || !oh->mux->enabled) 
			 |