From 0adf882b6894cd150392400e9642787cf691016a Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Mon, 21 Mar 2011 16:30:37 -0500 Subject: ARM: mx51: Implement code to allow mx51 to enter WFI Implement code for MX51 that allows the SoC to enter WFI when arch_idle is called. This patch is also necessary for correctly suspending the system. Signed-off-by: Dinh Nguyen Signed-off-by: Sascha Hauer --- arch/arm/mach-mx5/Makefile | 2 +- arch/arm/mach-mx5/system.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-mx5/system.c (limited to 'arch/arm/mach-mx5') diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile index 4f63048..0b9338c 100644 --- a/arch/arm/mach-mx5/Makefile +++ b/arch/arm/mach-mx5/Makefile @@ -3,7 +3,7 @@ # # Object file lists. -obj-y := cpu.o mm.o clock-mx51-mx53.o devices.o ehci.o +obj-y := cpu.o mm.o clock-mx51-mx53.o devices.o ehci.o system.o obj-$(CONFIG_SOC_IMX50) += mm-mx50.o obj-$(CONFIG_CPU_FREQ_IMX) += cpu_op-mx51.o diff --git a/arch/arm/mach-mx5/system.c b/arch/arm/mach-mx5/system.c new file mode 100644 index 0000000..76ae8dc --- /dev/null +++ b/arch/arm/mach-mx5/system.c @@ -0,0 +1,84 @@ +/* + * 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 +#include +#include +#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; + + if (tzic_enable_wake(1) != 0) + return; + 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); + } +} -- cgit v1.1