#include "sdrc.h"
#include "pm.h"
+#include <asm/arch/powerdomain.h>
+#include <asm/arch/clockdomain.h>
+
/* These addrs are in assembly language code to be patched at runtime */
extern void *omap2_ocs_sdrc_power;
extern void *omap2_ocs_sdrc_dlla_ctrl;
static void (*omap2_sram_suspend)(void __iomem *dllctrl);
static void (*saved_idle)(void);
+static struct powerdomain *mpu_pwrdm;
+static struct powerdomain *core_pwrdm;
+
+static struct clockdomain *dsp_clkdm;
+static struct clockdomain *gfx_clkdm;
+
static struct clk *osc_ck, *emul_ck;
static int omap2_fclks_active(void)
prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
- /* Try to enter retention */
- prm_write_mod_reg((0x01 << OMAP_POWERSTATE_SHIFT) | OMAP_LOGICRETSTATE,
- MPU_MOD, PM_PWSTCTRL);
+ /*
+ * 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;
.valid = suspend_valid_only_mem,
};
+static int _pm_clkdm_enable_hwsup(struct clockdomain *clkdm)
+{
+ omap2_clkdm_allow_idle(clkdm);
+ return 0;
+}
+
static void __init prcm_setup_regs(void)
{
- u32 l;
+ int i, num_mem_banks;
+ struct powerdomain *pwrdm;
/* Enable autoidle */
__raw_writel(OMAP24XX_AUTOIDLE, OMAP24XX_PRCM_SYSCONFIG);
if (cpu_is_omap2430())
prm_write_mod_reg(0, OMAP2430_MDM_MOD, PM_WKDEP);
- l = prm_read_mod_reg(CORE_MOD, PM_PWSTCTRL);
- /* Enable retention for all memory blocks */
- l |= OMAP24XX_MEM3RETSTATE | OMAP24XX_MEM2RETSTATE |
- OMAP24XX_MEM1RETSTATE;
-
- /* Set power state to RETENTION */
- l &= ~OMAP_POWERSTATE_MASK;
- l |= 0x01 << OMAP_POWERSTATE_SHIFT;
- prm_write_mod_reg(l, CORE_MOD, PM_PWSTCTRL);
-
- prm_write_mod_reg((0x01 << OMAP_POWERSTATE_SHIFT) |
- OMAP_LOGICRETSTATE,
- MPU_MOD, PM_PWSTCTRL);
-
- /* Power down DSP and GFX */
- prm_write_mod_reg(OMAP24XX_FORCESTATE | (0x3 << OMAP_POWERSTATE_SHIFT),
- OMAP24XX_DSP_MOD, PM_PWSTCTRL);
- prm_write_mod_reg(OMAP24XX_FORCESTATE | (0x3 << OMAP_POWERSTATE_SHIFT),
- GFX_MOD, PM_PWSTCTRL);
-
- /* Enable clock auto control for all domains */
- cm_write_mod_reg(OMAP24XX_AUTOSTATE_MPU_MASK, MPU_MOD, CM_CLKSTCTRL);
- cm_write_mod_reg(OMAP24XX_AUTOSTATE_DSS_MASK |
- OMAP24XX_AUTOSTATE_L4_MASK |
- OMAP24XX_AUTOSTATE_L3_MASK,
- CORE_MOD, CM_CLKSTCTRL);
- cm_write_mod_reg(OMAP24XX_AUTOSTATE_GFX_MASK, GFX_MOD, CM_CLKSTCTRL);
- cm_write_mod_reg(OMAP2420_AUTOSTATE_IVA_MASK |
- OMAP24XX_AUTOSTATE_DSP_MASK,
- OMAP24XX_DSP_MOD, CM_CLKSTCTRL);
+ /*
+ * 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);
/* Enable clock autoidle for all domains */
cm_write_mod_reg(OMAP24XX_AUTO_CAM |
l = __raw_readl(OMAP24XX_PRCM_REVISION);
printk(KERN_INFO "PRCM revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
+ /* Look up important powerdomains, clockdomains */
+
+ mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
+ if (!mpu_pwrdm)
+ pr_err("PM: mpu_pwrdm not found\n");
+
+ core_pwrdm = pwrdm_lookup("core_pwrdm");
+ if (!core_pwrdm)
+ pr_err("PM: core_pwrdm not found\n");
+
+ dsp_clkdm = clkdm_lookup("dsp_clkdm");
+ if (!dsp_clkdm)
+ pr_err("PM: mpu_clkdm not found\n");
+
+ gfx_clkdm = clkdm_lookup("gfx_clkdm");
+ if (!gfx_clkdm)
+ pr_err("PM: gfx_clkdm not found\n");
+
+
osc_ck = clk_get(NULL, "osc_ck");
if (IS_ERR(osc_ck)) {
printk(KERN_ERR "could not get osc_ck\n");