|  | @@ -153,3 +153,143 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits)
 | 
	
		
			
				|  |  |  	int c = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	wkst = omap2_prm_read_mod_reg(module, wkst_off);
 | 
	
		
			
				|  |  | +	wkst &= omap2_prm_read_mod_reg(module, grpsel_off);
 | 
	
		
			
				|  |  | +	wkst &= ~ignore_bits;
 | 
	
		
			
				|  |  | +	if (wkst) {
 | 
	
		
			
				|  |  | +		iclk = omap2_cm_read_mod_reg(module, iclk_off);
 | 
	
		
			
				|  |  | +		fclk = omap2_cm_read_mod_reg(module, fclk_off);
 | 
	
		
			
				|  |  | +		while (wkst) {
 | 
	
		
			
				|  |  | +			clken = wkst;
 | 
	
		
			
				|  |  | +			omap2_cm_set_mod_reg_bits(clken, module, iclk_off);
 | 
	
		
			
				|  |  | +			/*
 | 
	
		
			
				|  |  | +			 * For USBHOST, we don't know whether HOST1 or
 | 
	
		
			
				|  |  | +			 * HOST2 woke us up, so enable both f-clocks
 | 
	
		
			
				|  |  | +			 */
 | 
	
		
			
				|  |  | +			if (module == OMAP3430ES2_USBHOST_MOD)
 | 
	
		
			
				|  |  | +				clken |= 1 << OMAP3430ES2_EN_USBHOST2_SHIFT;
 | 
	
		
			
				|  |  | +			omap2_cm_set_mod_reg_bits(clken, module, fclk_off);
 | 
	
		
			
				|  |  | +			omap2_prm_write_mod_reg(wkst, module, wkst_off);
 | 
	
		
			
				|  |  | +			wkst = omap2_prm_read_mod_reg(module, wkst_off);
 | 
	
		
			
				|  |  | +			wkst &= ~ignore_bits;
 | 
	
		
			
				|  |  | +			c++;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		omap2_cm_write_mod_reg(iclk, module, iclk_off);
 | 
	
		
			
				|  |  | +		omap2_cm_write_mod_reg(fclk, module, fclk_off);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return c;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static irqreturn_t _prcm_int_handle_io(int irq, void *unused)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	int c;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	c = prcm_clear_mod_irqs(WKUP_MOD, 1,
 | 
	
		
			
				|  |  | +		~(OMAP3430_ST_IO_MASK | OMAP3430_ST_IO_CHAIN_MASK));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return c ? IRQ_HANDLED : IRQ_NONE;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static irqreturn_t _prcm_int_handle_wakeup(int irq, void *unused)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	int c;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * Clear all except ST_IO and ST_IO_CHAIN for wkup module,
 | 
	
		
			
				|  |  | +	 * these are handled in a separate handler to avoid acking
 | 
	
		
			
				|  |  | +	 * IO events before parsing in mux code
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	c = prcm_clear_mod_irqs(WKUP_MOD, 1,
 | 
	
		
			
				|  |  | +		OMAP3430_ST_IO_MASK | OMAP3430_ST_IO_CHAIN_MASK);
 | 
	
		
			
				|  |  | +	c += prcm_clear_mod_irqs(CORE_MOD, 1, 0);
 | 
	
		
			
				|  |  | +	c += prcm_clear_mod_irqs(OMAP3430_PER_MOD, 1, 0);
 | 
	
		
			
				|  |  | +	if (omap_rev() > OMAP3430_REV_ES1_0) {
 | 
	
		
			
				|  |  | +		c += prcm_clear_mod_irqs(CORE_MOD, 3, 0);
 | 
	
		
			
				|  |  | +		c += prcm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1, 0);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return c ? IRQ_HANDLED : IRQ_NONE;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void omap34xx_save_context(u32 *save)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	u32 val;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* Read Auxiliary Control Register */
 | 
	
		
			
				|  |  | +	asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (val));
 | 
	
		
			
				|  |  | +	*save++ = 1;
 | 
	
		
			
				|  |  | +	*save++ = val;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* Read L2 AUX ctrl register */
 | 
	
		
			
				|  |  | +	asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (val));
 | 
	
		
			
				|  |  | +	*save++ = 1;
 | 
	
		
			
				|  |  | +	*save++ = val;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static int omap34xx_do_sram_idle(unsigned long save_state)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	omap34xx_cpu_suspend(save_state);
 | 
	
		
			
				|  |  | +	return 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void omap_sram_idle(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	/* Variable to tell what needs to be saved and restored
 | 
	
		
			
				|  |  | +	 * in omap_sram_idle*/
 | 
	
		
			
				|  |  | +	/* save_state = 0 => Nothing to save and restored */
 | 
	
		
			
				|  |  | +	/* save_state = 1 => Only L1 and logic lost */
 | 
	
		
			
				|  |  | +	/* save_state = 2 => Only L2 lost */
 | 
	
		
			
				|  |  | +	/* save_state = 3 => L1, L2 and logic lost */
 | 
	
		
			
				|  |  | +	int save_state = 0;
 | 
	
		
			
				|  |  | +	int mpu_next_state = PWRDM_POWER_ON;
 | 
	
		
			
				|  |  | +	int per_next_state = PWRDM_POWER_ON;
 | 
	
		
			
				|  |  | +	int core_next_state = PWRDM_POWER_ON;
 | 
	
		
			
				|  |  | +	int per_going_off;
 | 
	
		
			
				|  |  | +	int core_prev_state;
 | 
	
		
			
				|  |  | +	u32 sdrc_pwr = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
 | 
	
		
			
				|  |  | +	switch (mpu_next_state) {
 | 
	
		
			
				|  |  | +	case PWRDM_POWER_ON:
 | 
	
		
			
				|  |  | +	case PWRDM_POWER_RET:
 | 
	
		
			
				|  |  | +		/* No need to save context */
 | 
	
		
			
				|  |  | +		save_state = 0;
 | 
	
		
			
				|  |  | +		break;
 | 
	
		
			
				|  |  | +	case PWRDM_POWER_OFF:
 | 
	
		
			
				|  |  | +		save_state = 3;
 | 
	
		
			
				|  |  | +		break;
 | 
	
		
			
				|  |  | +	default:
 | 
	
		
			
				|  |  | +		/* Invalid state */
 | 
	
		
			
				|  |  | +		pr_err("Invalid mpu state in sram_idle\n");
 | 
	
		
			
				|  |  | +		return;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* NEON control */
 | 
	
		
			
				|  |  | +	if (pwrdm_read_pwrst(neon_pwrdm) == PWRDM_POWER_ON)
 | 
	
		
			
				|  |  | +		pwrdm_set_next_pwrst(neon_pwrdm, mpu_next_state);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* Enable IO-PAD and IO-CHAIN wakeups */
 | 
	
		
			
				|  |  | +	per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
 | 
	
		
			
				|  |  | +	core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	pwrdm_pre_transition(NULL);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* PER */
 | 
	
		
			
				|  |  | +	if (per_next_state < PWRDM_POWER_ON) {
 | 
	
		
			
				|  |  | +		per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
 | 
	
		
			
				|  |  | +		omap2_gpio_prepare_for_idle(per_going_off);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* CORE */
 | 
	
		
			
				|  |  | +	if (core_next_state < PWRDM_POWER_ON) {
 | 
	
		
			
				|  |  | +		if (core_next_state == PWRDM_POWER_OFF) {
 | 
	
		
			
				|  |  | +			omap3_core_save_context();
 | 
	
		
			
				|  |  | +			omap3_cm_save_context();
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	omap3_intc_prepare_idle();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * On EMU/HS devices ROM code restores a SRDC value
 | 
	
		
			
				|  |  | +	 * from scratchpad which has automatic self refresh on timeout
 |