Hi, We have an issue related to implementing the idle 33Mhz mode in PXA255. We follow the steps that are provided in PXA255 developer's manual
- Mask all unwanted interrupts. Here we need to wake-up by only three interrupts. GPIO0, GPIO3 (CF_nIRQ) and RTC alarm.
- Set ICCR[DIM] bit so that only unmasked interrupts cause wake-up from idle mode.
- Set the I and F bits in the CPSR register to mask all interrupts.
- Place the SDRAM into self-refresh mode.
- Perform a frequency change sequence to 33 MHz mode.
- Enter idle mode by selecting the POWERMODE[M] bit.
- Wait for some time to finish the execution of idle mode.
But we find that the system hangs when the SDRAM is put into the self-refresh mode. We wish to know if the above code is enough. or is there any pre-requisites to implementing the 33Mhz idle mode, those which are not mentioned in the PXA255 developer's manual ?
We have a few doubts as well..
- should the peripherals be disabled before doing this ???
- how do the instructions get into the cache ?? is there is any specific instruction for that ??? ( we have used .align here.... )
The code implementation is as follows
===================================================================
#include #include #include #include
#include
.text
/* * pxa_cpu_idle33() * * Forces CPU into idle 33 Mhz state */ ENTRY(pxa_cpu_idle33)
stmfd sp!, {r1 - r12, lr} @ save registers on stack
ldr r0, =ICMR @interrupt mask register ldr r1, [r0] stmfd sp!, {r1} @save the content of ICMR register mov r1, #0x80000000 @Unmask interrupt for RTC alarm orr r1, r1, #0x500 @Unmask interrupts for GPIO0 and GPIO[2:84] str r1, [r0]
ldr r0, =GRER0 @Rising edge detect register ldr r1, [r0] orr r1, r1, #9 @Rising edge detect enable for GPIO0 and nCF_IRQ str r1, [r0]
ldr r0, =GFER0 @falling edge detect register ldr r1, [r0] orr r1, r1, #9 @falling edge detect enable for GPIO0 and nCF_IRQ str r1, [r0]
ldr r0, =ICCR mov r1, #1 str r1, [r0] @ Set ICCR[DIM] bit so only enabled interrupts wake-up up
@ Mask all interrupts using CPSR, Set I and F bits in CPSR mrs r0, cpsr orr r0, r0, #PSR_I_BIT | PSR_F_BIT @disable IRQ and FIQ interrupts
msr cpsr_c, r0
@ prepare value for idle mode mov r1, #1 @ idle mode
@ Prepare the SDRAM to self refresh mode ldr r4, =MDREFR ldr r5, [r4] orr r5, r5, #MDREFR_SLFRSH
@ keep original value for resume in normal mode ldr r6, =CCCR ldr r8, [r6]
@ Prepare frequency change to 33Mhz mov r7, #0x3f orr r7, r7, #0x100 @ value 0x13f to store in CCCR for 33MHz
@ get ready for the change mrc p14, 0, r0, c6, c0, 0 bic r0, r0, #2 @ clear change bit mcr p14, 0, r0, c6, c0, 0 orr r0, r0, #2 @ initiate change bit
@ align execution to a cache line b 1f
.ltorg .align 5
1: @ All needed values are now in registers. @ These last instructions should be in cache@ put SDRAM into self-refresh @str r5, [r4]
@ initiate the frequency change... str r7, [r6] mcr p14, 0, r0, c6, c0, 0
@ restore the original cpu speed value for resume str r8, [r6]
@ enter idle mode mcr p14, 0, r1, c7, c0, 0
mov r6, #0xff wait_for_idle: sub r6, r6,#1 @ loop waiting for idle is some time required. teq r6, #0 bne wait_for_idle
@ Exit from Idle Mode
@ Perform frequency change to Run mode @ the run mode cpu speed value present in CCCR mrc p14, 0, r0, c6, c0, 0 bic r0, r0, #2 @ clear change bit of CCLKCFG mcr p14, 0, r0, c6, c0, 0 orr r0, r0, #2 @ initiate change bit mcr p14, 0, r0, c6, c0, 0
@ Take SDRAM outof self refresh ldr r4, =MDREFR ldr r5, [r4] bic r5, r5, #MDREFR_SLFRSH str r5, [r4]
@restore the value of ICMR ldmfd sp!, {r1} ldr r0, =ICMR str r1, [r0]
@ Clear I and F bits in CPSR mrs r0, cpsr bic r0, r0, #PSR_I_BIT | PSR_F_BIT @enable IRQ and FIQ interrupts
msr cpsr_c, r0
ldmfd sp!, {r1 - r12, pc} @ return to caller
===================================================================
Sameer