aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/boot/dts/imx6q.dtsi1
-rw-r--r--arch/arm/include/asm/mach/arch.h1
-rw-r--r--arch/arm/include/asm/system.h1
-rw-r--r--arch/arm/kernel/machine_kexec.c4
-rw-r--r--arch/arm/kernel/process.c81
-rw-r--r--arch/arm/kernel/setup.c3
-rw-r--r--arch/arm/lib/Makefile3
-rw-r--r--arch/arm/lib/call_with_stack.S44
-rw-r--r--arch/arm/mach-clps711x/include/mach/system.h2
-rw-r--r--arch/arm/mach-ebsa110/include/mach/system.h2
-rw-r--r--arch/arm/mach-footbridge/include/mach/system.h2
-rw-r--r--arch/arm/mach-imx/Makefile2
-rw-r--r--arch/arm/mach-imx/clock-imx6q.c39
-rw-r--r--arch/arm/mach-imx/gpc.c21
-rw-r--r--arch/arm/mach-imx/head-v7.S1
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c34
-rw-r--r--arch/arm/mach-imx/pm-imx6q.c128
-rw-r--r--arch/arm/mach-imx/src.c23
-rw-r--r--arch/arm/mach-imx/suspend-imx6q.S308
-rw-r--r--arch/arm/mach-iop32x/include/mach/system.h2
-rw-r--r--arch/arm/mach-iop33x/include/mach/system.h2
-rw-r--r--arch/arm/mach-ixp4xx/include/mach/system.h2
-rw-r--r--arch/arm/mach-ks8695/include/mach/system.h2
-rw-r--r--arch/arm/mach-mmp/include/mach/system.h4
-rw-r--r--arch/arm/mach-mxs/system.c2
-rw-r--r--arch/arm/mach-pnx4008/include/mach/system.h2
-rw-r--r--arch/arm/mach-pxa/reset.c2
-rw-r--r--arch/arm/mach-rpc/include/mach/system.h2
-rw-r--r--arch/arm/mach-s3c2410/include/mach/system-reset.h4
-rw-r--r--arch/arm/mach-s3c64xx/include/mach/system.h2
-rw-r--r--arch/arm/mach-sa1100/include/mach/system.h2
-rw-r--r--arch/arm/mach-shmobile/include/mach/system.h2
-rw-r--r--arch/arm/mach-w90x900/include/mach/system.h2
-rw-r--r--arch/arm/mm/idmap.c2
-rw-r--r--arch/arm/mm/nommu.c2
-rw-r--r--arch/arm/plat-mxc/include/mach/common.h3
-rw-r--r--arch/arm/plat-mxc/include/mach/mx6q.h6
-rw-r--r--arch/arm/plat-mxc/system.c2
-rw-r--r--arch/arm/plat-spear/include/plat/system.h2
-rw-r--r--drivers/tty/serial/imx.c15
40 files changed, 696 insertions, 68 deletions
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index 263e8f3664b..2b255ae12b8 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -386,6 +386,7 @@
};
iomuxc@020e0000 {
+ compatible = "fsl,imx6q-iomuxc";
reg = <0x020e0000 0x4000>;
};
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index 2b0efc3104a..61ae6bb42c5 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -46,6 +46,7 @@ struct machine_desc {
#ifdef CONFIG_MULTI_IRQ_HANDLER
void (*handle_irq)(struct pt_regs *);
#endif
+ void (*restart)(char, const char *);
};
/*
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index 984014b9264..fe7de7571ba 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -101,6 +101,7 @@ extern int __pure cpu_architecture(void);
extern void cpu_init(void);
void arm_machine_restart(char mode, const char *cmd);
+void soft_restart(unsigned long);
extern void (*arm_pm_restart)(char str, const char *cmd);
#define UDBG_UNDEFINED (1 << 0)
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index e59bbd496c3..29620b632ed 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -16,7 +16,7 @@
extern const unsigned char relocate_new_kernel[];
extern const unsigned int relocate_new_kernel_size;
-extern void setup_mm_for_reboot(char mode);
+extern void setup_mm_for_reboot(void);
extern unsigned long kexec_start_address;
extern unsigned long kexec_indirection_page;
@@ -113,7 +113,7 @@ void machine_kexec(struct kimage *image)
kexec_reinit();
local_irq_disable();
local_fiq_disable();
- setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/
+ setup_mm_for_reboot();
flush_cache_all();
outer_flush_all();
outer_disable();
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 3d0c6fb74ae..423bb201945 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -57,7 +57,7 @@ static const char *isa_modes[] = {
"ARM" , "Thumb" , "Jazelle", "ThumbEE"
};
-extern void setup_mm_for_reboot(char mode);
+extern void setup_mm_for_reboot(void);
static volatile int hlt_counter;
@@ -92,18 +92,24 @@ static int __init hlt_setup(char *__unused)
__setup("nohlt", nohlt_setup);
__setup("hlt", hlt_setup);
-void arm_machine_restart(char mode, const char *cmd)
+extern void call_with_stack(void (*fn)(void *), void *arg, void *sp);
+typedef void (*phys_reset_t)(unsigned long);
+
+/*
+ * A temporary stack to use for CPU reset. This is static so that we
+ * don't clobber it with the identity mapping. When running with this
+ * stack, any references to the current task *will not work* so you
+ * should really do as little as possible before jumping to your reset
+ * code.
+ */
+static u64 soft_restart_stack[16];
+
+static void __soft_restart(void *addr)
{
- /* Disable interrupts first */
- local_irq_disable();
- local_fiq_disable();
+ phys_reset_t phys_reset;
- /*
- * Tell the mm system that we are going to reboot -
- * we may need it to insert some 1:1 mappings so that
- * soft boot works.
- */
- setup_mm_for_reboot(mode);
+ /* Take out a flat memory mapping. */
+ setup_mm_for_reboot();
/* Clean and invalidate caches */
flush_cache_all();
@@ -114,18 +120,41 @@ void arm_machine_restart(char mode, const char *cmd)
/* Push out any further dirty data, and ensure cache is empty */
flush_cache_all();
- /*
- * Now call the architecture specific reboot code.
- */
- arch_reset(mode, cmd);
+ /* Switch to the identity mapping. */
+ phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset);
+ phys_reset((unsigned long)addr);
- /*
- * Whoops - the architecture was unable to reboot.
- * Tell the user!
- */
- mdelay(1000);
- printk("Reboot failed -- System halted\n");
- while (1);
+ /* Should never get here. */
+ BUG();
+}
+
+void soft_restart(unsigned long addr)
+{
+ u64 *stack = soft_restart_stack + ARRAY_SIZE(soft_restart_stack);
+
+ /* Disable interrupts first */
+ local_irq_disable();
+ local_fiq_disable();
+
+ /* Disable the L2 if we're the last man standing. */
+ if (num_online_cpus() == 1)
+ outer_disable();
+
+ /* Change to the new stack and continue with the reset. */
+ call_with_stack(__soft_restart, (void *)addr, (void *)stack);
+
+ /* Should never get here. */
+ BUG();
+}
+
+void arm_machine_restart(char mode, const char *cmd)
+{
+ /* Disable interrupts first */
+ local_irq_disable();
+ local_fiq_disable();
+
+ /* Call the architecture specific reboot code. */
+ arch_reset(mode, cmd);
}
/*
@@ -253,7 +282,15 @@ void machine_power_off(void)
void machine_restart(char *cmd)
{
machine_shutdown();
+
arm_pm_restart(reboot_mode, cmd);
+
+ /* Give a grace period for failure to restart of 1s */
+ mdelay(1000);
+
+ /* Whoops - the platform was unable to reboot. Tell the user! */
+ printk("Reboot failed -- System halted\n");
+ while (1);
}
void __show_regs(struct pt_regs *regs)
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 8fc2c8fcbdc..d662dca774d 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -928,6 +928,9 @@ void __init setup_arch(char **cmdline_p)
paging_init(mdesc);
request_standard_resources(mdesc);
+ if (mdesc->restart)
+ arm_pm_restart = mdesc->restart;
+
unflatten_device_tree();
#ifdef CONFIG_SMP
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index cf73a7f742d..0ade0acc1ed 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -13,7 +13,8 @@ lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \
testchangebit.o testclearbit.o testsetbit.o \
ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
ucmpdi2.o lib1funcs.o div64.o \
- io-readsb.o io-writesb.o io-readsl.o io-writesl.o
+ io-readsb.o io-writesb.o io-readsl.o io-writesl.o \
+ call_with_stack.o
mmu-y := clear_user.o copy_page.o getuser.o putuser.o
diff --git a/arch/arm/lib/call_with_stack.S b/arch/arm/lib/call_with_stack.S
new file mode 100644
index 00000000000..916c80f13ae
--- /dev/null
+++ b/arch/arm/lib/call_with_stack.S
@@ -0,0 +1,44 @@
+/*
+ * arch/arm/lib/call_with_stack.S
+ *
+ * Copyright (C) 2011 ARM Ltd.
+ * Written by Will Deacon <will.deacon@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+/*
+ * void call_with_stack(void (*fn)(void *), void *arg, void *sp)
+ *
+ * Change the stack to that pointed at by sp, then invoke fn(arg) with
+ * the new stack.
+ */
+ENTRY(call_with_stack)
+ str sp, [r2, #-4]!
+ str lr, [r2, #-4]!
+
+ mov sp, r2
+ mov r2, r0
+ mov r0, r1
+
+ adr lr, BSYM(1f)
+ mov pc, r2
+
+1: ldr lr, [sp]
+ ldr sp, [sp, #4]
+ mov pc, lr
+ENDPROC(call_with_stack)
diff --git a/arch/arm/mach-clps711x/include/mach/system.h b/arch/arm/mach-clps711x/include/mach/system.h
index f916cd7a477..6c119937d39 100644
--- a/arch/arm/mach-clps711x/include/mach/system.h
+++ b/arch/arm/mach-clps711x/include/mach/system.h
@@ -34,7 +34,7 @@ static inline void arch_idle(void)
static inline void arch_reset(char mode, const char *cmd)
{
- cpu_reset(0);
+ soft_restart(0);
}
#endif
diff --git a/arch/arm/mach-ebsa110/include/mach/system.h b/arch/arm/mach-ebsa110/include/mach/system.h
index 9a26245bf1f..0d5df72a03f 100644
--- a/arch/arm/mach-ebsa110/include/mach/system.h
+++ b/arch/arm/mach-ebsa110/include/mach/system.h
@@ -34,6 +34,6 @@ static inline void arch_idle(void)
asm volatile ("mcr p15, 0, ip, c15, c1, 2" : : : "cc");
}
-#define arch_reset(mode, cmd) cpu_reset(0x80000000)
+#define arch_reset(mode, cmd) soft_restart(0x80000000)
#endif
diff --git a/arch/arm/mach-footbridge/include/mach/system.h b/arch/arm/mach-footbridge/include/mach/system.h
index 0b293156620..249f895910f 100644
--- a/arch/arm/mach-footbridge/include/mach/system.h
+++ b/arch/arm/mach-footbridge/include/mach/system.h
@@ -24,7 +24,7 @@ static inline void arch_reset(char mode, const char *cmd)
/*
* Jump into the ROM
*/
- cpu_reset(0x41000000);
+ soft_restart(0x41000000);
} else {
if (machine_is_netwinder()) {
/* open up the SuperIO chip
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index f5920c24f7d..2901584d47f 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -73,5 +73,5 @@ obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o
ifeq ($(CONFIG_PM),y)
-obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o
+obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o suspend-imx6q.o
endif
diff --git a/arch/arm/mach-imx/clock-imx6q.c b/arch/arm/mach-imx/clock-imx6q.c
index b347a847c64..c246712948c 100644
--- a/arch/arm/mach-imx/clock-imx6q.c
+++ b/arch/arm/mach-imx/clock-imx6q.c
@@ -115,6 +115,8 @@
#define CG14 28
#define CG15 30
+#define BM_CCR_RBC_EN (0x1 << 27)
+
#define BM_CCSR_PLL1_SW_SEL (0x1 << 2)
#define BM_CCSR_STEP_SEL (0x1 << 8)
@@ -1916,35 +1918,44 @@ static struct clk_lookup lookups[] = {
int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
{
- u32 val = readl_relaxed(CLPCR);
+ u32 clpcr = readl_relaxed(CLPCR);
+ u32 ccr = readl_relaxed(CCR);
- val &= ~BM_CLPCR_LPM;
+ clpcr &= ~(BM_CLPCR_LPM | BM_CLPCR_VSTBY | BM_CLPCR_SBYOS
+ | BM_CLPCR_STBY_COUNT | BM_CLPCR_WB_PER_AT_LPM);
+ ccr &= ~(BM_CCR_RBC_EN);
switch (mode) {
case WAIT_CLOCKED:
break;
case WAIT_UNCLOCKED:
- val |= 0x1 << BP_CLPCR_LPM;
+ clpcr |= 0x1 << BP_CLPCR_LPM;
break;
case STOP_POWER_ON:
- val |= 0x2 << BP_CLPCR_LPM;
+ clpcr |= 0x2 << BP_CLPCR_LPM;
break;
case WAIT_UNCLOCKED_POWER_OFF:
- val |= 0x1 << BP_CLPCR_LPM;
- val &= ~BM_CLPCR_VSTBY;
- val &= ~BM_CLPCR_SBYOS;
- val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+ clpcr |= 0x1 << BP_CLPCR_LPM;
break;
case STOP_POWER_OFF:
- val |= 0x2 << BP_CLPCR_LPM;
- val |= 0x3 << BP_CLPCR_STBY_COUNT;
- val |= BM_CLPCR_VSTBY;
- val |= BM_CLPCR_SBYOS;
- val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+ clpcr |= 0x2 << BP_CLPCR_LPM;
+ clpcr |= 0x3 << BP_CLPCR_STBY_COUNT;
+ clpcr |= BM_CLPCR_VSTBY;
+ clpcr |= BM_CLPCR_SBYOS;
break;
+ case ARM_POWER_OFF:
+ clpcr |= 0x2 << BP_CLPCR_LPM;
+ clpcr |= 0x3 << BP_CLPCR_STBY_COUNT;
+ clpcr |= BM_CLPCR_VSTBY;
+ clpcr |= BM_CLPCR_SBYOS;
+ clpcr |= BM_CLPCR_WB_PER_AT_LPM;
+ /* assert anatop_reg_bypass signal */
+ ccr |= BM_CCR_RBC_EN;
+ break;
default:
return -EINVAL;
}
- writel_relaxed(val, CLPCR);
+ writel_relaxed(clpcr, CLPCR);
+ writel_relaxed(ccr, CCR);
return 0;
}
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index e1537f9e45b..8fc255b6daa 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -17,15 +17,36 @@
#include <linux/of_irq.h>
#include <asm/hardware/gic.h>
+#define GPC_CNTR 0x000
#define GPC_IMR1 0x008
+#define GPC_ISR1 0x018
+#define GPC_ISR2 0x01c
+#define GPC_ISR3 0x020
+#define GPC_ISR4 0x024
#define GPC_PGC_CPU_PDN 0x2a0
#define IMR_NUM 4
+#define ISR_NUM 4
static void __iomem *gpc_base;
static u32 gpc_wake_irqs[IMR_NUM];
static u32 gpc_saved_imrs[IMR_NUM];
+bool imx_gpc_wake_irq_pending(void)
+{
+ void __iomem *reg_isr1 = gpc_base + GPC_ISR1;
+ int i;
+ u32 val;
+
+ for (i = 0; i < ISR_NUM; i++) {
+ val = readl_relaxed(reg_isr1 + i * 4);
+ if (val & gpc_wake_irqs[i])
+ return true;
+ }
+
+ return false;
+}
+
void imx_gpc_pre_suspend(void)
{
void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
diff --git a/arch/arm/mach-imx/head-v7.S b/arch/arm/mach-imx/head-v7.S
index ea12b0c4a05..7e49deb128a 100644
--- a/arch/arm/mach-imx/head-v7.S
+++ b/arch/arm/mach-imx/head-v7.S
@@ -16,7 +16,6 @@
#include <asm/hardware/cache-l2x0.h>
.section ".text.head", "ax"
- __CPUINIT
/*
* The secondary kernel init calls v7_flush_dcache_all before it enables
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index d69f99f63dc..36ad689c28f 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -10,10 +10,13 @@
* http://www.gnu.org/copyleft/gpl.html
*/
+#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/io.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/phy.h>
@@ -41,6 +44,36 @@ static int ksz9021rn_phy_fixup(struct phy_device *phydev)
return 0;
}
+void imx6q_restart(char mode, const char *cmd)
+{
+ struct device_node *np;
+ void __iomem *wdog_base;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-wdt");
+ wdog_base = of_iomap(np, 0);
+ if (!wdog_base)
+ goto soft;
+
+ imx_src_prepare_restart();
+
+ /* enable wdog */
+ writew_relaxed(1 << 2, wdog_base);
+ /* write twice to ensure the request will not get ignored */
+ writew_relaxed(1 << 2, wdog_base);
+
+ /* wait for reset to assert ... */
+ mdelay(500);
+
+ pr_err("Watchdog reset failed to assert reset\n");
+
+ /* delay to allow the serial port to show the message */
+ mdelay(50);
+
+soft:
+ /* we'll take a jump through zero as a poor second */
+ soft_restart(0);
+}
+
static void __init imx6q_init_machine(void)
{
if (of_machine_is_compatible("fsl,imx6q-sabrelite"))
@@ -108,4 +141,5 @@ DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)")
.timer = &imx6q_timer,
.init_machine = imx6q_init_machine,
.dt_compat = imx6q_dt_compat,
+ .restart = imx6q_restart,
MACHINE_END
diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c
index f20f191d7cc..85b758ec4af 100644
--- a/arch/arm/mach-imx/pm-imx6q.c
+++ b/arch/arm/mach-imx/pm-imx6q.c
@@ -13,31 +13,73 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/suspend.h>
+#include <asm/mach/map.h>
#include <asm/cacheflush.h>
#include <asm/proc-fns.h>
#include <asm/suspend.h>
#include <asm/hardware/cache-l2x0.h>
+#include <mach/iram.h>
#include <mach/common.h>
#include <mach/hardware.h>
+struct imx_iram_pm {
+ void *iram_cpaddr;
+ unsigned long suspend_iram_paddr;
+ unsigned long suspend_iram_size;
+ void *suspend_iram_vaddr;
+ void *reg_ptr[4];
+} imx6q_iram_pm;
+
extern unsigned long phys_l2x0_saved_regs;
+extern void imx6q_suspend(void);
+static void (*suspend_in_iram)(unsigned long iram_paddr,
+ unsigned long iram_vaddr,
+ unsigned long iram_size);
static int imx6q_suspend_finish(unsigned long val)
{
- cpu_do_idle();
+ if ((val == PM_SUSPEND_MEM) && suspend_in_iram) {
+ suspend_in_iram((unsigned long)imx6q_iram_pm.suspend_iram_paddr,
+ (unsigned long)imx6q_iram_pm.suspend_iram_vaddr,
+ (unsigned long)imx6q_iram_pm.suspend_iram_size);
+ } else
+ cpu_do_idle();
+
return 0;
}
+static void imx6q_prepare_suspend_iram(void)
+{
+ unsigned long *iram_stack = imx6q_iram_pm.suspend_iram_vaddr
+ + imx6q_iram_pm.suspend_iram_size;
+
+ *(--iram_stack) = (unsigned long)imx6q_iram_pm.reg_ptr[3];
+ *(--iram_stack) = (unsigned long)imx6q_iram_pm.reg_ptr[2];
+ *(--iram_stack) = (unsigned long)imx6q_iram_pm.reg_ptr[1];
+ *(--iram_stack) = (unsigned long)imx6q_iram_pm.reg_ptr[0];
+}
+
static int imx6q_pm_enter(suspend_state_t state)
{
switch (state) {
+ case PM_SUSPEND_STANDBY:
case PM_SUSPEND_MEM:
- imx6q_set_lpm(STOP_POWER_OFF);
+ if (imx_gpc_wake_irq_pending())
+ return 0;
+
+ if (state == PM_SUSPEND_STANDBY)
+ imx6q_set_lpm(STOP_POWER_OFF);
+ else
+ imx6q_set_lpm(ARM_POWER_OFF);
+
imx_gpc_pre_suspend();
imx_set_cpu_jump(0, v7_cpu_resume);
+ if (state == PM_SUSPEND_MEM)
+ imx6q_prepare_suspend_iram();
/* Zzz ... */
- cpu_suspend(0, imx6q_suspend_finish);
+ cpu_suspend(state, imx6q_suspend_finish);
imx_smp_prepare();
imx_gpc_post_resume();
break;
@@ -48,11 +90,55 @@ static int imx6q_pm_enter(suspend_state_t state)
return 0;
}
+static int imx6q_pm_valid(suspend_state_t state)
+{
+ return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX);
+}
+
static const struct platform_suspend_ops imx6q_pm_ops = {
.enter = imx6q_pm_enter,
- .valid = suspend_valid_only_mem,
+ .valid = imx6q_pm_valid,
};
+static int __init imx6q_pm_iram_of_init(void)
+{
+ struct device_node *np;
+
+ /*
+ * these register may already ioremaped, need figure out
+ * one way to save vmalloc space.
+ */
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-src");
+ imx6q_iram_pm.reg_ptr[0] = of_iomap(np, 0);
+ if (!imx6q_iram_pm.reg_ptr[0])
+ goto err0;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-iomuxc");
+ imx6q_iram_pm.reg_ptr[1] = of_iomap(np, 0);
+ if (!imx6q_iram_pm.reg_ptr[1])
+ goto err1;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-mmdc");
+ imx6q_iram_pm.reg_ptr[2] = of_iomap(np, 0);
+ if (!imx6q_iram_pm.reg_ptr[2])
+ goto err2;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
+ imx6q_iram_pm.reg_ptr[3] = of_iomap(np, 0);
+ if (!imx6q_iram_pm.reg_ptr[3])
+ goto err3;
+
+ return 0;
+err3:
+ iounmap(imx6q_iram_pm.reg_ptr[2]);
+err2:
+ iounmap(imx6q_iram_pm.reg_ptr[1]);
+err1:
+ iounmap(imx6q_iram_pm.reg_ptr[0]);
+err0:
+ return -EINVAL;
+}
+
void __init imx6q_pm_init(void)
{
/*
@@ -67,4 +153,38 @@ void __init imx6q_pm_init(void)
phys_l2x0_saved_regs = __pa(&l2x0_saved_regs);
suspend_set_ops(&imx6q_pm_ops);
+
+ /* Move suspend routine into iRAM */
+ imx6q_iram_pm.suspend_iram_size = SZ_4K;
+ imx6q_iram_pm.iram_cpaddr = iram_alloc(imx6q_iram_pm.suspend_iram_size,
+ &imx6q_iram_pm.suspend_iram_paddr);
+ if (imx6q_iram_pm.iram_cpaddr) {
+ if (imx6q_pm_iram_of_init() < 0) {
+ iram_free(imx6q_iram_pm.suspend_iram_paddr,
+ imx6q_iram_pm.suspend_iram_size);
+ return;
+ }
+ /*
+ * Need to remap the area here since we want the memory region
+ * to be noncached & executable.
+ */
+ imx6q_iram_pm.suspend_iram_vaddr =
+ __arm_ioremap(imx6q_iram_pm.suspend_iram_paddr,
+ imx6q_iram_pm.suspend_iram_size,
+ MT_MEMORY_NONCACHED);
+ pr_info("cpaddr = %p suspend_iram_base=%p\n",
+ imx6q_iram_pm.iram_cpaddr,
+ imx6q_iram_pm.suspend_iram_vaddr);
+
+ /*
+ * Need to run the suspend code from IRAM as the DDR needs
+ * to be put into low power mode manually.
+ */
+ memcpy(imx6q_iram_pm.iram_cpaddr, imx6q_suspend,
+ imx6q_iram_pm.suspend_iram_size);
+
+ suspend_in_iram = (void *)imx6q_iram_pm.suspend_iram_vaddr;
+
+ } else
+ suspend_in_iram = NULL;
}
diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c
index a8e33681b73..4bde04f99e3 100644
--- a/arch/arm/mach-imx/src.c
+++ b/arch/arm/mach-imx/src.c
@@ -19,6 +19,7 @@
#define SRC_SCR 0x000
#define SRC_GPR1 0x020
+#define BP_SRC_SCR_WARM_RESET_ENABLE 0
#define BP_SRC_SCR_CORE1_RST 14
#define BP_SRC_SCR_CORE1_ENABLE 22
@@ -46,11 +47,33 @@ void imx_set_cpu_jump(int cpu, void *jump_addr)
src_base + SRC_GPR1 + cpu * 8);
}
+void imx_src_prepare_restart(void)
+{
+ u32 val;
+
+ /* clear enable bits of secondary cores */
+ val = readl_relaxed(src_base + SRC_SCR);
+ val &= ~(0x7 << BP_SRC_SCR_CORE1_ENABLE);
+ writel_relaxed(val, src_base + SRC_SCR);
+
+ /* clear persistent entry register of primary core */
+ writel_relaxed(0, src_base + SRC_GPR1);
+}
+
void __init imx_src_init(void)
{
struct device_node *np;
+ u32 val;
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-src");
src_base = of_iomap(np, 0);
WARN_ON(!src_base);
+
+ /*
+ * force warm reset sources to generate cold reset
+ * for a more reliable restart
+ */
+ val = readl_relaxed(src_base + SRC_SCR);
+ val &= ~(1 << BP_SRC_SCR_WARM_RESET_ENABLE);
+ writel_relaxed(val, src_base + SRC_SCR);
}
diff --git a/arch/arm/mach-imx/suspend-imx6q.S b/arch/arm/mach-imx/suspend-imx6q.S
new file mode 100644
index 00000000000..f803e2b7b11
--- /dev/null
+++ b/arch/arm/mach-imx/suspend-imx6q.S
@@ -0,0 +1,308 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/linkage.h>
+#include <mach/hardware.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#define SRC_GPR1_OFFSET 0x020
+#define SRC_GPR2_OFFSET 0x024
+#define MMDC_MAPSR_OFFSET 0x404
+#define MMDC_MAPSR_PSS (1 << 4)
+#define MMDC_MAPSR_PSD (1 << 0)
+#define ANATOP_REG_2P5 0x130
+
+.macro ddr_io_save
+ ldr r4, [r9, #0x5ac] /* DRAM_DQM0 */
+ ldr r5, [r9, #0x5b4] /* DRAM_DQM1 */
+ ldr r6, [r9, #0x528] /* DRAM_DQM2 */
+ ldr r7, [r9, #0x520] /* DRAM_DQM3 */
+ stmfd sp!, {r4-r7}
+
+ ldr r4, [r9, #0x514] /* DRAM_DQM4 */
+ ldr r5, [r9, #0x510] /* DRAM_DQM5 */
+ ldr r6, [r9, #0x5bc] /* DRAM_DQM6 */
+ ldr r7, [r9, #0x5c4] /* DRAM_DQM7 */
+ stmfd sp!, {r4-r7}
+
+ ldr r4, [r9, #0x56c] /* DRAM_CAS */
+ ldr r5, [r9, #0x578] /* DRAM_RAS */
+ ldr r6, [r9, #0x588] /* DRAM_SDCLK_0 */
+ ldr r7, [r9, #0x594] /* DRAM_SDCLK_1 */
+ stmfd sp!, {r4-r7}
+
+ ldr r5, [r9, #0x750] /* DDRMODE_CTL */
+ ldr r6, [r9, #0x774] /* DDRMODE */
+ stmfd sp!, {r5-r6}
+
+ ldr r4, [r9, #0x5a8] /* DRAM_SDQS0 */
+ ldr r5, [r9, #0x5b0] /* DRAM_SDQS1 */
+ ldr r6, [r9, #0x524] /* DRAM_SDQS2 */
+ ldr r7, [r9, #0x51c] /* DRAM_SDQS3 */
+ stmfd sp!, {r4-r7}
+
+ ldr r4, [r9, #0x518] /* DRAM_SDQS4 */
+ ldr r5, [r9, #0x50c] /* DRAM_SDQS5 */
+ ldr r6, [r9, #0x5b8] /* DRAM_SDQS6 */
+ ldr r7, [r9, #0x5c0] /* DRAM_SDQS7 */
+ stmfd sp!, {r4-r7}
+
+ ldr r4, [r9, #0x784] /* GPR_B0DS */
+ ldr r5, [r9, #0x788] /* GPR_B1DS */
+ ldr r6, [r9, #0x794] /* GPR_B2DS */
+ ldr r7, [r9, #0x79c] /* GPR_B3DS */
+ stmfd sp!, {r4-r7}
+
+ ldr r4, [r9, #0x7a0] /* GPR_B4DS */
+ ldr r5, [r9, #0x7a4] /* GPR_B5DS */
+ ldr r6, [r9, #0x7a8] /* GPR_B6DS */
+ ldr r7, [r9, #0x748] /* GPR_B7DS */
+ stmfd sp!, {r4-r7}
+
+ ldr r5, [r9, #0x74c] /* GPR_ADDS*/
+ ldr r6, [r9, #0x59c] /* DRAM_SODT0*/
+ ldr r7, [r9, #0x5a0] /* DRAM_SODT1*/
+ stmfd sp!, {r5-r7}
+.endm
+
+.macro ddr_io_restore
+ ldmfd sp!, {r5-r7}
+ str r5, [r9, #0x74c] /* GPR_ADDS*/
+ str r6, [r9, #0x59c] /* DRAM_SODT0*/
+ str r7, [r9, #0x5a0] /* DRAM_SODT1*/
+
+ ldmfd sp!, {r4-r7}
+ str r4, [r9, #0x7a0] /* GPR_B4DS */
+ str r5, [r9, #0x7a4] /* GPR_B5DS */
+ str r6, [r9, #0x7a8] /* GPR_B6DS */
+ str r7, [r9, #0x748] /* GPR_B7DS */
+
+ ldmfd sp!, {r4-r7}
+ str r4, [r9, #0x784] /* GPR_B0DS */
+ str r5, [r9, #0x788] /* GPR_B1DS */
+ str r6, [r9, #0x794] /* GPR_B2DS */
+ str r7, [r9, #0x79c] /* GPR_B3DS */
+
+ ldmfd sp!, {r4-r7}
+ str r4, [r9, #0x518] /* DRAM_SDQS4 */
+ str r5, [r9, #0x50c] /* DRAM_SDQS5 */
+ str r6, [r9, #0x5b8] /* DRAM_SDQS6 */
+ str r7, [r9, #0x5c0] /* DRAM_SDQS7 */
+
+ ldmfd sp!, {r4-r7}
+ str r4, [r9, #0x5a8] /* DRAM_SDQS0 */
+ str r5, [r9, #0x5b0] /* DRAM_SDQS1 */
+ str r6, [r9, #0x524] /* DRAM_SDQS2 */
+ str r7, [r9, #0x51c] /* DRAM_SDQS3 */
+
+ ldmfd sp!, {r5-r6}
+ str r5, [r9, #0x750] /* DDRMODE_CTL */
+ str r6, [r9, #0x774] /* DDRMODE */
+
+ ldmfd sp!, {r4-r7}
+ str r4, [r9, #0x56c] /* DRAM_CAS */
+ str r5, [r9, #0x578] /* DRAM_RAS */
+ str r6, [r9, #0x588] /* DRAM_SDCLK_0 */
+ str r7, [r9, #0x594] /* DRAM_SDCLK_1 */
+
+ ldmfd sp!, {r4-r7}
+ str r4, [r9, #0x514] /* DRAM_DQM4 */
+ str r5, [r9, #0x510] /* DRAM_DQM5 */
+ str r6, [r9, #0x5bc] /* DRAM_DQM6 */
+ str r7, [r9, #0x5c4] /* DRAM_DQM7 */
+
+ ldmfd sp!, {r4-r7}
+ str r4, [r9, #0x5ac] /* DRAM_DQM0 */
+ str r5, [r9, #0x5b4] /* DRAM_DQM1 */
+ str r6, [r9, #0x528] /* DRAM_DQM2 */
+ str r7, [r9, #0x520] /* DRAM_DQM3 */
+.endm
+
+.macro ddr_io_set_lpm
+ mov r4, #0
+ str r4, [r9, #0x5ac] /* DRAM_DQM0 */
+ str r4, [r9, #0x5b4] /* DRAM_DQM1 */
+ str r4, [r9, #0x528] /* DRAM_DQM2 */
+ str r4, [r9, #0x520] /* DRAM_DQM3 */
+
+ str r4, [r9, #0x514] /* DRAM_DQM4 */
+ str r4, [r9, #0x510] /* DRAM_DQM5 */
+ str r4, [r9, #0x5bc] /* DRAM_DQM6 */
+ str r4, [r9, #0x5c4] /* DRAM_DQM7 */
+
+ str r4, [r9, #0x56c] /* DRAM_CAS */
+ str r4, [r9, #0x578] /* DRAM_RAS */
+ str r4, [r9, #0x588] /* DRAM_SDCLK_0 */
+ str r4, [r9, #0x594] /* DRAM_SDCLK_1 */
+
+ str r4, [r9, #0x750] /* DDRMODE_CTL */
+ str r4, [r9, #0x774] /* DDRMODE */
+
+ str r4, [r9, #0x5a8] /* DRAM_SDQS0 */
+ str r4, [r9, #0x5b0] /* DRAM_SDQS1 */
+ str r4, [r9, #0x524] /* DRAM_SDQS2 */
+ str r4, [r9, #0x51c] /* DRAM_SDQS3 */
+
+ str r4, [r9, #0x518] /* DRAM_SDQS4 */
+ str r4, [r9, #0x50c] /* DRAM_SDQS5 */
+ str r4, [r9, #0x5b8] /* DRAM_SDQS6 */
+ str r4, [r9, #0x5c0] /* DRAM_SDQS7 */
+
+ str r4, [r9, #0x784] /* GPR_B0DS */
+ str r4, [r9, #0x788] /* GPR_B1DS */
+ str r4, [r9, #0x794] /* GPR_B2DS */
+ str r4, [r9, #0x79c] /* GPR_B3DS */
+
+ str r4, [r9, #0x7a0] /* GPR_B4DS */
+ str r4, [r9, #0x7a4] /* GPR_B5DS */
+ str r4, [r9, #0x7a8] /* GPR_B6DS */
+ str r4, [r9, #0x748] /* GPR_B7DS */
+
+ str r4, [r9, #0x74c] /* GPR_ADDS*/
+ str r4, [r9, #0x59c] /* DRAM_SODT0*/
+ str r4, [r9, #0x5a0] /* DRAM_SODT1*/
+.endm
+
+/*
+ * imx6q_suspend:
+ *
+ * Suspend the processor (eg, wait for interrupt).
+ * Set the DDR into Self Refresh
+ * IRQs are already disabled.
+ *
+ * Registers usage in the imx6q_suspend:
+ *
+ * r0: suspend_iram_paddr
+ * r1: suspend_iram_vaddr
+ * r2: suspend_iram_size
+ *
+ * r8: src_base pointer
+ * r9: iomux_base pointer
+ * r10: mmdc_base pointer
+ * r11: anatop_base pointer
+ * sp: iram stack
+ *
+ * Corrupted registers: r0-r3
+ */
+
+ENTRY(imx6q_suspend)
+ mov r3, sp @ save sp
+ add sp, r1, r2 @ set sp to top iram stack
+ sub sp, sp, #16 @ 4 regs ptr
+ stmfd sp!, {r4 - r12, lr} @ save registers
+
+ add r4, r1, r2
+ ldr r8, [r4, #-16] @ r8 = src_base pointer
+ ldr r9, [r4, #-12] @ r9 = iomux_base pointer
+ ldr r10, [r4, #-8] @ r10 = mmdc_base pointer
+ ldr r11, [r4, #-4] @ r11 = anatop_base pointer
+
+ /* should not access sp in ddr until resume with cache MMU on */
+ stmfd sp!, {r3} @ save old sp
+
+ ldr r4, [r8, #SRC_GPR1_OFFSET] @ r8 = src_base pointer
+ stmfd sp!, {r4} @ save old resume func
+
+ /* Enable weak 2P5 linear regulator */
+ ldr r4, [r11, #ANATOP_REG_2P5] @ r11 = anatop_base pointer
+ orr r4, r4, #0x40000
+ str r4, [r11, #ANATOP_REG_2P5]
+ mov r6, #1
+wait: ldr r4, [r11, #ANATOP_REG_2P5]
+ and r4, r4, r6, lsl #17 @ output ok?
+ cmp r4, #0
+ beq wait
+
+ /* save ddr iomux regs */
+ ddr_io_save
+
+ /* set ddr to low power mode */
+ ldr r4, [r10, #MMDC_MAPSR_OFFSET] @ r10 = mmdc_base pointer
+ bic r4, #MMDC_MAPSR_PSD
+ str r4, [r10, #MMDC_MAPSR_OFFSET]
+refresh:
+ ldr r4, [r10, #MMDC_MAPSR_OFFSET]
+ and r4, r4, #MMDC_MAPSR_PSS
+ cmp r4, #0
+ beq refresh
+
+ ddr_io_set_lpm
+
+ /* save resume pointer into SRC_GPR1, sp pointer into SRC_GPR2 */
+ ldr r4, =imx6q_suspend
+ ldr r5, =imx6q_resume
+ sub r5, r5, r4 @ r5 = resmue offset
+ add r5, r0, r5 @ r0 = suspend_iram_paddr, r5 = resmue phy addr
+ str r5, [r8, #SRC_GPR1_OFFSET] @ r8 = src_base pointer
+ sub r5, sp, r1 @ r1 = suspend_iram_vaddr, r5 = sp offset
+ add r5, r0, r5 @ r0 = suspend_iram_paddr, r5 = sp phy addr
+ str r5, [r8, #SRC_GPR2_OFFSET] @ r8 = src_base pointer
+
+ /* execute a wfi instruction to let SOC go into stop mode */
+ dsb
+ wfi
+
+ nop
+ nop
+ nop
+ nop
+
+ /*
+ * if go here, means there is a wakeup irq pending, we should resume
+ * system immediately.
+ */
+ ddr_io_restore
+
+ /* Disable weak 2P5 linear regulator */
+ ldr r4, [r11, #ANATOP_REG_2P5] @ r11 = anatop_base pointer
+ bic r4, #0x40000
+ str r4, [r11, #ANATOP_REG_2P5]
+
+ ldmfd sp!, {r4} @ drop old resmue func ptr
+ ldmfd sp!, {r3}
+ ldmfd sp!, {r4 - r12, lr}
+ mov sp, r3
+ mov pc, lr
+
+/*
+ * when SOC exit stop mode, arm core restart from here, currently
+ * are running with MMU off.
+ */
+imx6q_resume:
+ ldr r0, =MX6Q_SRC_BASE_ADDR
+ mov r1, #0x0
+ str r1, [r0, #SRC_GPR1_OFFSET] @ clear SRC_GPR1
+ ldr sp, [r0, #SRC_GPR2_OFFSET]
+ str r1, [r0, #SRC_GPR2_OFFSET] @ clear SRC_GPR2
+
+ ldr r9, =MX6Q_IOMUXC_BASE_ADDR
+ ddr_io_restore
+
+ ldr r0, =MX6Q_MMDC0_BASE_ADDR
+ ldr r1, [r0, #MMDC_MAPSR_OFFSET]
+ orr r1, #MMDC_MAPSR_PSD
+ str r1, [r0, #MMDC_MAPSR_OFFSET]
+
+ /* Disable weak 2P5 linear regulator */
+ ldr r0, =MX6Q_ANATOP_BASE_ADDR
+ ldr r1, [r0, #ANATOP_REG_2P5]
+ bic r1, #0x40000
+ str r1, [r0, #ANATOP_REG_2P5]
+
+ ldmfd sp!, {r2} @ resmue func ptr
+ ldmfd sp!, {r3}
+ ldmfd sp!, {r4 - r12, lr}
+ mov sp, r3
+
+ /* return back */
+ mov pc, r2
+ENDPROC(imx6q_suspend)
diff --git a/arch/arm/mach-iop32x/include/mach/system.h b/arch/arm/mach-iop32x/include/mach/system.h
index a4b808fe0d8..4865a9bff85 100644
--- a/arch/arm/mach-iop32x/include/mach/system.h
+++ b/arch/arm/mach-iop32x/include/mach/system.h
@@ -30,5 +30,5 @@ static inline void arch_reset(char mode, const char *cmd)
*IOP3XX_PCSR = 0x30;
/* Jump into ROM at address 0 */
- cpu_reset(0);
+ soft_restart(0);
}
diff --git a/arch/arm/mach-iop33x/include/mach/system.h b/arch/arm/mach-iop33x/include/mach/system.h
index f192a34be07..86d1b20dd69 100644
--- a/arch/arm/mach-iop33x/include/mach/system.h
+++ b/arch/arm/mach-iop33x/include/mach/system.h
@@ -19,5 +19,5 @@ static inline void arch_reset(char mode, const char *cmd)
*IOP3XX_PCSR = 0x30;
/* Jump into ROM at address 0 */
- cpu_reset(0);
+ soft_restart(0);
}
diff --git a/arch/arm/mach-ixp4xx/include/mach/system.h b/arch/arm/mach-ixp4xx/include/mach/system.h
index 54c0af7fa2d..24337d9d275 100644
--- a/arch/arm/mach-ixp4xx/include/mach/system.h
+++ b/arch/arm/mach-ixp4xx/include/mach/system.h
@@ -26,7 +26,7 @@ static inline void arch_reset(char mode, const char *cmd)
{
if ( 1 && mode == 's') {
/* Jump into ROM at address 0 */
- cpu_reset(0);
+ soft_restart(0);
} else {
/* Use on-chip reset capability */
diff --git a/arch/arm/mach-ks8695/include/mach/system.h b/arch/arm/mach-ks8695/include/mach/system.h
index fb1dda9be2d..ceb19c90aa5 100644
--- a/arch/arm/mach-ks8695/include/mach/system.h
+++ b/arch/arm/mach-ks8695/include/mach/system.h
@@ -32,7 +32,7 @@ static void arch_reset(char mode, const char *cmd)
unsigned int reg;
if (mode == 's')
- cpu_reset(0);
+ soft_restart(0);
/* disable timer0 */
reg = __raw_readl(KS8695_TMR_VA + KS8695_TMCON);
diff --git a/arch/arm/mach-mmp/include/mach/system.h b/arch/arm/mach-mmp/include/mach/system.h
index 1a8a25edb1b..cb0637933a8 100644
--- a/arch/arm/mach-mmp/include/mach/system.h
+++ b/arch/arm/mach-mmp/include/mach/system.h
@@ -19,8 +19,8 @@ static inline void arch_idle(void)
static inline void arch_reset(char mode, const char *cmd)
{
if (cpu_is_pxa168())
- cpu_reset(0xffff0000);
+ soft_restart(0xffff0000);
else
- cpu_reset(0);
+ soft_restart(0);
}
#endif /* __ASM_MACH_SYSTEM_H */
diff --git a/arch/arm/mach-mxs/system.c b/arch/arm/mach-mxs/system.c
index 20ec3bddf7c..cab88364e7c 100644
--- a/arch/arm/mach-mxs/system.c
+++ b/arch/arm/mach-mxs/system.c
@@ -53,7 +53,7 @@ void arch_reset(char mode, const char *cmd)
mdelay(50);
/* We'll take a jump through zero as a poor second */
- cpu_reset(0);
+ soft_restart(0);
}
static int __init mxs_arch_reset_init(void)
diff --git a/arch/arm/mach-pnx4008/include/mach/system.h b/arch/arm/mach-pnx4008/include/mach/system.h
index 5dda2bb55f8..5d6384a6128 100644
--- a/arch/arm/mach-pnx4008/include/mach/system.h
+++ b/arch/arm/mach-pnx4008/include/mach/system.h
@@ -32,7 +32,7 @@ static void arch_idle(void)
static inline void arch_reset(char mode, const char *cmd)
{
- cpu_reset(0);
+ soft_restart(0);
}
#endif
diff --git a/arch/arm/mach-pxa/reset.c b/arch/arm/mach-pxa/reset.c
index 01e9d643394..b8bcda15da8 100644
--- a/arch/arm/mach-pxa/reset.c
+++ b/arch/arm/mach-pxa/reset.c
@@ -88,7 +88,7 @@ void arch_reset(char mode, const char *cmd)
switch (mode) {
case 's':
/* Jump into ROM at address 0 */
- cpu_reset(0);
+ soft_restart(0);
break;
case 'g':
do_gpio_reset();
diff --git a/arch/arm/mach-rpc/include/mach/system.h b/arch/arm/mach-rpc/include/mach/system.h
index 45c7b935dc4..a354f4d092c 100644
--- a/arch/arm/mach-rpc/include/mach/system.h
+++ b/arch/arm/mach-rpc/include/mach/system.h
@@ -23,5 +23,5 @@ static inline void arch_reset(char mode, const char *cmd)
/*
* Jump into the ROM
*/
- cpu_reset(0);
+ soft_restart(0);
}
diff --git a/arch/arm/mach-s3c2410/include/mach/system-reset.h b/arch/arm/mach-s3c2410/include/mach/system-reset.h
index 6faadcee772..913893d4465 100644
--- a/arch/arm/mach-s3c2410/include/mach/system-reset.h
+++ b/arch/arm/mach-s3c2410/include/mach/system-reset.h
@@ -19,7 +19,7 @@ static void
arch_reset(char mode, const char *cmd)
{
if (mode == 's') {
- cpu_reset(0);
+ soft_restart(0);
}
if (s3c24xx_reset_hook)
@@ -28,5 +28,5 @@ arch_reset(char mode, const char *cmd)
arch_wdt_reset();
/* we'll take a jump through zero as a poor second */
- cpu_reset(0);
+ soft_restart(0);
}
diff --git a/arch/arm/mach-s3c64xx/include/mach/system.h b/arch/arm/mach-s3c64xx/include/mach/system.h
index 2e58cb7a714..d8ca5786ba2 100644
--- a/arch/arm/mach-s3c64xx/include/mach/system.h
+++ b/arch/arm/mach-s3c64xx/include/mach/system.h
@@ -24,7 +24,7 @@ static void arch_reset(char mode, const char *cmd)
arch_wdt_reset();
/* if all else fails, or mode was for soft, jump to 0 */
- cpu_reset(0);
+ soft_restart(0);
}
#endif /* __ASM_ARCH_IRQ_H */
diff --git a/arch/arm/mach-sa1100/include/mach/system.h b/arch/arm/mach-sa1100/include/mach/system.h
index ba9da9f7f18..345d35b7450 100644
--- a/arch/arm/mach-sa1100/include/mach/system.h
+++ b/arch/arm/mach-sa1100/include/mach/system.h
@@ -14,7 +14,7 @@ static inline void arch_reset(char mode, const char *cmd)
{
if (mode == 's') {
/* Jump into ROM at address 0 */
- cpu_reset(0);
+ soft_restart(0);
} else {
/* Use on-chip reset capability */
RSRR = RSRR_SWR;
diff --git a/arch/arm/mach-shmobile/include/mach/system.h b/arch/arm/mach-shmobile/include/mach/system.h
index 76a687eeaa2..956ac18ddbf 100644
--- a/arch/arm/mach-shmobile/include/mach/system.h
+++ b/arch/arm/mach-shmobile/include/mach/system.h
@@ -8,7 +8,7 @@ static inline void arch_idle(void)
static inline void arch_reset(char mode, const char *cmd)
{
- cpu_reset(0);
+ soft_restart(0);
}
#endif
diff --git a/arch/arm/mach-w90x900/include/mach/system.h b/arch/arm/mach-w90x900/include/mach/system.h
index ce228bdc66d..68875a1c16b 100644
--- a/arch/arm/mach-w90x900/include/mach/system.h
+++ b/arch/arm/mach-w90x900/include/mach/system.h
@@ -33,7 +33,7 @@ static void arch_reset(char mode, const char *cmd)
{
if (mode == 's') {
/* Jump into ROM at address 0 */
- cpu_reset(0);
+ soft_restart(0);
} else {
__raw_writel(WTE | WTRE | WTCLK, WTCR);
}
diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c
index 2be9139a4ef..296ad2eaddb 100644
--- a/arch/arm/mm/idmap.c
+++ b/arch/arm/mm/idmap.c
@@ -78,7 +78,7 @@ void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end)
* the user-mode pages. This will then ensure that we have predictable
* results when turning the mmu off
*/
-void setup_mm_for_reboot(char mode)
+void setup_mm_for_reboot(void)
{
/*
* We need to access to user-mode page tables here. For kernel threads
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
index 941a98c9e8a..88417514b2c 100644
--- a/arch/arm/mm/nommu.c
+++ b/arch/arm/mm/nommu.c
@@ -43,7 +43,7 @@ void __init paging_init(struct machine_desc *mdesc)
/*
* We don't need to do anything here for nommu machines.
*/
-void setup_mm_for_reboot(char mode)
+void setup_mm_for_reboot(void)
{
}
diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
index f4ebdb817ab..7365b27ec64 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -82,6 +82,7 @@ enum mxc_cpu_pwr_mode {
WAIT_UNCLOCKED_POWER_OFF, /* WAIT + SRPG */
STOP_POWER_ON, /* just STOP */
STOP_POWER_OFF, /* STOP + SRPG */
+ ARM_POWER_OFF, /* STOP + SRPG + ARM power off */
};
extern void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode);
@@ -122,7 +123,9 @@ static inline void imx_smp_prepare(void) {}
extern void imx_enable_cpu(int cpu, bool enable);
extern void imx_set_cpu_jump(int cpu, void *jump_addr);
extern void imx_src_init(void);
+extern void imx_src_prepare_restart(void);
extern void imx_gpc_init(void);
+extern bool imx_gpc_wake_irq_pending(void);
extern void imx_gpc_pre_suspend(void);
extern void imx_gpc_post_resume(void);
extern void imx51_babbage_common_init(void);
diff --git a/arch/arm/plat-mxc/include/mach/mx6q.h b/arch/arm/plat-mxc/include/mach/mx6q.h
index e051ff1f651..8c13004c086 100644
--- a/arch/arm/plat-mxc/include/mach/mx6q.h
+++ b/arch/arm/plat-mxc/include/mach/mx6q.h
@@ -29,6 +29,12 @@
#define MX6Q_CCM_SIZE 0x4000
#define MX6Q_ANATOP_BASE_ADDR 0x020c8000
#define MX6Q_ANATOP_SIZE 0x1000
+#define MX6Q_SRC_BASE_ADDR 0x020d8000
+#define MX6Q_SRC_SIZE 0x4000
+#define MX6Q_IOMUXC_BASE_ADDR 0x020e0000
+#define MX6Q_IOMUXC_SIZE 0x4000
+#define MX6Q_MMDC0_BASE_ADDR 0x021b0000
+#define MX6Q_MMDC0_SIZE 0x4000
#define MX6Q_UART4_BASE_ADDR 0x021f0000
#define MX6Q_UART4_SIZE 0x4000
diff --git a/arch/arm/plat-mxc/system.c b/arch/arm/plat-mxc/system.c
index d65fb31a55c..7e5c76ea446 100644
--- a/arch/arm/plat-mxc/system.c
+++ b/arch/arm/plat-mxc/system.c
@@ -71,7 +71,7 @@ void arch_reset(char mode, const char *cmd)
mdelay(50);
/* we'll take a jump through zero as a poor second */
- cpu_reset(0);
+ soft_restart(0);
}
void mxc_arch_reset_init(void __iomem *base)
diff --git a/arch/arm/plat-spear/include/plat/system.h b/arch/arm/plat-spear/include/plat/system.h
index a235fa0ca77..1171f228d71 100644
--- a/arch/arm/plat-spear/include/plat/system.h
+++ b/arch/arm/plat-spear/include/plat/system.h
@@ -31,7 +31,7 @@ static inline void arch_reset(char mode, const char *cmd)
{
if (mode == 's') {
/* software reset, Jump into ROM at address 0 */
- cpu_reset(0);
+ soft_restart(0);
} else {
/* hardware reset, Use on-chip reset capability */
sysctl_soft_reset((void __iomem *)VA_SPEAR_SYS_CTRL_BASE);
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index e018aef88df..0f4ba212fd6 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -566,6 +566,9 @@ static irqreturn_t imx_int(int irq, void *dev_id)
if (sts & USR1_RTSD)
imx_rtsint(irq, dev_id);
+ if (sts & USR1_AWAKE)
+ writel(USR1_AWAKE, sport->port.membase + USR1);
+
return IRQ_HANDLED;
}
@@ -1269,6 +1272,12 @@ static struct uart_driver imx_reg = {
static int serial_imx_suspend(struct platform_device *dev, pm_message_t state)
{
struct imx_port *sport = platform_get_drvdata(dev);
+ unsigned int val;
+
+ /* enable wakeup from i.MX UART */
+ val = readl(sport->port.membase + UCR3);
+ val |= UCR3_AWAKEN;
+ writel(val, sport->port.membase + UCR3);
if (sport)
uart_suspend_port(&imx_reg, &sport->port);
@@ -1279,6 +1288,12 @@ static int serial_imx_suspend(struct platform_device *dev, pm_message_t state)
static int serial_imx_resume(struct platform_device *dev)
{
struct imx_port *sport = platform_get_drvdata(dev);
+ unsigned int val;
+
+ /* disable wakeup from i.MX UART */
+ val = readl(sport->port.membase + UCR3);
+ val &= ~UCR3_AWAKEN;
+ writel(val, sport->port.membase + UCR3);
if (sport)
uart_resume_port(&imx_reg, &sport->port);