Commit 09520524 authored by Nicolas Pitre's avatar Nicolas Pitre Committed by Russell King

[ARM PATCH] 1166/1: further cleanup of SA1110 suspend/resume code (2.5)

Same thing as patch #1165/1 but for 2.5.x
parent 1650fa58
...@@ -18,12 +18,14 @@ ...@@ -18,12 +18,14 @@
* 2001-08-29: Nicolas Pitre <nico@cam.org> * 2001-08-29: Nicolas Pitre <nico@cam.org>
* Cleaned up, pushed platform dependent stuff * Cleaned up, pushed platform dependent stuff
* in the platform specific files. * in the platform specific files.
*
* 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array.
* Storage is local on the stack now.
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/slab.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/sysctl.h> #include <linux/sysctl.h>
...@@ -35,7 +37,6 @@ ...@@ -35,7 +37,6 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/leds.h> #include <asm/leds.h>
#include "sleep.h"
/* /*
* Debug macros * Debug macros
...@@ -45,20 +46,32 @@ ...@@ -45,20 +46,32 @@
extern void sa1100_cpu_suspend(void); extern void sa1100_cpu_suspend(void);
extern void sa1100_cpu_resume(void); extern void sa1100_cpu_resume(void);
extern unsigned long *sleep_save; /* virtual address */
extern unsigned long sleep_save_p; /* physical address */
#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
/*
* List of global SA11x0 peripheral registers to preserve.
* More ones like CP and general purpose register values are preserved
* on the stack and then the stack pointer is stored last in sleep.S.
*/
enum { SLEEP_SAVE_SP = 0,
SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER,
SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3,
SLEEP_SAVE_GPDR, SLEEP_SAVE_GRER, SLEEP_SAVE_GFER, SLEEP_SAVE_GAFR,
SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR,
SLEEP_SAVE_ICMR,
SLEEP_SAVE_Ser1SDCR0,
SLEEP_SAVE_SIZE
};
int pm_do_suspend(void) int pm_do_suspend(void)
{ {
/* set up pointer to sleep parameters */ unsigned long sleep_save[SLEEP_SAVE_SIZE];
sleep_save = kmalloc(SLEEP_SAVE_SIZE*sizeof(long), GFP_ATOMIC);
if (!sleep_save)
return -ENOMEM;
sleep_save_p = virt_to_phys(sleep_save);
cli(); cli();
...@@ -146,8 +159,6 @@ int pm_do_suspend(void) ...@@ -146,8 +159,6 @@ int pm_do_suspend(void)
sti(); sti();
kfree (sleep_save);
/* /*
* Restore the CPU frequency settings. * Restore the CPU frequency settings.
*/ */
...@@ -158,6 +169,11 @@ int pm_do_suspend(void) ...@@ -158,6 +169,11 @@ int pm_do_suspend(void)
return 0; return 0;
} }
unsigned long sleep_phys_sp(void *sp)
{
return virt_to_phys(sp);
}
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
/* /*
* ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than * ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than
......
...@@ -11,12 +11,20 @@ ...@@ -11,12 +11,20 @@
* 2001-02-06: Cliff Brake Initial code * 2001-02-06: Cliff Brake Initial code
* *
* 2001-08-29: Nicolas Pitre Simplified. * 2001-08-29: Nicolas Pitre Simplified.
*
* 2002-05-27: Nicolas Pitre Revisited, more cleanup and simplification.
* Storage is on the stack now.
*/ */
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/assembler.h> #include <asm/assembler.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include "sleep.h"
.text
/* /*
* sa1100_cpu_suspend() * sa1100_cpu_suspend()
...@@ -25,35 +33,24 @@ ...@@ -25,35 +33,24 @@
* *
*/ */
.text ENTRY(sa1100_cpu_suspend)
ENTRY(sleep_save) .word 0 @ virtual address of parameter array stmfd sp!, {r4 - r12, lr} @ save registers on stack
ENTRY(sleep_save_p) .word 0 @ physical address of parameter array
ENTRY(sa1100_cpu_suspend) @ get coprocessor registers
mrc p15, 0, r4, c3, c0, 0 @ domain ID
mrc p15, 0, r5, c2, c0, 0 @ translation table base addr
mrc p15, 0, r6, c13, c0, 0 @ PID
mrc p15, 0, r7, c1, c0, 0 @ control reg
@ store them plus current virtual stack ptr on stack
stmfd sp!, {r4 - r7, sp}
@ save registers on stack @ preserve phys address of stack
stmfd sp!, {r4 - r12, lr} mov r0, sp
bl sleep_phys_sp
@ load virtual address for sleep_save array ldr r1, =sleep_save_sp
ldr r4, sleep_save str r0, [r1]
@ save stack pointer
str sp, [r4, #(SLEEP_SAVE_SP*4)]
@ save coprocessor registers
mrc p15, 0, r1, c1, c0, 0
str r1, [r4, #(SLEEP_SAVE_CP15_R1*4)]
mrc p15, 0, r1, c2, c0, 0
str r1, [r4, #(SLEEP_SAVE_CP15_R2*4)]
mrc p15, 0, r1, c3, c0, 0
str r1, [r4, #(SLEEP_SAVE_CP15_R3*4)]
mrc p15, 0, r1, c5, c0, 0
str r1, [r4, #(SLEEP_SAVE_CP15_R5*4)]
mrc p15, 0, r1, c6, c0, 0
str r1, [r4, #(SLEEP_SAVE_CP15_R6*4)]
mrc p15, 0, r1, c13, c0, 0
str r1, [r4, #(SLEEP_SAVE_CP15_R13*4)]
@ clean data cache and invalidate WB @ clean data cache and invalidate WB
bl cpu_sa1100_cache_clean_invalidate_all bl cpu_sa1100_cache_clean_invalidate_all
...@@ -79,25 +76,24 @@ ENTRY(sa1100_cpu_suspend) ...@@ -79,25 +76,24 @@ ENTRY(sa1100_cpu_suspend)
mov r0, #90 mov r0, #90
bl udelay bl udelay
/*
/* setup up register contents for jump to page containing SA1110 SDRAM controller bug fix suspend code * SA1110 SDRAM controller workaround. register values:
* *
* r0 points to MSC0 register * r0 = &MSC0
* r1 points to MSC1 register * r1 = &MSC1
* r2 points to MSC2 register * r2 = &MSC2
* r3 is MSC0 value * r3 = MSC0 value
* r4 is MSC1 value * r4 = MSC1 value
* r5 is MSC2 value * r5 = MSC2 value
* r6 points to MDREFR register * r6 = &MDREFR
* r7 is first MDREFR value * r7 = first MDREFR value
* r8 is second MDREFR value * r8 = second MDREFR value
* r9 is pointer to MDCNFG register * r9 = &MDCNFG
* r10 is MDCNFG value * r10 = MDCNFG value
* r11 is third MDREFR value * r11 = third MDREFR value
* r12 is pointer to PMCR register * r12 = &PMCR
* r13 is PMCR value (1) * r13 = PMCR value (1)
* */
*/
ldr r0, =MSC0 ldr r0, =MSC0
ldr r1, =MSC1 ldr r1, =MSC1
...@@ -170,69 +166,49 @@ sa1110_sdram_controller_fix: ...@@ -170,69 +166,49 @@ sa1110_sdram_controller_fix:
* *
* entry point from bootloader into kernel during resume * entry point from bootloader into kernel during resume
* *
* Note: Yes, part of the following code is located into the .data section.
* This is to allow sleep_save_sp to be accessed with a relative load
* while we can't rely on any MMU translation. We could have put
* sleep_save_sp in the .text section as well, but some setups might
* insist on it to be truely read-only.
*/ */
.data
.align 5 .align 5
ENTRY(sa1100_cpu_resume) ENTRY(sa1100_cpu_resume)
@ set SVC, irqs off
mov r0, #PSR_F_BIT | PSR_I_BIT | MODE_SVC mov r0, #PSR_F_BIT | PSR_I_BIT | MODE_SVC
msr cpsr_c, r0 msr cpsr_c, r0 @ set SVC, irqs off
@ load physical address of sleep_save
ldr r4, sleep_save_p
@ restore cp15_r3, domain id ldr r0, sleep_save_sp @ stack phys addr
ldr r1, [r4, #(SLEEP_SAVE_CP15_R3*4)] ldr r2, =resume_after_mmu @ its absolute virtual address
mcr p15, 0, r1, c3, c0 ,0 ldmfd r0, {r4 - r7, sp} @ CP regs + virt stack ptr
@ restore cp15_r2, translation table base address
ldr r1, [r4, #(SLEEP_SAVE_CP15_R2*4)]
mcr p15, 0, r1, c2, c0 ,0
mov r1, #0 mov r1, #0
mcr p15, 0, r1, c8, c7, 0 @ flush I+D TLBs mcr p15, 0, r1, c8, c7, 0 @ flush I+D TLBs
mcr p15, 0, r1, c7, c7, 0 @ flush I&D cache mcr p15, 0, r1, c7, c7, 0 @ flush I&D cache
mcr p15, 0, r1, c9, c0, 0 @ invalidate RB
mcr p15, 0, r1, c9, c0, 5 @ allow user space to use RB
@ get saved cp15 r1 (control register) mcr p15, 0, r4, c3, c0, 0 @ domain ID
ldr r1, [r4, #(SLEEP_SAVE_CP15_R1*4)] mcr p15, 0, r5, c2, c0, 0 @ translation table base addr
mcr p15, 0, r6, c13, c0, 0 @ PID
@ get address to jump to after turning on MMU b resume_turn_on_mmu @ cache align execution
ldr r2, =resume_after_mmu
cmp r2, #0
b resume_turn_on_mmu
.align 5 .align 5
resume_turn_on_mmu: resume_turn_on_mmu:
mcr p15, 0, r7, c1, c0, 0 @ turn on MMU, caches, etc.
@ turn on mmu nop
mcr p15, 0, r1, c1, c0 ,0 mov pc, r2 @ jump to virtual addr
nop
@ jump to resume_after_mmu
mov pc, r2
nop nop
nop nop
.align 5 sleep_save_sp:
resume_after_mmu: .word 0 @ preserve stack phys ptr here
@ load virtual address for sleep_save array
ldr r4, sleep_save
@ restore the rest of CPU state
ldr r1, [r4, #(SLEEP_SAVE_CP15_R13*4)]
mcr p15, 0, r1, c13, c0, 0
ldr r1, [r4, #(SLEEP_SAVE_CP15_R5*4)]
mcr p15, 0, r1, c5, c0 ,0
ldr r1, [r4, #(SLEEP_SAVE_CP15_R6*4)]
mcr p15, 0, r1, c6, c0 ,0
@ restore stack pointer
ldr sp, [r4, #(SLEEP_SAVE_SP*4)]
@ return to caller .text
ldmfd sp!, {r4 - r12, pc} resume_after_mmu:
mcr p15, 0, r1, c15, c1, 2 @ enable clock switching
ldmfd sp!, {r4 - r12, pc} @ return to caller
/*
* Offsets for register values preserved in RAM while in sleep mode
*/
#define SLEEP_SAVE_OSCR 0
#define SLEEP_SAVE_OSMR0 1
#define SLEEP_SAVE_OSMR1 2
#define SLEEP_SAVE_OSMR2 3
#define SLEEP_SAVE_OSMR3 4
#define SLEEP_SAVE_OIER 5
#define SLEEP_SAVE_GPDR 6
#define SLEEP_SAVE_GRER 7
#define SLEEP_SAVE_GFER 8
#define SLEEP_SAVE_GAFR 9
#define SLEEP_SAVE_PPDR 10
#define SLEEP_SAVE_PPSR 11
#define SLEEP_SAVE_PPAR 12
#define SLEEP_SAVE_PSDR 13
#define SLEEP_SAVE_Ser1SDCR0 14
#define SLEEP_SAVE_ICMR 15
#define SLEEP_SAVE_SP 16
#define SLEEP_SAVE_CP15_R1 17
#define SLEEP_SAVE_CP15_R2 18
#define SLEEP_SAVE_CP15_R3 19
#define SLEEP_SAVE_CP15_R5 20
#define SLEEP_SAVE_CP15_R6 21
#define SLEEP_SAVE_CP15_R13 22
#define SLEEP_SAVE_SIZE 23
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment