Esempio n. 1
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);
}
Esempio n. 2
0
static int am33xx_pm_suspend(void)
{
	int state, ret = 0;

	struct omap_hwmod *cpgmac_oh, *gpmc_oh, *usb_oh;

	cpgmac_oh	= omap_hwmod_lookup("cpgmac0");
	usb_oh		= omap_hwmod_lookup("usb_otg_hs");
	gpmc_oh		= omap_hwmod_lookup("gpmc");

	omap_hwmod_enable(cpgmac_oh);
	omap_hwmod_enable(usb_oh);
	omap_hwmod_enable(gpmc_oh);

	omap_hwmod_idle(cpgmac_oh);
	omap_hwmod_idle(usb_oh);
	omap_hwmod_idle(gpmc_oh);

	if (gfx_l3_clkdm && gfx_l4ls_clkdm) {
		clkdm_sleep(gfx_l3_clkdm);
		clkdm_sleep(gfx_l4ls_clkdm);
	}

	/* Try to put GFX to sleep */
	if (gfx_pwrdm)
		pwrdm_set_next_pwrst(gfx_pwrdm, PWRDM_POWER_OFF);
	else
		pr_err("Could not program GFX to low power state\n");

	writel(0x0, AM33XX_CM_MPU_MPU_CLKCTRL);

	ret = cpu_suspend(0, am33xx_do_sram_idle);

	writel(0x2, AM33XX_CM_MPU_MPU_CLKCTRL);

	if (gfx_pwrdm) {
		state = pwrdm_read_pwrst(gfx_pwrdm);
		if (state != PWRDM_POWER_OFF)
			pr_err("GFX domain did not transition to low power state\n");
		else
			pr_info("GFX domain entered low power state\n");
	}

	/* XXX: Why do we need to wakeup the clockdomains? */
	if(gfx_l3_clkdm && gfx_l4ls_clkdm) {
		clkdm_wakeup(gfx_l3_clkdm);
		clkdm_wakeup(gfx_l4ls_clkdm);
	}

	core_suspend_stat = ret;

	return ret;
}
Esempio n. 3
0
/*
 * Initiate sleep transition for other clockdomains, if
 * they are not used
 */
static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
{
	if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
			atomic_read(&clkdm->usecount) == 0)
		clkdm_sleep(clkdm);
	return 0;
}
Esempio n. 4
0
File: pm.c Progetto: ivdok/linux
int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
{
	if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
		clkdm_allow_idle(clkdm);
	else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
		 atomic_read(&clkdm->usecount) == 0)
		clkdm_sleep(clkdm);
	return 0;
}
Esempio n. 5
0
/*
 * This sets pwrdm state (other than mpu & core. Currently only ON &
 * RET are supported.
 */
int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
{
	u32 cur_state;
	int sleep_switch = 0;
	int ret = 0;

	if (pwrdm == NULL || IS_ERR(pwrdm))
		return -EINVAL;

	while (!(pwrdm->pwrsts & (1 << state))) {
		if (state == PWRDM_POWER_OFF)
			return ret;
		state--;
	}

	cur_state = pwrdm_read_next_pwrst(pwrdm);
	if (cur_state == state)
		return ret;

	if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) {
		if ((pwrdm_read_pwrst(pwrdm) > state) &&
			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
			sleep_switch = LOWPOWERSTATE_SWITCH;
		} else {
			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
			pwrdm_wait_transition(pwrdm);
			sleep_switch = FORCEWAKEUP_SWITCH;
		}
	}

	ret = pwrdm_set_next_pwrst(pwrdm, state);
	if (ret) {
		printk(KERN_ERR "Unable to set state of powerdomain: %s\n",
		       pwrdm->name);
		goto err;
	}

	switch (sleep_switch) {
	case FORCEWAKEUP_SWITCH:
		if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO)
			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
		else
			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
		break;
	case LOWPOWERSTATE_SWITCH:
		pwrdm_set_lowpwrstchange(pwrdm);
		break;
	default:
		return ret;
	}

	pwrdm_wait_transition(pwrdm);
	pwrdm_state_switch(pwrdm);
err:
	return ret;
}
Esempio n. 6
0
/*
 * This sets pwrdm state (other than mpu & core. Currently only ON &
 * RET are supported.
 */
int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
{
	u32 cur_state;
	int sleep_switch = -1;
	int ret = 0;
	int hwsup = 0;

	if (pwrdm == NULL || IS_ERR(pwrdm))
		return -EINVAL;

	while (!(pwrdm->pwrsts & (1 << state))) {
		if (state == PWRDM_POWER_OFF)
			return ret;
		state--;
	}

	cur_state = pwrdm_read_next_pwrst(pwrdm);
	if (cur_state == state)
		return ret;

	if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) {
		if ((pwrdm_read_pwrst(pwrdm) > state) &&
			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
			sleep_switch = LOWPOWERSTATE_SWITCH;
		} else {
			hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
			sleep_switch = FORCEWAKEUP_SWITCH;
		}
	}

	ret = pwrdm_set_next_pwrst(pwrdm, state);
	if (ret) {
		pr_err("%s: unable to set state of powerdomain: %s\n",
		       __func__, pwrdm->name);
		goto err;
	}

	switch (sleep_switch) {
	case FORCEWAKEUP_SWITCH:
		if (hwsup)
			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
		else
			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
		break;
	case LOWPOWERSTATE_SWITCH:
		pwrdm_set_lowpwrstchange(pwrdm);
		break;
	default:
		return ret;
	}

	pwrdm_state_switch(pwrdm);
err:
	return ret;
}
Esempio n. 7
0
static int omap4_clkdm_clk_disable(struct clockdomain *clkdm)
{
	bool hwsup = false;

	hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
					clkdm->cm_inst, clkdm->clkdm_offs);

	if (!hwsup)
		clkdm_sleep(clkdm);

	return 0;
}
Esempio n. 8
0
File: pm.c Progetto: ivdok/linux
/*
 * This sets pwrdm state (other than mpu & core. Currently only ON &
 * RET are supported.
 */
