summaryrefslogtreecommitdiff
path: root/arch/arm/mach-mx5/system.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-mx5/system.c')
-rwxr-xr-xarch/arm/mach-mx5/system.c113
1 files changed, 99 insertions, 14 deletions
diff --git a/arch/arm/mach-mx5/system.c b/arch/arm/mach-mx5/system.c
index 70667446cff3..8ecf04261d57 100755
--- a/arch/arm/mach-mx5/system.c
+++ b/arch/arm/mach-mx5/system.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -26,6 +26,7 @@
#include <mach/common.h>
#include <mach/hardware.h>
#include <mach/clock.h>
+#include <mach/devices-common.h>
#include <asm/proc-fns.h>
#include <asm/system.h>
#include "crm_regs.h"
@@ -47,34 +48,53 @@ extern int dvfs_core_is_active;
extern void __iomem *ccm_base;
extern void __iomem *databahn_base;
extern int low_bus_freq_mode;
-extern void (*wait_in_iram)(void *ccm_addr, void *databahn_addr);
+extern void (*wait_in_iram)(void *ccm_addr, void *databahn_addr,
+ u32 sys_clk_count);
extern void mx50_wait(u32 ccm_base, u32 databahn_addr);
extern void stop_dvfs(void);
extern void *wait_in_iram_base;
extern void __iomem *apll_base;
+extern void __iomem *arm_plat_base;
+extern void (*suspend_in_iram)(void *param1, void *param2, void* param3);
+extern void __iomem *suspend_param1;
+
+#ifdef CONFIG_MXC_REBOOT_ANDROID_CMD
+#ifdef CONFIG_SOC_IMX50
+static resource_size_t srtc_iobase = MX50_SRTC_BASE_ADDR;
+#endif
+#ifdef CONFIG_SOC_IMX51
+static resource_size_t srtc_iobase = MX51_SRTC_BASE_ADDR;
+#endif
+#ifdef CONFIG_SOC_IMX53
+static resource_size_t srtc_iobase = MX53_SRTC_BASE_ADDR;
+#endif
+#endif
static struct clk *gpc_dvfs_clk;
-static struct regulator *vpll;
static struct clk *pll1_sw_clk;
static struct clk *osc;
static struct clk *pll1_main_clk;
static struct clk *ddr_clk ;
-static int dvfs_core_paused;
+static struct clk *sys_clk ;
/* set cpu low power mode before WFI instruction */
void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
{
u32 plat_lpc, arm_srpgcr, ccm_clpcr;
- u32 empgc0, empgc1;
+ u32 empgc0 = 0, empgc1 = 0;
int stop_mode = 0;
/* always allow platform to issue a deep sleep mode request */
- plat_lpc = __raw_readl(MXC_CORTEXA8_PLAT_LPC) &
+ plat_lpc = __raw_readl(arm_plat_base + 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);
+ if (!cpu_is_mx53()) {
+ 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:
@@ -103,7 +123,7 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
if (tzic_enable_wake(1) != 0)
return;
break;
- case STOP_POWER_ON:
+ case STOP_XTAL_ON:
ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
break;
default:
@@ -111,7 +131,7 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
return;
}
- __raw_writel(plat_lpc, MXC_CORTEXA8_PLAT_LPC);
+ __raw_writel(plat_lpc, arm_plat_base + MXC_CORTEXA8_PLAT_LPC);
__raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
__raw_writel(arm_srpgcr, MXC_SRPG_ARM_SRPGCR);
@@ -119,7 +139,7 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
if (mx50_revision() != IMX_CHIP_REVISION_1_0)
__raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR);
- if (stop_mode) {
+ if (stop_mode && !cpu_is_mx53()) {
empgc0 |= MXC_SRPGCR_PCR;
empgc1 |= MXC_SRPGCR_PCR;
@@ -149,6 +169,9 @@ void arch_idle(void)
mxc_cpu_lp_set(arch_idle_mode);
if (cpu_is_mx50() && (clk_get_usecount(ddr_clk) == 0)) {
+ if (sys_clk == NULL)
+ sys_clk = clk_get(NULL, "sys_clk");
+
memcpy(wait_in_iram_base, mx50_wait, SZ_4K);
wait_in_iram = (void *)wait_in_iram_base;
if (low_bus_freq_mode) {
@@ -178,7 +201,8 @@ void arch_idle(void)
cpu_podf = __raw_readl(MXC_CCM_CACRR);
__raw_writel(0x01, MXC_CCM_CACRR);
- wait_in_iram(ccm_base, databahn_base);
+ wait_in_iram(ccm_base, databahn_base,
+ clk_get_usecount(sys_clk));
/* Set the ARM-POD divider back
* to the original.
@@ -186,7 +210,11 @@ void arch_idle(void)
__raw_writel(cpu_podf, MXC_CCM_CACRR);
clk_set_parent(pll1_sw_clk, pll1_main_clk);
} else
- wait_in_iram(ccm_base, databahn_base);
+ wait_in_iram(ccm_base, databahn_base,
+ clk_get_usecount(sys_clk));
+ } else if (cpu_is_mx53() && (clk_get_usecount(ddr_clk) == 0)
+ && low_bus_freq_mode) {
+ suspend_in_iram(suspend_param1, NULL, NULL);
} else
cpu_do_idle();
clk_disable(gpc_dvfs_clk);
@@ -272,7 +300,7 @@ static int __mxs_reset_block(void __iomem *hwreg, int just_enable)
int mxs_reset_block(void __iomem *hwreg, int just_enable)
{
int try = 10;
- int r;
+ int r = 0;
while (try--) {
r = __mxs_reset_block(hwreg, just_enable);
@@ -282,3 +310,60 @@ int mxs_reset_block(void __iomem *hwreg, int just_enable)
}
return r;
}
+
+#ifdef CONFIG_MXC_REBOOT_ANDROID_CMD
+/* This function will set a bits on SRTC_LPGR[27-26] bits to enter
+ * special boot mode. These bits will not clear by watchdog reset, so
+ * it can be checked by bootloader to choose enter different mode.
+ * Bit 27 = Recovery mode
+ * Bit 26 = Fastboot mode
+ */
+
+#define ANDROID_RECOVERY_BOOT (1 << 27)
+#define ANDROID_FASTBOOT_BOOT (1 << 26)
+#define SRTC_LPGR 0x1C
+
+void do_switch_recovery(void)
+{
+ u32 reg;
+ void __iomem *srtc_base;
+ struct clk *srtc_clk;
+
+ srtc_clk = clk_get_sys("mxc_rtc.0", NULL);
+ if (IS_ERR_OR_NULL(srtc_clk))
+ printk(KERN_WARNING "Error getting mxc_rtc clk\n");
+ else
+ clk_enable(srtc_clk);
+
+ srtc_base = ioremap(srtc_iobase, 40);
+ if (srtc_base) {
+ reg = __raw_readl(srtc_base + SRTC_LPGR);
+ reg |= ANDROID_RECOVERY_BOOT;
+ __raw_writel(reg, srtc_base + SRTC_LPGR);
+ iounmap(srtc_base);
+ } else
+ printk(KERN_WARNING "Failed to ioremap srtc iobase\n");
+}
+
+void do_switch_fastboot(void)
+{
+ u32 reg;
+ void __iomem *srtc_base;
+ struct clk *srtc_clk;
+
+ srtc_clk = clk_get_sys("mxc_rtc.0", NULL);
+ if (IS_ERR_OR_NULL(srtc_clk))
+ printk(KERN_WARNING "Error getting mxc_rtc clk\n");
+ else
+ clk_enable(srtc_clk);
+
+ srtc_base = ioremap(srtc_iobase, 40);
+ if (srtc_base) {
+ reg = __raw_readl(srtc_base + SRTC_LPGR);
+ reg |= ANDROID_FASTBOOT_BOOT;
+ __raw_writel(reg, srtc_base + SRTC_LPGR);
+ iounmap(srtc_base);
+ } else
+ printk(KERN_WARNING "Failed to ioremap srtc iobase\n");
+}
+#endif