381 lines
20 KiB
ArmAsm
Executable File
381 lines
20 KiB
ArmAsm
Executable File
/*
|
|
* mem support specific for ARM
|
|
* based on hibernate support specific for ARM
|
|
* Copyright (C) 2010 Nokia Corporation
|
|
* Copyright (C) 2010 Texas Instruments, Inc.
|
|
* Copyright (C) 2006 Rafael J. Wysocki <rjw <at> sisk.pl>
|
|
*
|
|
* Contact: Hiroshi DOYU <Hiroshi.DOYU <at> nokia.com>
|
|
*
|
|
* License terms: GNU General Public License (GPL) version 2
|
|
*/
|
|
|
|
#include <linux/linkage.h>
|
|
/*
|
|
* function: mem_arch_suspend
|
|
* discription: save main part of general purpose register.
|
|
*/
|
|
.text
|
|
.globl mem_arch_suspend
|
|
mem_arch_suspend:
|
|
push {r0-r3}
|
|
/*
|
|
* Save current program status register
|
|
*/
|
|
ldr r3, .Lsaved_cpsr_svc
|
|
mrs r0, cpsr
|
|
str r0, [r3]
|
|
|
|
/*
|
|
* Change to system(user) mode
|
|
*/
|
|
mov r1, r0
|
|
orr r1, r1, #0x1f
|
|
msr cpsr_c, r1
|
|
|
|
/*
|
|
* Save User context
|
|
*/
|
|
ldr r3, .Lsaved_context_r13_sys
|
|
stmia r3, {r13-r14}
|
|
|
|
/*
|
|
* Change to fiq mode
|
|
*/
|
|
mov r1, r0
|
|
bic r1, r1, #0x1f
|
|
orr r1, r1, #0x11
|
|
msr cpsr_c, r1
|
|
|
|
/*
|
|
* Save fiq context
|
|
*/
|
|
ldr r3, .Lsaved_context_r13_fiq
|
|
stmia r3, {r8-r14}
|
|
ldr r3, .Lsaved_spsr_fiq
|
|
mrs r1, spsr
|
|
str r1, [r3]
|
|
|
|
/*
|
|
* Change to abt mode
|
|
*/
|
|
mov r1, r0
|
|
bic r1, r1, #0x1f
|
|
orr r1, r1, #0x17
|
|
msr cpsr_c, r1
|
|
|
|
/*
|
|
* Save abt context
|
|
*/
|
|
ldr r3, .Lsaved_context_r13_abt
|
|
stmia r3, {r13-r14}
|
|
ldr r3, .Lsaved_spsr_abt
|
|
mrs r1, spsr
|
|
str r1, [r3]
|
|
|
|
/*
|
|
* Change to irq mode
|
|
*/
|
|
mov r1, r0
|
|
bic r1, r1, #0x1f
|
|
orr r1, r1, #0x12
|
|
msr cpsr_c, r1
|
|
|
|
/*
|
|
* Save irq context
|
|
*/
|
|
ldr r3, .Lsaved_context_r13_irq
|
|
stmia r3, {r13-r14}
|
|
ldr r3, .Lsaved_spsr_irq
|
|
mrs r1, spsr
|
|
str r1, [r3]
|
|
|
|
/*
|
|
* Change to und mode
|
|
*/
|
|
mov r1, r0
|
|
bic r1, r1, #0x1f
|
|
orr r1, r1, #0x1b
|
|
msr cpsr_c, r1
|
|
|
|
/*
|
|
* Save und context
|
|
*/
|
|
ldr r3, .Lsaved_context_r13_und
|
|
stmia r3, {r13-r14}
|
|
ldr r3, .Lsaved_spsr_und
|
|
mrs r1, spsr
|
|
str r1, [r3]
|
|
|
|
/*
|
|
* Change to mon mode
|
|
*/
|
|
mov r1, r0
|
|
bic r1, r1, #0x1f
|
|
orr r1, r1, #0x16
|
|
msr cpsr_c, r1
|
|
|
|
/*
|
|
* Save mon context
|
|
*/
|
|
ldr r3, .Lsaved_context_r13_mon
|
|
stmia r3, {r13-r14}
|
|
ldr r3, .Lsaved_spsr_mon
|
|
mrs r1, spsr
|
|
str r1, [r3]
|
|
|
|
/*
|
|
* Go back to original SVC mode
|
|
*/
|
|
msr cpsr_c, r0
|
|
|
|
/*
|
|
* Save SVC context
|
|
*/
|
|
ldr r3, .Lsaved_context_r12_svc
|
|
stmia r3, {r12-r13}
|
|
ldr r3, .Lsaved_spsr_svc
|
|
mrs r1, spsr
|
|
str r1, [r3]
|
|
|
|
pop {r0-r3}
|
|
/*
|
|
* return
|
|
*/
|
|
mov pc, lr
|
|
|
|
/*
|
|
* function: mem_arch_resume
|
|
* discription: retore main part of general purpose register.
|
|
*/
|
|
.align 4
|
|
.globl mem_arch_resume
|
|
mem_arch_resume:
|
|
push {r0-r3}
|
|
|
|
mrs r0, cpsr
|
|
/*
|
|
* Restore SVC context
|
|
*/
|
|
ldr r3, .Lsaved_context_r12_svc
|
|
ldmia r3, {r12-r13}
|
|
ldr r3, .Lsaved_spsr_svc
|
|
ldr r1, [r3]
|
|
msr spsr_cxsf, r1
|
|
|
|
/*
|
|
* Change to system(user) mode
|
|
*/
|
|
mov r1, r0
|
|
orr r1, r1, #0x1f
|
|
msr cpsr_c, r1
|
|
|
|
/*
|
|
* Restore User context
|
|
*/
|
|
ldr r3, .Lsaved_context_r13_sys
|
|
ldmia r3, {r13-r14}
|
|
|
|
/*
|
|
* Change to fiq mode
|
|
*/
|
|
mov r1, r0
|
|
bic r1, r1, #0x1f
|
|
orr r1, r1, #0x11
|
|
msr cpsr_c, r1
|
|
|
|
/*
|
|
* Restore fiq context
|
|
*/
|
|
ldr r3, .Lsaved_context_r13_fiq
|
|
ldmia r3, {r8-r14}
|
|
ldr r3, .Lsaved_spsr_fiq
|
|
ldr r1, [r3]
|
|
msr spsr_cxsf, r1
|
|
|
|
/*
|
|
* Change to abt mode
|
|
*/
|
|
mov r1, r0
|
|
bic r1, r1, #0x1f
|
|
orr r1, r1, #0x17
|
|
msr cpsr_c, r1
|
|
|
|
/*
|
|
* Restore abt context
|
|
*/
|
|
ldr r3, .Lsaved_context_r13_abt
|
|
ldmia r3, {r13-r14}
|
|
ldr r3, .Lsaved_spsr_abt
|
|
ldr r1, [r3]
|
|
msr spsr_cxsf, r1
|
|
/*
|
|
* Change to irq mode
|
|
*/
|
|
mov r1, r0
|
|
bic r1, r1, #0x1f
|
|
orr r1, r1, #0x12
|
|
msr cpsr_c, r1
|
|
|
|
/*
|
|
* Restore irq context
|
|
*/
|
|
ldr r3, .Lsaved_context_r13_irq
|
|
ldmia r3, {r13-r14}
|
|
ldr r3, .Lsaved_spsr_irq
|
|
ldr r1, [r3]
|
|
msr spsr_cxsf, r1
|
|
|
|
/*
|
|
* Change to und mode
|
|
*/
|
|
mov r1, r0
|
|
bic r1, r1, #0x1f
|
|
orr r1, r1, #0x1b
|
|
msr cpsr_c, r1
|
|
|
|
/*
|
|
* Restore und context
|
|
*/
|
|
ldr r3, .Lsaved_context_r13_und
|
|
ldmia r3, {r13-r14}
|
|
ldr r3, .Lsaved_spsr_und
|
|
ldr r1, [r3]
|
|
msr spsr_cxsf, r1
|
|
|
|
/*
|
|
* Change to mon mode
|
|
*/
|
|
mov r1, r0
|
|
bic r1, r1, #0x1f
|
|
orr r1, r1, #0x16
|
|
msr cpsr_c, r1
|
|
|
|
/*
|
|
* Restore mon context
|
|
*/
|
|
ldr r3, .Lsaved_context_r13_mon
|
|
ldmia r3, {r13-r14}
|
|
ldr r3, .Lsaved_spsr_mon
|
|
ldr r1, [r3]
|
|
msr spsr_cxsf, r1
|
|
|
|
/*
|
|
* Restore CPSR, and Change to svc mode
|
|
*/
|
|
ldr r3, .Lsaved_cpsr_svc
|
|
ldr r1, [r3]
|
|
msr cpsr_cxsf, r1
|
|
|
|
/*
|
|
* Flush TLB (Invalidate unified TLB unlocked entries)
|
|
*/
|
|
mov r1, #0
|
|
mcr p15, 0, r1, c8, c7, 0
|
|
|
|
pop {r0-r3}
|
|
|
|
/* Set the return value */
|
|
mov r0, #0
|
|
|
|
/* return*/
|
|
mov pc, lr
|
|
|
|
.align 4
|
|
|
|
ENTRY(mem_clear_runtime_context)
|
|
push {r0-r3}
|
|
/*
|
|
* Save empty context for clear r0 - r10
|
|
*/
|
|
ldr r3, .Lsaved_empty_context_svc
|
|
mov r0, #0
|
|
str r0, [r3], #0x4
|
|
str r0, [r3], #0x4
|
|
str r0, [r3], #0x4
|
|
str r0, [r3], #0x4
|
|
str r0, [r3], #0x4
|
|
str r0, [r3], #0x4
|
|
str r0, [r3], #0x4
|
|
str r0, [r3], #0x4
|
|
str r0, [r3], #0x4
|
|
str r0, [r3], #0x4
|
|
str r0, [r3], #0x4
|
|
|
|
/*
|
|
* clear SVC context
|
|
*/
|
|
ldr r3, .Lsaved_empty_context_svc
|
|
ldmia r3, {r0-r10}
|
|
|
|
pop {r0-r3}
|
|
/* return*/
|
|
mov pc, lr
|
|
ENDPROC(mem_clear_runtime_context)
|
|
|
|
.align 4
|
|
ENTRY(disable_prefetch)
|
|
push {r0-r3}
|
|
mrc p15, 0, r0, c1, c0, 0
|
|
bic r0, r0, #(0x1 << 11) //Disable all forms of branch prediction
|
|
mcr p15, 0, r0, c1, c0, 0
|
|
|
|
// enable invalidate btb ...
|
|
mrc p15, 0, r0, c1, c0, 1
|
|
orr r0, r0, #(0x11 << 0) //Invalidate BTB, disable indirect predictor
|
|
orr r0, r0, #(0x1 << 15) //Forces in-order issue in branch execution unit
|
|
orr r0, r0, #(0xE << 20) //Disable L2 TLB prefetching, force in-order load issue, force in-order requests to the same set and way
|
|
mcr p15, 0, r0, c1, c0, 1
|
|
|
|
pop {r0-r3}
|
|
/* return*/
|
|
mov pc, lr
|
|
ENDPROC(disable_prefetch)
|
|
|
|
.align 4
|
|
.globl save_runtime_context
|
|
save_runtime_context:
|
|
/*save r0-r13 register*/
|
|
stmia r0, {r0 - r13}
|
|
mov pc, lr
|
|
|
|
|
|
.align 4
|
|
.globl clear_reg_context
|
|
clear_reg_context:
|
|
/*clear r0-r11 register*/
|
|
mov r0, #0
|
|
mov r1, #0
|
|
mov r2, #0
|
|
mov r3, #0
|
|
mov r4, #0
|
|
mov r5, #0
|
|
mov r6, #0
|
|
mov r7, #0
|
|
mov r8, #0
|
|
mov r9, #0
|
|
mov r10,#0
|
|
mov r11,#0
|
|
mov r12,#0
|
|
mov pc, lr
|
|
|
|
.Lsaved_context_r13_sys: .long saved_context_r13_sys
|
|
.Lsaved_cpsr_svc: .long saved_cpsr_svc
|
|
.Lsaved_context_r12_svc: .long saved_context_r12_svc
|
|
.Lsaved_spsr_svc: .long saved_spsr_svc
|
|
.Lsaved_context_r13_fiq: .long saved_context_r13_fiq
|
|
.Lsaved_spsr_fiq: .long saved_spsr_fiq
|
|
.Lsaved_context_r13_abt: .long saved_context_r13_abt
|
|
.Lsaved_spsr_abt: .long saved_spsr_abt
|
|
.Lsaved_context_r13_irq: .long saved_context_r13_irq
|
|
.Lsaved_spsr_irq: .long saved_spsr_irq
|
|
.Lsaved_context_r13_und: .long saved_context_r13_und
|
|
.Lsaved_spsr_und: .long saved_spsr_und
|
|
.Lsaved_context_r13_mon: .long saved_context_r13_mon
|
|
.Lsaved_spsr_mon: .long saved_spsr_mon
|
|
.Lsaved_empty_context_svc: .long saved_empty_context_svc
|
|
|
|
|
|
|
|
|
|
|