010dc8af8f
Two problems exist in the current i.MX5 pm suspend/resume and idle functions. The first is the current i.MX5 suspend routine will call tzic_enable_wake(1) to set wake source, this will set all enabled irq as wake source rather than those wake capable. The second is i.MX5 idle will call mx5_cpu_lp_set() to prepare enter low power mode, but it forgets to call wfi instruction to enter this mode. To fix these two problems, using generic irq chip pm interface and modify function imx5_idle(). [Tested by Shawn Guo on imx51 babbage board. Tested by Hui Wang on imx51 pdk board.] Signed-off-by: Hui Wang <jason77.wang@gmail.com> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
83 lines
2.4 KiB
C
83 lines
2.4 KiB
C
/*
|
|
* Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
*/
|
|
|
|
/*
|
|
* The code contained herein is licensed under the GNU General Public
|
|
* License. You may obtain a copy of the GNU General Public License
|
|
* Version 2 or later at the following locations:
|
|
*
|
|
* http://www.opensource.org/licenses/gpl-license.html
|
|
* http://www.gnu.org/copyleft/gpl.html
|
|
*/
|
|
#include <linux/platform_device.h>
|
|
#include <linux/io.h>
|
|
#include <mach/hardware.h>
|
|
#include <mach/common.h>
|
|
#include "crm_regs.h"
|
|
|
|
/* set cpu low power mode before WFI instruction. This function is called
|
|
* mx5 because it can be used for mx50, mx51, and mx53.*/
|
|
void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
|
|
{
|
|
u32 plat_lpc, arm_srpgcr, ccm_clpcr;
|
|
u32 empgc0, empgc1;
|
|
int stop_mode = 0;
|
|
|
|
/* always allow platform to issue a deep sleep mode request */
|
|
plat_lpc = __raw_readl(MXC_CORTEXA8_PLAT_LPC) &
|
|
~(MXC_CORTEXA8_PLAT_LPC_DSM);
|
|
ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK);
|
|
arm_srpgcr = __raw_readl(MXC_SRPG_ARM_SRPGCR) & ~(MXC_SRPGCR_PCR);
|
|
empgc0 = __raw_readl(MXC_SRPG_EMPGC0_SRPGCR) & ~(MXC_SRPGCR_PCR);
|
|
empgc1 = __raw_readl(MXC_SRPG_EMPGC1_SRPGCR) & ~(MXC_SRPGCR_PCR);
|
|
|
|
switch (mode) {
|
|
case WAIT_CLOCKED:
|
|
break;
|
|
case WAIT_UNCLOCKED:
|
|
ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
|
|
break;
|
|
case WAIT_UNCLOCKED_POWER_OFF:
|
|
case STOP_POWER_OFF:
|
|
plat_lpc |= MXC_CORTEXA8_PLAT_LPC_DSM
|
|
| MXC_CORTEXA8_PLAT_LPC_DBG_DSM;
|
|
if (mode == WAIT_UNCLOCKED_POWER_OFF) {
|
|
ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
|
|
ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY;
|
|
ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS;
|
|
stop_mode = 0;
|
|
} else {
|
|
ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
|
|
ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET;
|
|
ccm_clpcr |= MXC_CCM_CLPCR_VSTBY;
|
|
ccm_clpcr |= MXC_CCM_CLPCR_SBYOS;
|
|
stop_mode = 1;
|
|
}
|
|
arm_srpgcr |= MXC_SRPGCR_PCR;
|
|
break;
|
|
case STOP_POWER_ON:
|
|
ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
|
|
break;
|
|
default:
|
|
printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode);
|
|
return;
|
|
}
|
|
|
|
__raw_writel(plat_lpc, MXC_CORTEXA8_PLAT_LPC);
|
|
__raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
|
|
__raw_writel(arm_srpgcr, MXC_SRPG_ARM_SRPGCR);
|
|
|
|
/* Enable NEON SRPG for all but MX50TO1.0. */
|
|
if (mx50_revision() != IMX_CHIP_REVISION_1_0)
|
|
__raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR);
|
|
|
|
if (stop_mode) {
|
|
empgc0 |= MXC_SRPGCR_PCR;
|
|
empgc1 |= MXC_SRPGCR_PCR;
|
|
|
|
__raw_writel(empgc0, MXC_SRPG_EMPGC0_SRPGCR);
|
|
__raw_writel(empgc1, MXC_SRPG_EMPGC1_SRPGCR);
|
|
}
|
|
}
|