static int omap2_enter_full_retention(void) { u32 l; clk_disable(osc_ck); omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1); omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2); omap2_prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST); pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET); pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET); l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL; omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0); omap2_gpio_prepare_for_idle(0); if (omap_irq_pending()) goto no_sleep; omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL), OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL), OMAP_SDRC_REGADDR(SDRC_POWER)); no_sleep: omap2_gpio_resume_after_idle(); clk_enable(osc_ck); omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1); omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2); omap2_prm_clear_mod_reg_bits(0x4 | 0x1, WKUP_MOD, PM_WKST); l = omap2_prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET); if (l & 0x01) omap2_prm_write_mod_reg(0x01, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET); if (l & 0x20) omap2_prm_write_mod_reg(0x20, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET); omap2_prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET); return 0; }
static void __init prcm_setup_regs(void) { int i, num_mem_banks; struct powerdomain *pwrdm; omap2_prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD, OMAP2_PRCM_SYSCONFIG_OFFSET); num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm); for (i = 0; i < num_mem_banks; i++) pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET); pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET); pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET); pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET); pwrdm = clkdm_get_pwrdm(dsp_clkdm); pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); clkdm_sleep(dsp_clkdm); pwrdm = clkdm_get_pwrdm(gfx_clkdm); pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); clkdm_sleep(gfx_clkdm); clkdm_for_each(omap_pm_clkdms_setup, NULL); clkdm_add_wkdep(mpu_clkdm, wkup_clkdm); #ifdef CONFIG_SUSPEND omap_pm_suspend = omap2_enter_full_retention; #endif omap2_prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD, OMAP2_PRCM_CLKSSETUP_OFFSET); omap2_prm_write_mod_reg(2 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD, OMAP2_PRCM_VOLTSETUP_OFFSET); omap2_prm_write_mod_reg(OMAP24XX_AUTO_EXTVOLT_MASK | (0x1 << OMAP24XX_SETOFF_LEVEL_SHIFT) | OMAP24XX_MEMRETCTRL_MASK | (0x1 << OMAP24XX_SETRET_LEVEL_SHIFT) | (0x0 << OMAP24XX_VOLT_LEVEL_SHIFT), OMAP24XX_GR_MOD, OMAP2_PRCM_VOLTCTRL_OFFSET); omap2_prm_write_mod_reg(OMAP24XX_EN_GPIOS_MASK | OMAP24XX_EN_GPT1_MASK, WKUP_MOD, PM_WKEN); }
static void omap2_enter_full_retention(void) { u32 l; struct timespec ts_preidle, ts_postidle, ts_idle; /* 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? */ omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1); omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2); omap2_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_idle(0); if (omap2_pm_debug) { omap2_pm_dump(0, 0, 0); getnstimeofday(&ts_preidle); } /* One last check for pending IRQs to avoid extra latency due * to sleeping unnecessarily. */ if (omap_irq_pending()) goto no_sleep; /* Block console output in case it is on one of the OMAP UARTs */ if (!is_suspending()) if (!console_trylock()) goto no_sleep; omap_uart_prepare_idle(0); omap_uart_prepare_idle(1); omap_uart_prepare_idle(2); /* 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)); omap_uart_resume_idle(2); omap_uart_resume_idle(1); omap_uart_resume_idle(0); if (!is_suspending()) console_unlock(); no_sleep: if (omap2_pm_debug) { unsigned long long tmp; getnstimeofday(&ts_postidle); ts_idle = timespec_sub(ts_postidle, ts_preidle); tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC; omap2_pm_dump(0, 1, tmp); } omap2_gpio_resume_after_idle(); clk_enable(osc_ck); /* clear CORE wake-up events */ omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1); omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2); /* wakeup domain events - bit 1: GPT1, bit5 GPIO */ omap2_prm_clear_mod_reg_bits(0x4 | 0x1, WKUP_MOD, PM_WKST); /* MPU domain wake events */ l = omap2_prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET); if (l & 0x01) omap2_prm_write_mod_reg(0x01, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET); if (l & 0x20) omap2_prm_write_mod_reg(0x20, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET); /* Mask future PRCM-to-MPU interrupts */ omap2_prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET); }
static void __init prcm_setup_regs(void) { int i, num_mem_banks; struct powerdomain *pwrdm; /* * Enable autoidle * XXX This should be handled by hwmod code or PRCM init code */ omap2_prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD, OMAP2_PRCM_SYSCONFIG_OFFSET); /* * Set CORE powerdomain memory banks to retain their contents * during RETENTION */ num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm); for (i = 0; i < num_mem_banks; i++) pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET); /* Set CORE powerdomain's next power state to RETENTION */ pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET); /* * 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); /* Force-power down DSP, GFX powerdomains */ pwrdm = clkdm_get_pwrdm(dsp_clkdm); pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); clkdm_sleep(dsp_clkdm); pwrdm = clkdm_get_pwrdm(gfx_clkdm); pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); clkdm_sleep(gfx_clkdm); /* Enable hardware-supervised idle for all clkdms */ clkdm_for_each(clkdms_setup, NULL); clkdm_add_wkdep(mpu_clkdm, wkup_clkdm); /* REVISIT: Configure number of 32 kHz clock cycles for sys_clk * stabilisation */ omap2_prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD, OMAP2_PRCM_CLKSSETUP_OFFSET); /* Configure automatic voltage transition */ omap2_prm_write_mod_reg(2 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD, OMAP2_PRCM_VOLTSETUP_OFFSET); omap2_prm_write_mod_reg(OMAP24XX_AUTO_EXTVOLT_MASK | (0x1 << OMAP24XX_SETOFF_LEVEL_SHIFT) | OMAP24XX_MEMRETCTRL_MASK | (0x1 << OMAP24XX_SETRET_LEVEL_SHIFT) | (0x0 << OMAP24XX_VOLT_LEVEL_SHIFT), OMAP24XX_GR_MOD, OMAP2_PRCM_VOLTCTRL_OFFSET); /* Enable wake-up events */ omap2_prm_write_mod_reg(OMAP24XX_EN_GPIOS_MASK | OMAP24XX_EN_GPT1_MASK, WKUP_MOD, PM_WKEN); }
static void __init prcm_setup_regs(void) { int i, num_mem_banks; struct powerdomain *pwrdm; /* Enable autoidle */ prm_write_mod_reg(OMAP24XX_AUTOIDLE, OCP_MOD, OMAP24XX_PRM_SYSCONFIG_OFFSET); /* Set all domain wakeup dependencies */ prm_write_mod_reg(OMAP_EN_WKUP_MASK, MPU_MOD, PM_WKDEP); prm_write_mod_reg(0, OMAP24XX_DSP_MOD, PM_WKDEP); prm_write_mod_reg(0, GFX_MOD, PM_WKDEP); prm_write_mod_reg(0, CORE_MOD, PM_WKDEP); if (cpu_is_omap2430()) prm_write_mod_reg(0, OMAP2430_MDM_MOD, PM_WKDEP); /* * Set CORE powerdomain memory banks to retain their contents * during RETENTION */ num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm); for (i = 0; i < num_mem_banks; i++) pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET); /* Set CORE powerdomain's next power state to RETENTION */ pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET); /* * 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); /* Force-power down DSP, GFX powerdomains */ pwrdm = clkdm_get_pwrdm(dsp_clkdm); pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); omap2_clkdm_sleep(dsp_clkdm); pwrdm = clkdm_get_pwrdm(gfx_clkdm); pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); omap2_clkdm_sleep(gfx_clkdm); /* Enable clockdomain hardware-supervised control for all clkdms */ clkdm_for_each(_pm_clkdm_enable_hwsup, NULL); /* Enable clock autoidle for all domains */ cm_write_mod_reg(OMAP24XX_AUTO_CAM | OMAP24XX_AUTO_MAILBOXES | OMAP24XX_AUTO_WDT4 | OMAP2420_AUTO_WDT3 | OMAP24XX_AUTO_MSPRO | OMAP2420_AUTO_MMC | OMAP24XX_AUTO_FAC | OMAP2420_AUTO_EAC | OMAP24XX_AUTO_HDQ | OMAP24XX_AUTO_UART2 | OMAP24XX_AUTO_UART1 | OMAP24XX_AUTO_I2C2 | OMAP24XX_AUTO_I2C1 | OMAP24XX_AUTO_MCSPI2 | OMAP24XX_AUTO_MCSPI1 | OMAP24XX_AUTO_MCBSP2 | OMAP24XX_AUTO_MCBSP1 | OMAP24XX_AUTO_GPT12 | OMAP24XX_AUTO_GPT11 | OMAP24XX_AUTO_GPT10 | OMAP24XX_AUTO_GPT9 | OMAP24XX_AUTO_GPT8 | OMAP24XX_AUTO_GPT7 | OMAP24XX_AUTO_GPT6 | OMAP24XX_AUTO_GPT5 | OMAP24XX_AUTO_GPT4 | OMAP24XX_AUTO_GPT3 | OMAP24XX_AUTO_GPT2 | OMAP2420_AUTO_VLYNQ | OMAP24XX_AUTO_DSS, CORE_MOD, CM_AUTOIDLE1); cm_write_mod_reg(OMAP24XX_AUTO_UART3 | OMAP24XX_AUTO_SSI | OMAP24XX_AUTO_USB, CORE_MOD, CM_AUTOIDLE2); cm_write_mod_reg(OMAP24XX_AUTO_SDRC | OMAP24XX_AUTO_GPMC | OMAP24XX_AUTO_SDMA, CORE_MOD, CM_AUTOIDLE3); cm_write_mod_reg(OMAP24XX_AUTO_PKA | OMAP24XX_AUTO_AES | OMAP24XX_AUTO_RNG | OMAP24XX_AUTO_SHA | OMAP24XX_AUTO_DES, CORE_MOD, OMAP24XX_CM_AUTOIDLE4); cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI, OMAP24XX_DSP_MOD, CM_AUTOIDLE); /* Put DPLL and both APLLs into autoidle mode */ cm_write_mod_reg((0x03 << OMAP24XX_AUTO_DPLL_SHIFT) | (0x03 << OMAP24XX_AUTO_96M_SHIFT) | (0x03 << OMAP24XX_AUTO_54M_SHIFT), PLL_MOD, CM_AUTOIDLE); cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL | OMAP24XX_AUTO_WDT1 | OMAP24XX_AUTO_MPU_WDT | OMAP24XX_AUTO_GPIOS | OMAP24XX_AUTO_32KSYNC | OMAP24XX_AUTO_GPT1, WKUP_MOD, CM_AUTOIDLE); /* REVISIT: Configure number of 32 kHz clock cycles for sys_clk * stabilisation */ prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD, OMAP24XX_PRCM_CLKSSETUP_OFFSET); /* Configure automatic voltage transition */ prm_write_mod_reg(2 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD, OMAP24XX_PRCM_VOLTSETUP_OFFSET); prm_write_mod_reg(OMAP24XX_AUTO_EXTVOLT | (0x1 << OMAP24XX_SETOFF_LEVEL_SHIFT) | OMAP24XX_MEMRETCTRL | (0x1 << OMAP24XX_SETRET_LEVEL_SHIFT) | (0x0 << OMAP24XX_VOLT_LEVEL_SHIFT), OMAP24XX_GR_MOD, OMAP24XX_PRCM_VOLTCTRL_OFFSET); /* Enable wake-up events */ prm_write_mod_reg(OMAP24XX_EN_GPIOS | OMAP24XX_EN_GPT1, WKUP_MOD, PM_WKEN); }
static int omap2_enter_full_retention(void) { u32 l; /* 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? */ omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1); omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2); omap2_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_idle(0); /* One last check for pending IRQs to avoid extra latency due * to sleeping unnecessarily. */ if (omap_irq_pending()) goto no_sleep; /* 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: omap2_gpio_resume_after_idle(); clk_enable(osc_ck); /* clear CORE wake-up events */ omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1); omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2); /* wakeup domain events - bit 1: GPT1, bit5 GPIO */ omap2_prm_clear_mod_reg_bits(0x4 | 0x1, WKUP_MOD, PM_WKST); /* MPU domain wake events */ l = omap2_prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET); if (l & 0x01) omap2_prm_write_mod_reg(0x01, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET); if (l & 0x20) omap2_prm_write_mod_reg(0x20, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET); /* Mask future PRCM-to-MPU interrupts */ omap2_prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET); return 0; }
static void __init prcm_setup_regs(void) { int i, num_mem_banks; struct powerdomain *pwrdm; /* Enable autoidle */ omap2_prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD, OMAP2_PRCM_SYSCONFIG_OFFSET); /* * Set CORE powerdomain memory banks to retain their contents * during RETENTION */ num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm); for (i = 0; i < num_mem_banks; i++) pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET); /* Set CORE powerdomain's next power state to RETENTION */ pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET); /* * 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); /* Force-power down DSP, GFX powerdomains */ pwrdm = clkdm_get_pwrdm(dsp_clkdm); pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); omap2_clkdm_sleep(dsp_clkdm); pwrdm = clkdm_get_pwrdm(gfx_clkdm); pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); omap2_clkdm_sleep(gfx_clkdm); /* * Clear clockdomain wakeup dependencies and enable * hardware-supervised idle for all clkdms */ clkdm_for_each(clkdms_setup, NULL); clkdm_add_wkdep(mpu_clkdm, wkup_clkdm); /* Enable clock autoidle for all domains */ omap2_cm_write_mod_reg(OMAP24XX_AUTO_CAM_MASK | OMAP24XX_AUTO_MAILBOXES_MASK | OMAP24XX_AUTO_WDT4_MASK | OMAP2420_AUTO_WDT3_MASK | OMAP24XX_AUTO_MSPRO_MASK | OMAP2420_AUTO_MMC_MASK | OMAP24XX_AUTO_FAC_MASK | OMAP2420_AUTO_EAC_MASK | OMAP24XX_AUTO_HDQ_MASK | OMAP24XX_AUTO_UART2_MASK | OMAP24XX_AUTO_UART1_MASK | OMAP24XX_AUTO_I2C2_MASK | OMAP24XX_AUTO_I2C1_MASK | OMAP24XX_AUTO_MCSPI2_MASK | OMAP24XX_AUTO_MCSPI1_MASK | OMAP24XX_AUTO_MCBSP2_MASK | OMAP24XX_AUTO_MCBSP1_MASK | OMAP24XX_AUTO_GPT12_MASK | OMAP24XX_AUTO_GPT11_MASK | OMAP24XX_AUTO_GPT10_MASK | OMAP24XX_AUTO_GPT9_MASK | OMAP24XX_AUTO_GPT8_MASK | OMAP24XX_AUTO_GPT7_MASK | OMAP24XX_AUTO_GPT6_MASK | OMAP24XX_AUTO_GPT5_MASK | OMAP24XX_AUTO_GPT4_MASK | OMAP24XX_AUTO_GPT3_MASK | OMAP24XX_AUTO_GPT2_MASK | OMAP2420_AUTO_VLYNQ_MASK | OMAP24XX_AUTO_DSS_MASK, CORE_MOD, CM_AUTOIDLE1); omap2_cm_write_mod_reg(OMAP24XX_AUTO_UART3_MASK | OMAP24XX_AUTO_SSI_MASK | OMAP24XX_AUTO_USB_MASK, CORE_MOD, CM_AUTOIDLE2); omap2_cm_write_mod_reg(OMAP24XX_AUTO_SDRC_MASK | OMAP24XX_AUTO_GPMC_MASK | OMAP24XX_AUTO_SDMA_MASK, CORE_MOD, CM_AUTOIDLE3); omap2_cm_write_mod_reg(OMAP24XX_AUTO_PKA_MASK | OMAP24XX_AUTO_AES_MASK | OMAP24XX_AUTO_RNG_MASK | OMAP24XX_AUTO_SHA_MASK | OMAP24XX_AUTO_DES_MASK, CORE_MOD, OMAP24XX_CM_AUTOIDLE4); omap2_cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI_MASK, OMAP24XX_DSP_MOD, CM_AUTOIDLE); /* Put DPLL and both APLLs into autoidle mode */ omap2_cm_write_mod_reg((0x03 << OMAP24XX_AUTO_DPLL_SHIFT) | (0x03 << OMAP24XX_AUTO_96M_SHIFT) | (0x03 << OMAP24XX_AUTO_54M_SHIFT), PLL_MOD, CM_AUTOIDLE); omap2_cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL_MASK | OMAP24XX_AUTO_WDT1_MASK | OMAP24XX_AUTO_MPU_WDT_MASK | OMAP24XX_AUTO_GPIOS_MASK | OMAP24XX_AUTO_32KSYNC_MASK | OMAP24XX_AUTO_GPT1_MASK, WKUP_MOD, CM_AUTOIDLE); /* REVISIT: Configure number of 32 kHz clock cycles for sys_clk * stabilisation */ omap2_prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD, OMAP2_PRCM_CLKSSETUP_OFFSET); /* Configure automatic voltage transition */ omap2_prm_write_mod_reg(2 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD, OMAP2_PRCM_VOLTSETUP_OFFSET); omap2_prm_write_mod_reg(OMAP24XX_AUTO_EXTVOLT_MASK | (0x1 << OMAP24XX_SETOFF_LEVEL_SHIFT) | OMAP24XX_MEMRETCTRL_MASK | (0x1 << OMAP24XX_SETRET_LEVEL_SHIFT) | (0x0 << OMAP24XX_VOLT_LEVEL_SHIFT), OMAP24XX_GR_MOD, OMAP2_PRCM_VOLTCTRL_OFFSET); /* Enable wake-up events */ omap2_prm_write_mod_reg(OMAP24XX_EN_GPIOS_MASK | OMAP24XX_EN_GPT1_MASK, WKUP_MOD, PM_WKEN); }
/** * omap4_enter_idle - Programs OMAP4 to enter the specified state * @dev: cpuidle device * @state: The target state to be programmed * * Called from the CPUidle framework to program the device to the * specified low power state selected by the governor. * Returns the amount of time spent in the low power state. */ static int omap4_enter_idle(struct cpuidle_device *dev, struct cpuidle_state *state) { struct omap4_processor_cx *cx = cpuidle_get_statedata(state); struct timespec ts_preidle, ts_postidle, ts_idle; u32 cpu1_state; int cpu_id = smp_processor_id(); /* Used to keep track of the total time in idle */ getnstimeofday(&ts_preidle); local_irq_disable(); local_fiq_disable(); /* * Do only WFI for non-boot CPU(aux cores) */ if (dev->cpu) { wmb(); DO_WFI(); goto return_sleep_time; } /* * Do only a WFI as long as CPU1 is online */ if (num_online_cpus() > 1) { wmb(); DO_WFI(); goto return_sleep_time; } /* * Hold on till CPU1 hits OFF */ cpu1_state = pwrdm_read_pwrst(cpu1_pd); if (cpu1_state != PWRDM_POWER_OFF) { wmb(); DO_WFI(); goto return_sleep_time; } if (cx->type > OMAP4_STATE_C1) clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu_id); #ifdef CONFIG_PM_DEBUG pwrdm_pre_transition(); #endif pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state); omap4_set_pwrdm_state(mpu_pd, cx->mpu_state); pwrdm_set_logic_retst(core_pd, cx->core_logic_state); omap4_set_pwrdm_state(core_pd, cx->core_state); omap4_enter_sleep(dev->cpu, cx->cpu0_state); /* restore the MPU and CORE states to ON */ omap4_set_pwrdm_state(mpu_pd, PWRDM_POWER_ON); omap4_set_pwrdm_state(core_pd, PWRDM_POWER_ON); #ifdef CONFIG_PM_DEBUG pwrdm_post_transition(); #endif if (cx->type > OMAP4_STATE_C1) clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id); return_sleep_time: getnstimeofday(&ts_postidle); ts_idle = timespec_sub(ts_postidle, ts_preidle); local_irq_enable(); local_fiq_enable(); return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC;; }
/** * power_domain_test - Test the power domain APIs * * Test the power domain APIs for all power domains * */ void power_domain_test() { int bank, i; int val = -EINVAL; static struct powerdomain *p, *pwrdm; for (i = 0; powerdomains_omap[i] != NULL; i++) { p = powerdomains_omap[i]; pwrdm = pwrdm_lookup(p->name); if (pwrdm) printk(KERN_INFO "PWR DM No%d = %s\n", i, pwrdm->name); else printk(KERN_INFO "PWR DM %s not supported\n", p->name); } /* i starts from 1 as gfx_pwrdm not supported in ES3.1.1 */ for (i = 1; powerdomains_omap[i] != NULL; i++) { val = pwrdm_add_clkdm(p = powerdomains_omap[i], &dummy_clkdm); if (val == 0) printk(KERN_INFO "Clock Domain Registered for %s\n", p->name); else if (val == -EINVAL) printk(KERN_ERR "Clock Domain Register FAILED!!! for" " %s\n", p->name); } for (i = 1; powerdomains_omap[i] != NULL; i++) { val = pwrdm_del_clkdm(p = powerdomains_omap[i], &dummy_clkdm); if (val == 0) printk(KERN_INFO "Clock Domain Unregistered for %s\n", p->name); else if (val == -EINVAL) printk(KERN_ERR "Clock Domain Unregister FAILED!!! for" " %s\n", p->name); } for (i = 1; powerdomains_omap[i] != NULL; i++) { val = pwrdm_get_mem_bank_count(p = powerdomains_omap[i]); printk(KERN_INFO "Bnk Cnt for %s = %d\n", p->name, val); } for (i = 1; powerdomains_omap[i] != NULL; i++) { val = pwrdm_read_logic_pwrst(p = powerdomains_omap[i]); printk(KERN_INFO "PwrState of %s = %d\n", p->name, val); } for (i = 1; powerdomains_omap[i] != NULL; i++) { val = pwrdm_set_logic_retst(p = powerdomains_omap[i], PWRDM_POWER_OFF); if (val == 0) printk(KERN_INFO "Logic RET State OFF for %s Set\n", p->name); else if (val == -EINVAL) printk(KERN_INFO "OFF State not supported for %s\n", p->name); else printk(KERN_ERR "Set Logic RET State OFF FAILED!!!" " with value %d\n", val); } for (i = 1; powerdomains_omap[i] != NULL; i++) { val = pwrdm_set_logic_retst(p = powerdomains_omap[i], PWRDM_POWER_RET); if (val == 0) printk(KERN_INFO "Logic RET State RET for %s Set\n", p->name); else if (val == -EINVAL) printk(KERN_INFO "RET State not supported for %s\n", p->name); else printk(KERN_ERR "Logic RET State RET FAILED!!!" " with value %d\n", val); } for (i = 1; powerdomains_omap[i] != NULL; i++) { val = pwrdm_read_pwrst(p = powerdomains_omap[i]); printk(KERN_INFO "PwrState of %s = %d\n", p->name, val); } for (i = 1; powerdomains_omap[i] != NULL; i++) { val = pwrdm_set_next_pwrst(p = powerdomains_omap[i], PWRDM_POWER_OFF); if (val == 0) printk(KERN_INFO "Next PWRST for %s Set to OFF\n", p->name); else if (val == -EINVAL) printk(KERN_INFO "OFF not supported for %s\n", p->name); else printk(KERN_ERR "Next PWRST Set to OFF FAILED!!!" " with value %d\n", val); } for (i = 1; powerdomains_omap[i] != NULL; i++) { val = pwrdm_set_next_pwrst(p = powerdomains_omap[i], PWRDM_POWER_RET); if (val == 0) printk(KERN_INFO "Next PWRST for %s Set to RET\n", p->name); else if (val == -EINVAL) printk(KERN_INFO "RET not supported for %s\n", p->name); else printk(KERN_ERR "Next PWRST Set to RET FAILED!!!" " with value %d\n", val); } for (i = 1; powerdomains_omap[i] != NULL; i++) { val = pwrdm_set_next_pwrst(p = powerdomains_omap[i], PWRDM_POWER_ON); if (val == 0) printk(KERN_INFO "Next PWRST for %s Set to ON\n", p->name); else if (val == -EINVAL) printk(KERN_INFO "ON not supported for %s\n", p->name); else printk(KERN_ERR "Next PWRST Set to ON FAILED!!!" " with value %d\n", val); } for (i = 1; powerdomains_omap[i] != NULL; i++) { val = pwrdm_read_next_pwrst(p = powerdomains_omap[i]); printk(KERN_INFO "Next Power State of %s = %d\n", p->name, val); } for (i = 1; powerdomains_omap[i] != NULL; i++) { val = pwrdm_read_pwrst(p = powerdomains_omap[i]); printk(KERN_INFO "Current Power State of %s = %d\n", p->name, val); } for (i = 1; powerdomains_omap[i] != NULL; i++) { for (bank = 0; bank < PWRDM_MAX_MEM_BANKS; bank++) { val = pwrdm_set_mem_onst(p = powerdomains_omap[i], bank, PWRDM_POWER_OFF); if (val == 0) printk(KERN_INFO "Memory ON State OFF for %s" " Set\n", p->name); else if (val == -EINVAL) printk(KERN_INFO "OFF State not supported" " for %s\n", p->name); else if (val == -EEXIST) printk(KERN_ERR "Memory Bank %d not present" " for %s\n", bank, p->name); else printk(KERN_ERR "Memory ON State OFF FAILED!!!" " with value %d\n", val); } } for (i = 1; powerdomains_omap[i] != NULL; i++) { for (bank = 0; bank < PWRDM_MAX_MEM_BANKS; bank++) { val = pwrdm_set_mem_onst(p = powerdomains_omap[i], bank, PWRDM_POWER_RET); if (val == 0) printk(KERN_INFO "Memory ON State RET for %s" " Set\n", p->name); else if (val == -EINVAL) printk(KERN_INFO "RET State not supported" " for %s\n", p->name); else if (val == -EEXIST) printk(KERN_ERR "Memory Bank %d not present" " for %s\n", bank, p->name); else printk(KERN_ERR "Memory ON State RET FAILED!!!" " with value %d\n", val); } } for (i = 1; powerdomains_omap[i] != NULL; i++) { for (bank = 0; bank < PWRDM_MAX_MEM_BANKS; bank++) { val = pwrdm_set_mem_retst(p = powerdomains_omap[i], bank, PWRDM_POWER_OFF); if (val == 0) printk(KERN_INFO "Memory RET State OFF for" " %s Set\n", p->name); else if (val == -EINVAL) printk(KERN_INFO "OFF State not supported for" " %s\n", p->name); else if (val == -EEXIST) printk(KERN_ERR "Memory Bank %d not present" " for %s\n", bank, p->name); else printk(KERN_ERR "Memory ON State OFF FAILED!!!" " with value %d\n", val); } } for (i = 1; powerdomains_omap[i] != NULL; i++) { for (bank = 0; bank < PWRDM_MAX_MEM_BANKS; bank++) { val = pwrdm_set_mem_retst(p = powerdomains_omap[i], bank, PWRDM_POWER_RET); if (val == 0) printk(KERN_INFO "Memory RET State RET for" " %s Set\n", p->name); else if (val == -EINVAL) printk(KERN_INFO "RET State not supported for" " %s\n", p->name); else if (val == -EEXIST) printk(KERN_ERR "Memory Bank %d not present" " for %s\n", bank, p->name); else printk(KERN_ERR "MEM PWRST Set FAILED!!!" " with value %d\n", val); } } for (i = 1; powerdomains_omap[i] != NULL; i++) { for (bank = 0; bank < PWRDM_MAX_MEM_BANKS; bank++) { val = pwrdm_read_mem_pwrst(p = powerdomains_omap[i], bank); if (val == -EEXIST) printk(KERN_ERR "Memory Bank %d not present" " for %s\n", bank, p->name); else if (val == -EINVAL) printk(KERN_ERR "MEM PWRST Read FAILED!!!" " with value %d\n", val); else printk(KERN_INFO "MEM PWRST for bank %d of" " %s = %d\n", bank, p->name, val); } } }
/** * omap4_enter_lowpower: OMAP4 MPUSS Low Power Entry Function * The purpose of this function is to manage low power programming * of OMAP4 MPUSS subsystem * @cpu : CPU ID * @power_state: Low power state. * * MPUSS states for the context save: * save_state = * 0 - Nothing lost and no need to save: MPUSS INACTIVE * 1 - CPUx L1 and logic lost: MPUSS CSWR * 2 - CPUx L1 and logic lost + GIC lost: MPUSS OSWR * 3 - CPUx L1 and logic lost + GIC + L2 lost: DEVICE OFF */ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) { struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu); unsigned int save_state = 0, cpu_logic_state = PWRDM_POWER_RET; unsigned int wakeup_cpu; if (omap_rev() == OMAP4430_REV_ES1_0) return -ENXIO; switch (power_state) { case PWRDM_POWER_ON: case PWRDM_POWER_INACTIVE: save_state = 0; break; case PWRDM_POWER_OFF: cpu_logic_state = PWRDM_POWER_OFF; save_state = 1; break; case PWRDM_POWER_RET: if (IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE)) save_state = 0; break; default: /* * CPUx CSWR is invalid hardware state. Also CPUx OSWR * doesn't make much scense, since logic is lost and $L1 * needs to be cleaned because of coherency. This makes * CPUx OSWR equivalent to CPUX OFF and hence not supported */ WARN_ON(1); return -ENXIO; } pwrdm_pre_transition(NULL); /* * Check MPUSS next state and save interrupt controller if needed. * In MPUSS OSWR or device OFF, interrupt controller contest is lost. */ mpuss_clear_prev_logic_pwrst(); if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) && (pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF)) save_state = 2; cpu_clear_prev_logic_pwrst(cpu); pwrdm_set_next_pwrst(pm_info->pwrdm, power_state); pwrdm_set_logic_retst(pm_info->pwrdm, cpu_logic_state); set_cpu_wakeup_addr(cpu, virt_to_phys(omap_pm_ops.resume)); omap_pm_ops.scu_prepare(cpu, power_state); l2x0_pwrst_prepare(cpu, save_state); /* * Call low level function with targeted low power state. */ if (save_state) cpu_suspend(save_state, omap_pm_ops.finish_suspend); else omap_pm_ops.finish_suspend(save_state); if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD) && cpu) gic_dist_enable(); /* * Restore the CPUx power state to ON otherwise CPUx * power domain can transitions to programmed low power * state while doing WFI outside the low powe code. On * secure devices, CPUx does WFI which can result in * domain transition */ wakeup_cpu = smp_processor_id(); pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON); pwrdm_post_transition(NULL); return 0; }