diff options
Diffstat (limited to 'arch/arm/mach-imx/system.c')
-rw-r--r-- | arch/arm/mach-imx/system.c | 62 |
1 files changed, 61 insertions, 1 deletions
diff --git a/arch/arm/mach-imx/system.c b/arch/arm/mach-imx/system.c index df3d1ff0c288..b3f48f032a26 100644 --- a/arch/arm/mach-imx/system.c +++ b/arch/arm/mach-imx/system.c @@ -1,7 +1,7 @@ /* * Copyright (C) 1999 ARM Limited * Copyright (C) 2000 Deep Blue Solutions Ltd - * Copyright (C) 2006-2013 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2006-2014 Freescale Semiconductor, Inc. All Rights Reserved. * Copyright 2008 Juergen Beisert, kernel@pengutronix.de * Copyright 2009 Ilya Yanok, Emcraft Systems Ltd, yanok@emcraft.com * @@ -31,11 +31,69 @@ #include "common.h" #include "hardware.h" +#include "mx6.h" static void __iomem *wdog_base; static struct clk *wdog_clk; static u32 wdog_source = 1; /* use WDOG1 default */ +#ifdef CONFIG_MXC_REBOOT_ANDROID_CMD +/* This function will set a bit on SNVS_LPGPR[7-8] 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.*/ + +#define ANDROID_RECOVERY_BOOT (1 << 7) +#define ANDROID_FASTBOOT_BOOT (1 << 8) + +#define AIPS1_ARB_BASE_ADDR 0x02000000 +#define ATZ1_BASE_ADDR AIPS1_ARB_BASE_ADDR +#define AIPS1_OFF_BASE_ADDR (ATZ1_BASE_ADDR + 0x80000) +#define MX6_SNVS_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x4C000) +#define SNVS_LPGPR 0x68 +#define SNVS_SIZE (1024*16) +void do_switch_recovery(void) +{ + u32 reg; + u32 addr; + addr = ioremap(MX6_SNVS_BASE_ADDR, SNVS_SIZE); + if (!addr) { + pr_warn("SNVS ioremap failed!\n"); + return; + } + reg = __raw_readl(addr + SNVS_LPGPR); + reg |= ANDROID_RECOVERY_BOOT; + __raw_writel(reg, (addr + SNVS_LPGPR)); + + iounmap(addr); +} + +void do_switch_fastboot(void) +{ + u32 reg; + u32 addr; + + addr = ioremap(MX6_SNVS_BASE_ADDR, SNVS_SIZE); + if (!addr) { + pr_warn("SNVS ioremap failed!\n"); + return; + } + + reg = __raw_readl(addr + SNVS_LPGPR); + reg |= ANDROID_FASTBOOT_BOOT; + __raw_writel(reg, addr + SNVS_LPGPR); + + iounmap(addr); +} +#endif +static void arch_reset_special_mode(char mode, const char *cmd) +{ +#ifdef CONFIG_MXC_REBOOT_ANDROID_CMD + if (strcmp(cmd, "recovery") == 0) + do_switch_recovery(); + else if (strcmp(cmd, "fastboot") == 0) + do_switch_fastboot(); +#endif +} /* * Reset the system. It is called by machine_restart(). */ @@ -43,6 +101,8 @@ void mxc_restart(char mode, const char *cmd) { unsigned int wcr_enable; + arch_reset_special_mode(mode, cmd); + if (wdog_clk) clk_enable(wdog_clk); |