mirror of
https://github.com/Stichting-MINIX-Research-Foundation/netbsd.git
synced 2025-08-31 08:50:34 -04:00
588 lines
15 KiB
ArmAsm
588 lines
15 KiB
ArmAsm
/* $OpenBSD: pxa2x0_apm_asm.S,v 1.4 2007/11/02 05:18:25 miod Exp $ */
|
|
|
|
/*
|
|
* Copyright (c) 2005 Uwe Stuehler <uwe@openbsd.org>
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#include <arm/asm.h>
|
|
#include <arm/locore.h>
|
|
|
|
#include <arch/arm/xscale/pxa2x0reg.h>
|
|
#include <arch/arm/sa11x0/sa11x0_reg.h>
|
|
|
|
/* XXX replace with values defined elsewhere. */
|
|
#define DCACHE_CACHELINECOUNT 1024
|
|
#define CACHELINESIZE 32
|
|
#define DCACHE_SIZE (CACHELINESIZE * DCACHE_CACHELINECOUNT)
|
|
|
|
/* cp14 register 6 */
|
|
#define CLKCFG_T (1<<0) /* turbo */
|
|
#define CLKCFG_F (1<<1) /* frequency change */
|
|
#define CLKCFG_HT (1<<2) /* half-turbo */
|
|
#define CLKCFG_B (1<<3) /* fast-bus */
|
|
|
|
/* cp14 register 7 */
|
|
#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)
|
|
|
|
/* XXX */
|
|
#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 /* PXA271 */ | \
|
|
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 /* PXA271 */ | \
|
|
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 /* XXX */
|
|
.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
|
|
|
|
/*
|
|
* void pxa2x0_cpu_suspend(void)
|
|
*
|
|
* Enter sleep mode without automatic voltage change. The core must
|
|
* be in low power mode, and interrupts disabled.
|
|
*/
|
|
ENTRY(pxa2x0_cpu_suspend)
|
|
stmdb sp!, {r0-r12, lr}
|
|
|
|
ldr r3, .Lsleepdata /* Point to the data area. */
|
|
ldr r2, =pxa2x0_cpu_resume_virt
|
|
str r2, [r3], #4
|
|
|
|
mrc p15, 0, r2, c1, c0, 0 /* Load MMU control register. */
|
|
mov r0, #0xff000000
|
|
orr r0, r0, #0x00ff0000
|
|
bic r2, r2, r0 /* Clear undefined bits. */
|
|
str r2, [r3], #4 /* Save MMU control register. */
|
|
|
|
mrc p15, 0, r2, c2, c0, 0 /* Load TTB address. */
|
|
mov r0, #0x00003f00
|
|
orr r0, r0, #0x000000ff
|
|
bic r2, r2, r0 /* Clear undefined bits. */
|
|
str r2, [r3], #4 /* Save TTB address. */
|
|
|
|
mrc p15, 0, r2, c3, c0, 0 /* Load domain access control. */
|
|
str r2, [r3], #4 /* Save domain access control. */
|
|
|
|
mrs r2, spsr /* Load SVC saved CPSR. */
|
|
str r2, [r3], #4 /* Save SVC saved CPSR. */
|
|
str sp, [r3], #4 /* Save SVC stack pointer. */
|
|
|
|
mov r1, #(PSR_FIQ32_MODE | I32_bit | F32_bit)
|
|
msr cpsr, r1 /* Enter FIQ mode. */
|
|
mrs r2, spsr /* Load FIQ mode saved CPSR. */
|
|
stmia r3!, {r2, r8-r12, sp, lr} /* Save FIQ mode registers. */
|
|
|
|
mov r1, #(PSR_IRQ32_MODE | I32_bit | F32_bit)
|
|
msr cpsr, r1 /* Enter IRQ mode. */
|
|
mrs r0, spsr /* Load IRQ mode saved CPSR. */
|
|
stmia r3!, {r0, sp, lr} /* Save IRQ mode registers. */
|
|
|
|
mov r1, #(PSR_ABT32_MODE | I32_bit | F32_bit)
|
|
msr cpsr, r1 /* Enter ABT mode. */
|
|
mrs r0, spsr /* Load ABT mode saved CPSR. */
|
|
stmia r3!, {r0, sp, lr} /* Save ABT mode registers. */
|
|
|
|
mov r1, #(PSR_UND32_MODE | I32_bit | F32_bit)
|
|
msr cpsr, r1 /* Enter UND mode. */
|
|
mrs r0, spsr /* Load UND mode saved CPSR. */
|
|
stmia r3!, {r0, sp, lr} /* Save UND mode registers. */
|
|
|
|
mov r1, #(PSR_SYS32_MODE | I32_bit | F32_bit)
|
|
msr cpsr, r1 /* Enter SYS mode. */
|
|
stmia r3!, {sp, lr} /* Save SYS mode registers. */
|
|
|
|
mov r1, #(PSR_SVC32_MODE | I32_bit | F32_bit)
|
|
msr cpsr, r1 /* Return to SVC mode. */
|
|
|
|
/* At this point all critical registers have been saved. */
|
|
|
|
mov r0, #0
|
|
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
|
|
|
|
mov r1, #DCACHE_CACHELINECOUNT
|
|
ldr r2, .Lxscale_cache_clean_addr
|
|
ldr r0, [r2]
|
|
/*
|
|
* For an explanation of the following two instructions, refer
|
|
* to the ``BUG ALERT'' section of the XSCALE_CACHE_CLEAN_PROLOGUE
|
|
* macro in arch/arm/arm/cpufunc_asm_xscale.S.
|
|
*/
|
|
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 /* disable IRQ/FIQ */
|
|
|
|
mcr p15, 0, r0, c7, c2, 5 /* allocate cache line */
|
|
mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */
|
|
|
|
mrs r2, cpsr
|
|
and r2, r2, #~(I32_bit|F32_bit)
|
|
msr cpsr_c, r2 /* enable IRQ/FIQ */
|
|
|
|
add r0, r0, #CACHELINESIZE
|
|
subs r1, r1, #1
|
|
bne cache_flush_loop
|
|
|
|
mov r0, #0
|
|
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
|
|
|
|
b 1f
|
|
1:
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
|
|
/* Prepare to enter sleep mode. */
|
|
mov r1, #PWRMODE_SLEEP
|
|
|
|
/* Prepare to put SDRAM into self-refresh mode. */
|
|
ldr r4, .Lmemctliohp
|
|
ldr r4, [r4]
|
|
add r4, r4, #MEMCTL_MDREFR
|
|
ldr r5, [r4]
|
|
orr r5, r5, #MDREFR_SLFRSH
|
|
|
|
/* XXX prepare pointer to physical address 0, but for whom? */
|
|
ldr r2, .Lvector_page
|
|
|
|
/*
|
|
* Execute the rest of this routine from cache. The needed values
|
|
* are now in registers.
|
|
*/
|
|
b 1f
|
|
/* XXX tell as(1) to dump the literal pool here, but why? */
|
|
.ltorg
|
|
.align 5
|
|
1:
|
|
|
|
/* Put SDRAM into self-refresh mode manually. */
|
|
str r5, [r4]
|
|
nop
|
|
|
|
/*
|
|
* Enter sleep mode. Exit from sleep mode returns the processor
|
|
* to normal run mode. Execution resumes at the physical address
|
|
* stored in the PSPR after the required boot sequence (a short
|
|
* excursion into the ROM boot loader).
|
|
*/
|
|
mcr p14, 0, r1, c7, c0, 0
|
|
|
|
/* Just in case that wake-up does not resume at */
|
|
nop
|
|
nop
|
|
nop
|
|
1:
|
|
b 1b
|
|
|
|
/*
|
|
* void pxa2x0_cpu_resume(void)
|
|
*/
|
|
.align 5
|
|
ENTRY(pxa2x0_cpu_resume)
|
|
/* XXX C3000-specific */
|
|
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 /* Point to PA of saved data. */
|
|
|
|
ldmia r0!, {r7-r10}
|
|
mcr p15, 0, r10, c3, c0, 0 /* Restore domain access control. */
|
|
mcr p15, 0, r9, c2, c0, 0 /* Restore TTB address. */
|
|
mcr p15, 0, r0, c8, c7, 0 /* Flush I+D TLBs. */
|
|
mcr p15, 0, r0, c7, c7, 0 /* Flush I+D BTB. */
|
|
mcr p15, 0, r8, c1, c0, 0 /* Restore MMU control. */
|
|
mov pc, r7 /* Jump to virtual address. */
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
|
|
pxa2x0_cpu_resume_virt:
|
|
ldr r2, .Lsleepdata_svc /* Load VA of saved registers. */
|
|
|
|
/* Restore SVC mode SPSR and stack pointer. */
|
|
ldr r0, [r2], #4
|
|
msr spsr, r0
|
|
ldr sp, [r2], #4
|
|
|
|
/* Restore FIQ mode registers. */
|
|
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
|
|
|
|
/* Restore IRQ mode registers. */
|
|
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
|
|
|
|
/* Restore ABT mode registers. */
|
|
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
|
|
|
|
/* Restore UND mode registers. */
|
|
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
|
|
|
|
/* Restore SYS mode registers. */
|
|
mov r1, #(PSR_SYS32_MODE | I32_bit | F32_bit)
|
|
msr cpsr, r1
|
|
ldr sp, [r2], #4
|
|
ldr lr, [r2], #4
|
|
|
|
/* Return to SVC mode. */
|
|
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
|
|
|
|
/*
|
|
* Saved processor state
|
|
*/
|
|
.align 5
|
|
sleepdata:
|
|
.word 0 /* =pxa2x0_cpu_resume_virt */
|
|
.word 0 /* MMU control */
|
|
.word 0 /* MMU TTB address */
|
|
.word 0 /* MMU domain access control */
|
|
sleepdata_svc:
|
|
.word 0 /* SVC mode saved CPSR */
|
|
.word 0 /* SVC mode stack pointer */
|
|
.word 0 /* FIQ mode saved CPSR */
|
|
.word 0 /* FIQ mode r8 */
|
|
.word 0 /* FIQ mode r9 */
|
|
.word 0 /* FIQ mode r10 */
|
|
.word 0 /* FIQ mode r11 */
|
|
.word 0 /* FIQ mode r12 */
|
|
.word 0 /* FIQ mode stack pointer */
|
|
.word 0 /* FIQ mode link register */
|
|
.word 0 /* IRQ mode saved CPSR */
|
|
.word 0 /* IRQ mode stack pointer */
|
|
.word 0 /* IRQ mode link register */
|
|
.word 0 /* ABT mode saved CPSR */
|
|
.word 0 /* ABT mode stack pointer */
|
|
.word 0 /* ABT mode link register */
|
|
.word 0 /* UND mode saved CPSR */
|
|
.word 0 /* UND mode stack pointer */
|
|
.word 0 /* UND mode link register */
|
|
.word 0 /* SYS mode stack pointer */
|
|
.word 0 /* SYS mode link register */
|
|
|
|
.text
|
|
|
|
/*
|
|
* void pxa27x_run_mode(void)
|
|
*
|
|
* Disable half-turbo and turbo mode, but keep fast-bus mode.
|
|
* Memory and LCD clock is not changed, so no reconfiguration is
|
|
* necessary.
|
|
*/
|
|
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
|
|
|
|
/*
|
|
* void pxa27x_fastbus_run_mode(int enable, uint32_t mdrefr)
|
|
*
|
|
* Enter normal run mode with fast-bus mode enabled or disabled.
|
|
* The new value of MDREFR is programmed before or after CLKCFG,
|
|
* as appropriate.
|
|
*/
|
|
.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:
|
|
/* Enter normal run mode with fast-bus mode enabled. */
|
|
mov r0, #CLKCFG_B
|
|
mcr p14, 0, r0, c6, c0, 0
|
|
/* Set the new SDRAM refresh rate. */
|
|
str r1, [r2, #MEMCTL_MDREFR]
|
|
ldr r0, [r2, #MEMCTL_MDREFR]
|
|
mov r0, r0
|
|
ldmia sp!, {r0-r2, pc}
|
|
.align 5
|
|
disable_fastbus:
|
|
/* Set the new SDRAM refresh rate. */
|
|
str r1, [r2, #MEMCTL_MDREFR]
|
|
ldr r0, [r2, #MEMCTL_MDREFR]
|
|
mov r0, r0
|
|
/* Enter normal run mode with fast-bus mode disabled. */
|
|
mov r0, #0x0
|
|
mcr p14, 0, r0, c6, c0, 0
|
|
ldmia sp!, {r0-r2, pc}
|
|
|
|
/* Keep these offsets in sync with struct memcfg. */
|
|
#define memcfg_mdrefr_high 0x00
|
|
#define memcfg_mdrefr_low 0x04
|
|
#define memcfg_mdrefr_low2 0x08 /* unused */
|
|
#define memcfg_msc_high 0x0c
|
|
#define memcfg_msc_low 0x18
|
|
#define memcfg_mdrefr_91 0x24
|
|
|
|
/*
|
|
* void pxa27x_frequency_change(int cccr, int clkcfg,
|
|
* struct pxa2x0_memcfg *memcfg)
|
|
*
|
|
* Change the core PLL frequency and SDRAM refresh rate, ensuring the
|
|
* proper sequence of operations. If the CCCR_A bit is clear and L
|
|
* is not equal to 7 the result is undefined.
|
|
*/
|
|
.align 5
|
|
ENTRY(pxa27x_frequency_change)
|
|
stmdb sp!, {r0-r5, lr}
|
|
|
|
/* Always write to CCCR before a frequency change. */
|
|
ldr r3, .Lclkmaniohp
|
|
ldr r3, [r3]
|
|
str r0, [r3, #CLKMAN_CCCR]
|
|
|
|
/* Load the needed values into registers to avoid SDRAM access. */
|
|
and r3, r0, #CCCR_L_MASK
|
|
ldr r0, .Lmemctliohp
|
|
ldr r0, [r0]
|
|
cmp r3, #CCCR_RUN_X7 /* L=7 is 91MHz mode */
|
|
beq frequency_change_91
|
|
and r3, r1, #CLKCFG_B
|
|
cmp r3, #CLKCFG_B
|
|
bne frequency_change_208
|
|
/* FALLTHROUGH */
|
|
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 /* XXX why BL? */
|
|
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 execution to a cache line. */
|
|
.align 5
|
|
frequency_change_on_cache:
|
|
/* Change to a low SDRAM refresh rate. Wait until the store to
|
|
* MDREFR is complete, following section 2.4 I/O Ordering and
|
|
* 6.5.1.4 of the PXA27x Developer's Manual. */
|
|
str r3, [r0, #MEMCTL_MDREFR]
|
|
ldr r5, [r0, #MEMCTL_MDREFR]
|
|
mov r5, r5
|
|
/* Program new CLKCFG value, starting a core PLL frequency change
|
|
* if CLKCFG_F is set. */
|
|
mcr p14, 0, r1, c6, c0, 0
|
|
/* Change SDRAM clock frequency to 104MHz, and ensure that the
|
|
* store to MDREFR is complete before the next SDRAM access. */
|
|
str r4, [r0, #MEMCTL_MDREFR]
|
|
ldr r5, [r0, #MEMCTL_MDREFR]
|
|
mov r5, r5
|
|
/* Configure synchronous, static, and VLIO interfaces. */
|
|
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}
|
|
|
|
/*
|
|
* void pxa27x_cpu_speed_91(void)
|
|
*
|
|
* Switch core run frequency to 91 MHz.
|
|
*/
|
|
.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
|