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

1. Mask all unwanted interrupts. Here we need to wake-up by only three
interrupts. GPIO0, GPIO3 (CF_nIRQ) and RTC alarm.
2. Set ICCR[DIM] bit so that only unmasked interrupts cause wake-up
from idle mode.
3. Set the I and F bits in the CPSR register to mask all interrupts.
4. Place the SDRAM into self-refresh mode.
5. Perform a frequency change sequence to 33 MHz mode.
6. Enter idle mode by selecting the POWERMODE[M] bit.
7. 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..
1. should the peripherals be disabled before doing this ???
2. 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