blob: 04cbc89e8422cc9d50118dac04b6bc870abca2c8 [file] [log] [blame]
/*
* arch/arm/mach-feroceon-kw/sleep.S
*
* Lower level support for Marvell Orion System On Chip
*
* Maintainer: Tawfik Bayouk <tawfik@marvell.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/domain.h>
#include <asm/pgtable-hwdef.h>
#include <asm/system.h>
#include "config/mvSysHwConfig.h"
.text
support_dram_self_refresh_address:
.word support_dram_self_refresh
#define FUNC(x) ENTRY(x)
#define FUNC_END(x)
#define CHANGE_MODE(x) \
mov r1, r0 ; \
bic r1, r1, #0x1f ; \
orr r1, r1, #0x##x ; \
msr cpsr_c, r1
# r0 - The address to map 0xF1000000 to.
FUNC(kw2_cpu_map_regs)
stmfd sp!, {lr}
mrc p15, 0, r1, c2, c0, 0 @ Get TTBR
ldr r2, =INTER_REGS_BASE
lsr r2, r2, #18
orr r2, r2, #0xC0000000 @ Add kernel virtual Base.
orr r1, r1, r2 @ Add TTBR base.
ldr r2, [r1]
ldr r3, =0xFFF
and r2, r2, r3
orr r0, r0, r2
str r0, [r1]
# Flush Caches So that all is writen back to DRAM
bl feroceon_flush_kern_cache_all
#if defined(CONFIG_L2_CACHE_ENABLE) || defined(CONFIG_CACHE_FEROCEON_L2)
mov r0, #0
mcr p15, 1, r0, c15, c9, 0 @ clean entire L2 cache
mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
#endif
#ifdef CONFIG_MMU
mcr p15, 0, r0, c8, c7, 0 @ invalidate I,D TLBs on v4
#endif
ldmfd sp!, {pc}
FUNC_END(kw2_cpu_suspend)
/*
* Suspend execution and enter STANDBY or SLEEP mode
*/
FUNC(kw2_cpu_suspend)
stmfd sp!, {r4-r12, lr} @ save general regs
mrc p15, 0, r2, c1, c0, 0 @ save CP15 - CR
mrc p15, 0, r3, c3, c0, 0 @ save CP15 - DACR
mrc p15, 0, r4, c13, c0, 0 @ save CP15 - FCSE
mrc p15, 0, r5, c2, c0, 0 @ save CP15 - TTBR
mov r6, r13 @ save resume SP
mrc p15, 1, r7, c15, c1, 0 @ save Marvell extra features
ldr r0, =(INTER_REGS_BASE + 0x20128)@ save L2 Config Reg
ldr r8, [r0]
stmfd sp!, {r2-r8}
/*
* Save the physical address of the resume SP
*/
mov r0, sp
bl suspend_phys_addr
ldr r1, =suspend_saved_sp
str r0, [r1]
/*
* Flush Caches So that all is writen back to DRAM
*/
bl feroceon_flush_kern_cache_all
#if defined(CONFIG_L2_CACHE_ENABLE) || defined(CONFIG_CACHE_FEROCEON_L2)
mov r0, #0
mcr p15, 1, r0, c15, c9, 0 @ clean entire L2 cache
mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
#endif
ldr r1, =(INTER_REGS_BASE + 0x200F0)
ldr r2, =(0xD0000000)
# str r2, [r1]
ldr r3, =(INTER_REGS_BASE + 0x1418)
mov r4, #0x7
mov r0, #0x0
mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
/*
** Check if dram_self_refresh is enabled.
*/
ldr r0, support_dram_self_refresh_address
ldr r0, [r0]
cmp r0, #1 @ Do we support SR?
bne 2f @ if yes, then go to WFI.
b 1f @ if no, enable SR.
.align 5
1: str r4, [r3] @ Self refresh command
2: str r2, [r1] @ Regs base to 0xD0000000
mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
# We returned immediately from suspend, restore internal regs base &
# stack pointer.
ldr r0, =0xD0000000
bl kw2_cpu_map_regs @ Map 0xF1000000 --> 0xD0000000 in MMU.
ldr r0, =(INTER_REGS_BASE + 0x200F0)
ldr r1, =INTER_REGS_BASE
str r1, [r0] @ restore regs base addr
ldr r0, =INTER_REGS_BASE
bl kw2_cpu_map_regs @ Map 0xF1000000 --> 0xF1000000 in MMU.
## ldr r3, =(INTER_REGS_BASE + 0x1418)
## mov r4, #0x0
## str r4, [r3] @ Self refresh command
## ldr r0, =(INTER_REGS_BASE + 0x12000)
## mov r1, #'F'
## str r1, [r0]
mov r0, #1
ldmfd sp!, {r2-r8}
ldmfd sp!, {r4-r12, pc}
FUNC_END(kw2_cpu_suspend)
/*
* Resume from SLEEP or STANDBY suspend
*/
.data
.align 5
FUNC(kw2_cpu_resume)
msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
## ldr r0, =(0xD0000000 + 0x12000)
## mov r1, #'O'
## str r1, [r0]
ldr r0, =0xD00200F0
ldr r1, =INTER_REGS_BASE
str r1, [r0] @ restore regs base addr
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 @ invalidate I,D caches on v4
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4
#ifdef CONFIG_MMU
mcr p15, 0, r0, c8, c7, 0 @ invalidate I,D TLBs on v4
#endif
#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
mov r0, #4 @ disable write-back on caches explicitly
mcr p15, 7, r0, c15, c0, 0
#endif
ldr r0, suspend_saved_sp @ stack phys addr
ldmfd r0, {r2-r8}
ldr r0, =(INTER_REGS_BASE + 0x20128)
str r8, [r0] @ restorem L2 Config Reg
mcr p15, 1, r7, c15, c1, 0 @ restore Marvell Extra Features
mcr p15, 0, r5, c2, c0, 0 @ restore CP15 - TTBR
mcr p15, 0, r4, c13, c0, 0 @ restore CP15 - FCSE
mcr p15, 0, r3, c3, c0, 0 @ restore CP15 - DACR
ldr r3, =resume_after_mmu @ virtual address jump
b resume_turn_on_mmu @ cache align
.align 5
resume_turn_on_mmu:
mcr p15, 0, r2, c1, c0, 0 @ restore CP15 - CR
nop
mov pc, r3 @ jump to virtual addr
nop
nop
nop
suspend_saved_sp:
.word 0 @ physical SP saved here
.text
resume_after_mmu:
mov r13, r6 @ restore virtual SP
mov r0, #0x0
ldmfd sp!, {r4-r12, pc} @ restore SVC registers
FUNC_END(kw2_cpu_resume)
.end