int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
{
	u8 curr_pwrst, next_pwrst;
	int sleep_switch = -1, ret = 0, hwsup = 0;

	if (!pwrdm || IS_ERR(pwrdm))
		return -EINVAL;

	while (!(pwrdm->pwrsts & (1 << pwrst))) {
		if (pwrst == PWRDM_POWER_OFF)
			return ret;
		pwrst--;
	}

	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
	if (next_pwrst == pwrst)
		return ret;

	curr_pwrst = pwrdm_read_pwrst(pwrdm);
	if (curr_pwrst < PWRDM_POWER_ON) {
		if ((curr_pwrst > pwrst) &&
			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
			sleep_switch = LOWPOWERSTATE_SWITCH;
		} else {
			hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
			sleep_switch = FORCEWAKEUP_SWITCH;
		}
	}

	ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
	if (ret)
		pr_err("%s: unable to set power state of powerdomain: %s\n",
		       __func__, pwrdm->name);

	switch (sleep_switch) {
	case FORCEWAKEUP_SWITCH:
		if (hwsup)
			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
		else
			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
		break;
	case LOWPOWERSTATE_SWITCH:
		pwrdm_set_lowpwrstchange(pwrdm);
		pwrdm_wait_transition(pwrdm);
		pwrdm_state_switch(pwrdm);
		break;
	}

	return ret;
}
Esempio n. 9
0
static void am33xx_post_suspend(unsigned int state)
{
	int status = 0;

	status = pwrdm_read_pwrst(gfx_pwrdm);
	if (status != PWRDM_POWER_OFF)
		pr_err("GFX domain did not transition\n");

	/*
	 * BUG: GFX_L4LS clock domain needs to be woken up to
	 * ensure thet L4LS clock domain does not get stuck in
	 * transition. If that happens L3 module does not get
	 * disabled, thereby leading to PER power domain
	 * transition failing
	 */
	clkdm_wakeup(gfx_l4ls_clkdm);
	clkdm_sleep(gfx_l4ls_clkdm);
}
static int omap2_clkdm_clk_disable(struct clockdomain *clkdm)
{
	bool hwsup = false;

	if (!clkdm->clktrctrl_mask)
		return 0;

	hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
				clkdm->clktrctrl_mask);

	if (hwsup) {
		/* Disable HW transitions when we are changing deps */
		_disable_hwsup(clkdm);
		_clkdm_del_autodeps(clkdm);
		_enable_hwsup(clkdm);
	} else {
		clkdm_sleep(clkdm);
	}

	return 0;
}
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);
}
Esempio n. 12
0
static int am33xx_pm_suspend(void)
{
	int state, ret = 0;

	struct omap_hwmod *gpmc_oh, *usb_oh, *gpio1_oh;

	usb_oh		= omap_hwmod_lookup("usb_otg_hs");
	gpmc_oh		= omap_hwmod_lookup("gpmc");
	gpio1_oh	= omap_hwmod_lookup("gpio1");	/* WKUP domain GPIO */

	omap_hwmod_enable(usb_oh);
	omap_hwmod_enable(gpmc_oh);

	/*
	 * Keep USB module enabled during standby
	 * to enable USB remote wakeup
	 * Note: This will result in hard-coding USB state
	 * during standby
	 */
	if (suspend_state != PM_SUSPEND_STANDBY)
		omap_hwmod_idle(usb_oh);

	omap_hwmod_idle(gpmc_oh);

	/*
	 * Disable the GPIO module. This ensure that
	 * only sWAKEUP interrupts to Cortex-M3 get generated
	 *
	 * XXX: EVM_SK uses a GPIO0 pin for VTP control
	 * in suspend and hence we can't do this for EVM_SK
	 * alone. The side-effect of this is that GPIO wakeup
	 * might have issues. Refer to commit 672639b for the
	 * details
	 */
	/*
	 * Keep GPIO0 module enabled during standby to
	 * support wakeup via GPIO0 keys.
	 */
	if ((suspend_cfg_param_list[EVM_ID] != EVM_SK) &&
			(suspend_state != PM_SUSPEND_STANDBY))
		omap_hwmod_idle(gpio1_oh);
	/*
	 * Update Suspend_State value to be used in sleep33xx.S to keep
	 * GPIO0 module enabled during standby for EVM-SK
	 */
	if (suspend_state == PM_SUSPEND_STANDBY)
		suspend_cfg_param_list[SUSPEND_STATE] = PM_STANDBY;
	else
		suspend_cfg_param_list[SUSPEND_STATE] = PM_DS0;

	/*
	 * Keep Touchscreen module enabled during standby
	 * to enable wakeup from standby.
	 */
	if (suspend_state == PM_SUSPEND_STANDBY)
		writel(0x2, AM33XX_CM_WKUP_ADC_TSC_CLKCTRL);

	if (gfx_l3_clkdm && gfx_l4ls_clkdm) {
		clkdm_sleep(gfx_l3_clkdm);
		clkdm_sleep(gfx_l4ls_clkdm);
	}

	/* Try to put GFX to sleep */
	if (gfx_pwrdm)
		pwrdm_set_next_pwrst(gfx_pwrdm, PWRDM_POWER_OFF);
	else
		pr_err("Could not program GFX to low power state\n");

	omap3_intc_suspend();

	writel(0x0, AM33XX_CM_MPU_MPU_CLKCTRL);

	ret = cpu_suspend(0, am33xx_do_sram_idle);

	writel(0x2, AM33XX_CM_MPU_MPU_CLKCTRL);

	if (gfx_pwrdm) {
		state = pwrdm_read_pwrst(gfx_pwrdm);
		if (state != PWRDM_POWER_OFF)
			pr_err("GFX domain did not transition to low power state\n");
		else
			pr_info("GFX domain entered low power state\n");
	}

	/* XXX: Why do we need to wakeup the clockdomains? */
	if(gfx_l3_clkdm && gfx_l4ls_clkdm) {
		clkdm_wakeup(gfx_l3_clkdm);
		clkdm_wakeup(gfx_l4ls_clkdm);
	}

	/*
	 * Touchscreen module was enabled during standby
	 * Disable it here.
	 */
	if (suspend_state == PM_SUSPEND_STANDBY)
		writel(0x0, AM33XX_CM_WKUP_ADC_TSC_CLKCTRL);

	/*
	 * Put USB module to idle on resume from standby
	 */
	if (suspend_state == PM_SUSPEND_STANDBY)
		omap_hwmod_idle(usb_oh);

	ret = am33xx_verify_lp_state(ret);

	/*
	 * Enable the GPIO module. Once the driver is
	 * fully adapted to runtime PM this will go away
	 */
	/*
	 * During standby, GPIO was not disabled. Hence no
	 * need to enable it here.
	 */
	if ((suspend_cfg_param_list[EVM_ID] != EVM_SK) &&
			(suspend_state != PM_SUSPEND_STANDBY))
		omap_hwmod_enable(gpio1_oh);

	return ret;
}