[ARM] pxa: add preliminary suspend/resume code for pxa3xx

1. clear RDH bit after resuming back from D3, otherwise, the multi function
   pins will retain the low power state

2. save/restore essential system registers

Signed-off-by: eric miao <eric.miao@marvell.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S
index 14bb4a9..784716e 100644
--- a/arch/arm/mach-pxa/sleep.S
+++ b/arch/arm/mach-pxa/sleep.S
@@ -50,6 +50,108 @@
 	str	r0, [r1]
 	ldr	pc, [sp], #4
 
+#ifdef CONFIG_PXA3xx
+/*
+ * pxa3xx_cpu_suspend() - forces CPU into sleep state (S2D3C4)
+ *
+ * NOTE:  unfortunately, pxa_cpu_save_cp can not be reused here since
+ * the auxiliary control register address is different between pxa3xx
+ * and pxa{25x,27x}
+ */
+
+ENTRY(pxa3xx_cpu_suspend)
+
+#ifndef CONFIG_IWMMXT
+	mra	r2, r3, acc0
+#endif
+	stmfd	sp!, {r2 - r12, lr}	@ save registers on stack
+
+	mrc	p14, 0, r3, c6, c0, 0		@ clock configuration, for turbo mode
+	mrc	p15, 0, r4, c15, c1, 0		@ CP access reg
+	mrc	p15, 0, r5, c13, c0, 0		@ PID
+	mrc 	p15, 0, r6, c3, c0, 0		@ domain ID
+	mrc 	p15, 0, r7, c2, c0, 0		@ translation table base addr
+	mrc	p15, 0, r8, c1, c0, 1           @ auxiliary control reg
+	mrc 	p15, 0, r9, c1, c0, 0		@ control reg
+
+	bic	r3, r3, #2			@ clear frequency change bit
+
+	@ store them plus current virtual stack ptr on stack
+	mov	r10, sp
+	stmfd	sp!, {r3 - r10}
+
+	@ store physical address of stack pointer
+	mov	r0, sp
+	bl	sleep_phys_sp
+	ldr	r1, =sleep_save_sp
+	str	r0, [r1]
+
+	@ clean data cache
+	bl	xsc3_flush_kern_cache_all
+
+	mov	r0, #0x06		@ S2D3C4 mode
+	mcr	p14, 0, r0, c7, c0, 0	@ enter sleep
+
+20:	b	20b			@ waiting for sleep
+
+	.data
+	.align 5
+/*
+ * pxa3xx_cpu_resume
+ */
+
+ENTRY(pxa3xx_cpu_resume)
+
+	mov	r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE	@ set SVC, irqs off
+	msr	cpsr_c, r0
+
+	ldr	r0, sleep_save_sp		@ stack phys addr
+	ldmfd	r0, {r3 - r9, sp}		@ CP regs + virt stack ptr
+
+	mov	r1, #0
+	mcr	p15, 0, r1, c7, c7, 0		@ invalidate I & D caches, BTB
+	mcr	p15, 0, r1, c7, c10, 4		@ drain write (&fill) buffer
+	mcr	p15, 0, r1, c7, c5, 4		@ flush prefetch buffer
+	mcr	p15, 0, r1, c8, c7, 0   	@ invalidate I & D TLBs
+
+	mcr	p14, 0, r3, c6, c0, 0		@ clock configuration, turbo mode.
+	mcr	p15, 0, r4, c15, c1, 0		@ CP access reg
+	mcr	p15, 0, r5, c13, c0, 0		@ PID
+	mcr 	p15, 0, r6, c3, c0, 0		@ domain ID
+	mcr 	p15, 0, r7, c2, c0, 0		@ translation table base addr
+	mcr	p15, 0, r8, c1, c0, 1           @ auxiliary control reg
+
+	@ temporarily map resume_turn_on_mmu into the page table,
+	@ otherwise prefetch abort occurs after MMU is turned on
+	mov	r1, r7
+	bic	r1, r1, #0x00ff
+	bic	r1, r1, #0x3f00
+	ldr	r2, =0x542e
+
+	adr	r3, resume_turn_on_mmu
+	mov	r3, r3, lsr #20
+	orr	r4, r2, r3, lsl #20
+	ldr	r5, [r1, r3, lsl #2]
+	str     r4, [r1, r3, lsl #2]
+
+	@ Mapping page table address in the page table
+	mov	r6, r1, lsr #20
+	orr	r7, r2, r6, lsl #20
+	ldr	r8, [r1, r6, lsl #2]
+	str	r7, [r1, r6, lsl #2]
+
+	ldr	r2, =pxa3xx_resume_after_mmu	@ absolute virtual address
+	b	resume_turn_on_mmu		@ cache align execution
+
+	.text
+pxa3xx_resume_after_mmu:
+	/* restore the temporary mapping */
+	str	r5, [r1, r3, lsl #2]
+	str	r8, [r1, r6, lsl #2]
+	b	resume_after_mmu
+
+#endif /* CONFIG_PXA3xx */
+
 #ifdef CONFIG_PXA27x
 /*
  * pxa27x_cpu_suspend()