Beispiel #1
0
static void omap2_enter_mpu_retention(void)
{
	u32 sleep_time = 0;
	int only_idle = 0;

	/* Putting MPU into the WFI state while a transfer is active
	 * seems to cause the I2C block to timeout. Why? Good question. */
	if (omap2_i2c_active())
		return;

	/* The peripherals seem not to be able to wake up the MPU when
	 * it is in retention mode. */
	if (omap2_allow_mpu_retention()) {
		/* REVISIT: These write to reserved bits? */
		prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
		prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
		prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);

		/* Try to enter MPU retention */
		prm_write_mod_reg((0x01 << OMAP_POWERSTATE_SHIFT) |
				  OMAP_LOGICRETSTATE,
				  MPU_MOD, PM_PWSTCTRL);
	} else {
		/* Block MPU retention */

		prm_write_mod_reg(OMAP_LOGICRETSTATE, MPU_MOD, PM_PWSTCTRL);
		only_idle = 1;
	}

	if (omap2_pm_debug) {
		omap2_pm_dump(only_idle ? 2 : 1, 0, 0);
		sleep_time = omap2_read_32k_sync_counter();
	}

	omap2_sram_idle();

	if (omap2_pm_debug) {
		unsigned long long tmp;
		u32 resume_time;

		resume_time = omap2_read_32k_sync_counter();
		tmp = resume_time - sleep_time;
		tmp *= 1000000;
		omap2_pm_dump(only_idle ? 2 : 1, 1, tmp / 32768);
	}
}
Beispiel #2
0
static void serial_console_sleep(int enable)
{
    if (console_iclk == NULL || console_fclk == NULL)
        return;

    if (enable) {
        BUG_ON(serial_console_clock_disabled);
        if (clk_get_usecount(console_fclk) == 0)
            return;
        if ((int) serial_console_next_disable - (int) omap2_read_32k_sync_counter() >= 0)
            return;
        serial_wait_tx();
        clk_disable(console_iclk);
        clk_disable(console_fclk);
        serial_console_clock_disabled = 1;
    } else {
        int serial_wakeup = 0;
        u32 l;

        switch (serial_console_uart)  {
        case 1:
            l = prm_read_mod_reg(CORE_MOD, PM_WKST1);
            if (l & OMAP24XX_ST_UART1)
                serial_wakeup = 1;
            break;
        case 2:
            l = prm_read_mod_reg(CORE_MOD, PM_WKST1);
            if (l & OMAP24XX_ST_UART2)
                serial_wakeup = 1;
            break;
        case 3:
            l = prm_read_mod_reg(CORE_MOD, OMAP24XX_PM_WKST2);
            if (l & OMAP24XX_ST_UART3)
                serial_wakeup = 1;
            break;
        }
        if (serial_wakeup)
            serial_console_kick();
        if (!serial_console_clock_disabled)
            return;
        clk_enable(console_iclk);
        clk_enable(console_fclk);
        serial_console_clock_disabled = 0;
    }
}
Beispiel #3
0
static void serial_console_kick(void)
{
    serial_console_next_disable = omap2_read_32k_sync_counter();
    /* Keep the clocks on for 4 secs */
    serial_console_next_disable += 4 * 32768;
}
Beispiel #4
0
static void omap2_enter_full_retention(void)
{
	u32 l, sleep_time = 0;

	/* There is 1 reference hold for all children of the oscillator
	 * clock, the following will remove it. If no one else uses the
	 * oscillator itself it will be disabled if/when we enter retention
	 * mode.
	 */
	clk_disable(osc_ck);

	/* Clear old wake-up events */
	/* REVISIT: These write to reserved bits? */
	prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
	prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
	prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);

	/*
	 * Set MPU powerdomain's next power state to RETENTION;
	 * preserve logic state during retention
	 */
	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);

	/* Workaround to kill USB */
	l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL;
	omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0);

	omap2_gpio_prepare_for_retention();

	if (omap2_pm_debug) {
		omap2_pm_dump(0, 0, 0);
		sleep_time = omap2_read_32k_sync_counter();
	}

	/* One last check for pending IRQs to avoid extra latency due
	 * to sleeping unnecessarily. */
	if (omap_irq_pending())
		goto no_sleep;

	serial_console_sleep(1);
	/* Jump to SRAM suspend code */
	omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL),
				OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL),
				OMAP_SDRC_REGADDR(SDRC_POWER));
no_sleep:
	serial_console_sleep(0);

	if (omap2_pm_debug) {
		unsigned long long tmp;
		u32 resume_time;

		resume_time = omap2_read_32k_sync_counter();
		tmp = resume_time - sleep_time;
		tmp *= 1000000;
		omap2_pm_dump(0, 1, tmp / 32768);
	}
	omap2_gpio_resume_after_retention();

	clk_enable(osc_ck);

	/* clear CORE wake-up events */
	prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
	prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);

	/* wakeup domain events - bit 1: GPT1, bit5 GPIO */
	prm_clear_mod_reg_bits(0x4 | 0x1, WKUP_MOD, PM_WKST);

	/* MPU domain wake events */
	l = prm_read_mod_reg(OCP_MOD, OMAP2_PRM_IRQSTATUS_MPU_OFFSET);
	if (l & 0x01)
		prm_write_mod_reg(0x01, OCP_MOD,
				OMAP2_PRM_IRQSTATUS_MPU_OFFSET);
	if (l & 0x20)
		prm_write_mod_reg(0x20, OCP_MOD,
				OMAP2_PRM_IRQSTATUS_MPU_OFFSET);

	/* Mask future PRCM-to-MPU interrupts */
	prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRM_IRQSTATUS_MPU_OFFSET);
}