#include <arm/asm.h>
#include <arm/locore.h>
#include <arch/arm/xscale/pxa2x0reg.h>
#include <arch/arm/sa11x0/sa11x0_reg.h>
#define DCACHE_CACHELINECOUNT 1024
#define CACHELINESIZE 32
#define DCACHE_SIZE (CACHELINESIZE * DCACHE_CACHELINECOUNT)
#define CLKCFG_T (1<<0)
#define CLKCFG_F (1<<1)
#define CLKCFG_HT (1<<2)
#define CLKCFG_B (1<<3)
#define PWRMODE_NORMAL (0<<0)
#define PWRMODE_IDLE (1<<0)
#define PWRMODE_STANDBY (2<<0)
#define PWRMODE_SLEEP (3<<0)
#define PWRMODE_DEEP_SLEEP (7<<0)
#define MDREFR_C3000 (MDREFR_K0DB2|MDREFR_E1PIN|MDREFR_K1RUN|\
MDREFR_K1DB2|MDREFR_K2DB2|MDREFR_APD)
#define MDREFR_DRI_91MHZ (0x13<<0)
#define MDREFR_HIGH (MDREFR_C3000 | 0x030)
#define MDREFR_LOW (MDREFR_C3000 | 0x00b)
#define MDREFR_SPEED_91 (MDREFR_C3000 | MDREFR_DRI_91MHZ)
#define MDREFR_SPEED_LOW (MDREFR_C3000 | 0x017)
#define MSC0_HIGH \
( 7 << MSC_RRR_SHIFT << 16) | \
(15 << MSC_RDN_SHIFT << 16) | \
(15 << MSC_RDF_SHIFT << 16) | \
(MSC_RT_NONBURST << 16) | \
( 2 << MSC_RRR_SHIFT) | \
(13 << MSC_RDN_SHIFT) | \
(13 << MSC_RDF_SHIFT) | \
MSC_RBW | \
MSC_RT_NONBURST
#define MSC1_HIGH \
( 7 << MSC_RRR_SHIFT << 16) | \
(15 << MSC_RDN_SHIFT << 16) | \
(15 << MSC_RDF_SHIFT << 16) | \
(MSC_RT_VLIO << 16) | \
( 3 << MSC_RRR_SHIFT) | \
( 4 << MSC_RDN_SHIFT) | \
(13 << MSC_RDF_SHIFT) | \
MSC_RT_VLIO
#define MSC2_HIGH \
( 7 << MSC_RRR_SHIFT << 16) | \
(15 << MSC_RDN_SHIFT << 16) | \
(15 << MSC_RDF_SHIFT << 16) | \
(MSC_RT_NONBURST << 16) | \
( 3 << MSC_RRR_SHIFT) | \
( 4 << MSC_RDN_SHIFT) | \
(13 << MSC_RDF_SHIFT) | \
MSC_RT_VLIO
#define MSC0_LOW \
( 7 << MSC_RRR_SHIFT << 16) | \
(15 << MSC_RDN_SHIFT << 16) | \
(15 << MSC_RDF_SHIFT << 16) | \
(MSC_RT_NONBURST << 16) | \
( 1 << MSC_RRR_SHIFT) | \
( 8 << MSC_RDN_SHIFT) | \
( 8 << MSC_RDF_SHIFT) | \
MSC_RBW | \
MSC_RT_NONBURST
#define MSC1_LOW \
( 7 << MSC_RRR_SHIFT << 16) | \
(15 << MSC_RDN_SHIFT << 16) | \
(15 << MSC_RDF_SHIFT << 16) | \
(MSC_RT_VLIO << 16) | \
( 1 << MSC_RRR_SHIFT) | \
( 2 << MSC_RDN_SHIFT) | \
( 6 << MSC_RDF_SHIFT) | \
MSC_RT_VLIO
#define MSC2_LOW \
( 7 << MSC_RRR_SHIFT << 16) | \
(15 << MSC_RDN_SHIFT << 16) | \
(15 << MSC_RDF_SHIFT << 16) | \
(MSC_RT_NONBURST << 16) | \
( 1 << MSC_RRR_SHIFT) | \
( 2 << MSC_RDN_SHIFT) | \
( 6 << MSC_RDF_SHIFT) | \
MSC_RT_VLIO
.text
.global _C_LABEL(vector_page)
.global _C_LABEL(xscale_cache_clean_addr)
.global _C_LABEL(pxa2x0_clkman_ioh)
.global _C_LABEL(pxa2x0_memctl_ioh)
.Lvector_page:
.word _C_LABEL(vector_page)
.Lxscale_cache_clean_addr:
.word _C_LABEL(xscale_cache_clean_addr)
.Lgpioiohp: .word _C_LABEL(pxa2x0_gpio_ioh)
.Lclkmaniohp: .word _C_LABEL(pxa2x0_clkman_ioh)
.Lmemctliohp: .word _C_LABEL(pxa2x0_memctl_ioh)
.Lsleepdata: .word sleepdata
.Lsleepdata_phys: .word sleepdata - 0xc0200000 + 0xa0200000
.Lsleepdata_svc: .word sleepdata_svc
.Lcccr_high: .word CCCR_A | CCCR_TURBO_X2 | CCCR_RUN_X16
.Lmdrefr_high: .word MDREFR_HIGH
.Lmsc0_high: .word MSC0_HIGH
.Lmsc1_high: .word MSC1_HIGH
.Lmsc2_high: .word MSC2_HIGH
.Lmdrefr_low: .word MDREFR_LOW
.Lmsc0_low: .word MSC0_LOW
.Lmsc1_low: .word MSC1_LOW
.Lmsc2_low: .word MSC2_LOW
ENTRY(pxa2x0_cpu_suspend)
stmdb sp!, {r0-r12, lr}
ldr r3, .Lsleepdata
ldr r2, =pxa2x0_cpu_resume_virt
str r2, [r3], #4
mrc p15, 0, r2, c1, c0, 0
mov r0, #0xff000000
orr r0, r0, #0x00ff0000
bic r2, r2, r0
str r2, [r3], #4
mrc p15, 0, r2, c2, c0, 0
mov r0, #0x00003f00
orr r0, r0, #0x000000ff
bic r2, r2, r0
str r2, [r3], #4
mrc p15, 0, r2, c3, c0, 0
str r2, [r3], #4
mrs r2, spsr
str r2, [r3], #4
str sp, [r3], #4
mov r1, #(PSR_FIQ32_MODE | I32_bit | F32_bit)
msr cpsr, r1
mrs r2, spsr
stmia r3!, {r2, r8-r12, sp, lr}
mov r1, #(PSR_IRQ32_MODE | I32_bit | F32_bit)
msr cpsr, r1
mrs r0, spsr
stmia r3!, {r0, sp, lr}
mov r1, #(PSR_ABT32_MODE | I32_bit | F32_bit)
msr cpsr, r1
mrs r0, spsr
stmia r3!, {r0, sp, lr}
mov r1, #(PSR_UND32_MODE | I32_bit | F32_bit)
msr cpsr, r1
mrs r0, spsr
stmia r3!, {r0, sp, lr}
mov r1, #(PSR_SYS32_MODE | I32_bit | F32_bit)
msr cpsr, r1
stmia r3!, {sp, lr}
mov r1, #(PSR_SVC32_MODE | I32_bit | F32_bit)
msr cpsr, r1
mov r0, #0
mcr p15, 0, r0, c7, c10, 4
mov r1, #DCACHE_CACHELINECOUNT
ldr r2, .Lxscale_cache_clean_addr
ldr r0, [r2]
eor r0, r0, #(DCACHE_SIZE)
str r0, [r2]
cache_flush_loop:
mrs r2, cpsr
orr r2, r2, #(I32_bit|F32_bit)
msr cpsr_c, r2
mcr p15, 0, r0, c7, c2, 5
mcr p15, 0, r0, c7, c6, 1
mrs r2, cpsr
and r2, r2, #~(I32_bit|F32_bit)
msr cpsr_c, r2
add r0, r0, #CACHELINESIZE
subs r1, r1, #1
bne cache_flush_loop
mov r0, #0
mcr p15, 0, r0, c7, c10, 4
b 1f
1:
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
mov r1, #PWRMODE_SLEEP
ldr r4, .Lmemctliohp
ldr r4, [r4]
add r4, r4, #MEMCTL_MDREFR
ldr r5, [r4]
orr r5, r5, #MDREFR_SLFRSH
ldr r2, .Lvector_page
b 1f
.ltorg
.align 5
1:
str r5, [r4]
nop
mcr p14, 0, r1, c7, c0, 0
nop
nop
nop
1:
b 1b
.align 5
ENTRY(pxa2x0_cpu_resume)
ldr r0, .Lmdrefr_addr_phys
b 1f
.align 5
1:
ldr r2, [r0]
bic r2, r2, #MDREFR_DRI & 0x000000ff
bic r2, r2, #MDREFR_DRI & 0x0000ff00
orr r2, r2, #MDREFR_DRI_91MHZ
str r2, [r0]
b 1f
.align 5
1:
ldr r0, .Lsleepdata_phys
ldmia r0!, {r7-r10}
mcr p15, 0, r10, c3, c0, 0
mcr p15, 0, r9, c2, c0, 0
mcr p15, 0, r0, c8, c7, 0
mcr p15, 0, r0, c7, c7, 0
mcr p15, 0, r8, c1, c0, 0
mov pc, r7
nop
nop
nop
nop
nop
nop
nop
nop
pxa2x0_cpu_resume_virt:
ldr r2, .Lsleepdata_svc
ldr r0, [r2], #4
msr spsr, r0
ldr sp, [r2], #4
mov r1, #(PSR_FIQ32_MODE | I32_bit | F32_bit)
msr cpsr, r1
ldr r0, [r2], #4
msr spsr, r0
ldr r8, [r2], #4
ldr r9, [r2], #4
ldr r10, [r2], #4
ldr r11, [r2], #4
ldr r12, [r2], #4
ldr sp, [r2], #4
ldr lr, [r2], #4
mov r1, #(PSR_IRQ32_MODE | I32_bit | F32_bit)
msr cpsr, r1
ldr r0, [r2], #4
msr spsr, r0
ldr sp, [r2], #4
ldr lr, [r2], #4
mov r1, #(PSR_ABT32_MODE | I32_bit | F32_bit)
msr cpsr, r1
ldr r0, [r2], #4
msr spsr, r0
ldr sp, [r2], #4
ldr lr, [r2], #4
mov r1, #(PSR_UND32_MODE | I32_bit | F32_bit)
msr cpsr, r1
ldr r0, [r2], #4
msr spsr, r0
ldr sp, [r2], #4
ldr lr, [r2], #4
mov r1, #(PSR_SYS32_MODE | I32_bit | F32_bit)
msr cpsr, r1
ldr sp, [r2], #4
ldr lr, [r2], #4
mov r1, #(PSR_SVC32_MODE | I32_bit | F32_bit)
msr cpsr, r1
ldmia sp!, {r0-r12, pc}
.Lmdrefr_addr_phys:
.word PXA2X0_MEMCTL_BASE + MEMCTL_MDREFR
.data
.align 5
sleepdata:
.word 0
.word 0
.word 0
.word 0
sleepdata_svc:
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.text
ENTRY(pxa27x_run_mode)
stmdb sp!, {r0}
mrc p14, 0, r0, c6, c0, 0
and r0, r0, #~(CLKCFG_HT | CLKCFG_F| CLKCFG_T)
mcr p14, 0, r0, c6, c0, 0
ldmia sp!, {r0}
mov pc, lr
.align 5
ENTRY(pxa27x_fastbus_run_mode)
stmdb sp!, {r0-r2, lr}
ldr r2, .Lmemctliohp
ldr r2, [r2]
cmp r0, #0
beq disable_fastbus
b enable_fastbus
.align 5
enable_fastbus:
mov r0, #CLKCFG_B
mcr p14, 0, r0, c6, c0, 0
str r1, [r2, #MEMCTL_MDREFR]
ldr r0, [r2, #MEMCTL_MDREFR]
mov r0, r0
ldmia sp!, {r0-r2, pc}
.align 5
disable_fastbus:
str r1, [r2, #MEMCTL_MDREFR]
ldr r0, [r2, #MEMCTL_MDREFR]
mov r0, r0
mov r0, #0x0
mcr p14, 0, r0, c6, c0, 0
ldmia sp!, {r0-r2, pc}
#define memcfg_mdrefr_high 0x00
#define memcfg_mdrefr_low 0x04
#define memcfg_mdrefr_low2 0x08
#define memcfg_msc_high 0x0c
#define memcfg_msc_low 0x18
#define memcfg_mdrefr_91 0x24
.align 5
ENTRY(pxa27x_frequency_change)
stmdb sp!, {r0-r5, lr}
ldr r3, .Lclkmaniohp
ldr r3, [r3]
str r0, [r3, #CLKMAN_CCCR]
and r3, r0, #CCCR_L_MASK
ldr r0, .Lmemctliohp
ldr r0, [r0]
cmp r3, #CCCR_RUN_X7
beq frequency_change_91
and r3, r1, #CLKCFG_B
cmp r3, #CLKCFG_B
bne frequency_change_208
frequency_change_high:
ldr r3, [r2, #memcfg_mdrefr_low]
ldr r4, [r2, #memcfg_mdrefr_high]
add r2, r2, #memcfg_msc_high
bl frequency_change_on_cache
frequency_change_208:
ldr r3, [r2, #memcfg_mdrefr_low]
ldr r4, [r2, #memcfg_mdrefr_low]
add r2, r2, #memcfg_msc_high
bl frequency_change_on_cache
frequency_change_91:
ldr r3, [r2, #memcfg_mdrefr_low]
ldr r4, [r2, #memcfg_mdrefr_91]
add r2, r2, #memcfg_msc_low
bl frequency_change_on_cache
.align 5
frequency_change_on_cache:
str r3, [r0, #MEMCTL_MDREFR]
ldr r5, [r0, #MEMCTL_MDREFR]
mov r5, r5
mcr p14, 0, r1, c6, c0, 0
str r4, [r0, #MEMCTL_MDREFR]
ldr r5, [r0, #MEMCTL_MDREFR]
mov r5, r5
ldr r1, [r2], #4
str r1, [r0, #MEMCTL_MSC0]
ldr r1, [r2], #4
str r1, [r0, #MEMCTL_MSC1]
ldr r1, [r2]
str r1, [r0, #MEMCTL_MSC2]
ldmia sp!, {r0-r5, pc}
.align 5
ENTRY(pxa27x_cpu_speed_91)
stmdb sp!, {r0-r3, lr}
ldr r0, .Lclkmaniohp
ldr r0, [r0]
ldr r1, .Lcccr_91
str r1, [r0, #CLKMAN_CCCR]
ldr r0, .Lmemctliohp
ldr r0, [r0]
ldr r2, .Lmdrefr_91
ldr r3, .Lmdrefr_low
bl 1f
.align 5
1:
str r3, [r0, #MEMCTL_MDREFR]
ldr r3, [r0, #MEMCTL_MDREFR]
mov r1, #CLKCFG_F
mcr p14, 0, r1, c6, c0, 0
str r2, [r0, #MEMCTL_MDREFR]
ldr r2, [r0, #MEMCTL_MDREFR]
ldr r1, .Lmsc0_low
str r1, [r0, #MEMCTL_MSC0]
ldr r1, .Lmsc1_low
str r1, [r0, #MEMCTL_MSC1]
ldr r1, .Lmsc2_low
str r1, [r0, #MEMCTL_MSC2]
ldmia sp!, {r0-r3, pc}
.Lcccr_91: .word CCCR_TURBO_X1 | CCCR_RUN_X7
.Lmdrefr_91: .word MDREFR_SPEED_91