I am attempting to place an iMX25 SDRAM into manual self-refresh mode, reset the PLL and then set the SDRAM controller back into normal mode.
As soon as I attempt to place the SDRAM controller into manual-self refresh the CPU locks up and the watchdog resets the device.
Here is the code I am using:
LEAF_ENTRY OALCPUEnterSuspend
mov r0,#0 mcr p15, 0, r0, c7, c0, 4 ; Enter WFI
; Exit Wait For Interrupt set SDRAM to manual self-refresh
ldr r1, =CSP_BASE_REG_PA_ESDCTL ldr r2, =CSP_BASE_MEM_PA_CSD0
; Set precharge command ldr r0, =0x93118880 str r0, [r1, #ESDRAMC_ESDCTL0_OFFSET]
; Access SDRAM with A10 high to precharge all banks ldr r0, =0x0 strb r0, [r2, #0x400]
; Set manual refresh command ldr r0, =0xC3118880 str r0, [r1, #ESDRAMC_ESDCTL0_OFFSET]
; Wait for more than 400 us ldr r3, =0x20000 wait subs r3, r3, #1 bne wait
; Configure Clock Control Register ; Configure ARM and AHB Clock ; ; ARM Clock 399Mhz = MCUPLL * DIVGEN / ARM_DIVIDER ; = 532Mhz * 0.75 / 1 ; = 399 Mhz ; ARM_DIVIDER (0 << 30) = 0x00000000 ; ARM_SRC (1 << 14) = 0x00004000 ; ; AHB Clock 133Mhz = ARMCLK / AHB_DIVIDER ; = 399Mhz / 3 ; = 133 Mhz ; AHB_DIVIDER (2 << 28) = 0x20000000 ; ; USB Clock 60Mhz = UPLL / USB_DIVIDER ; = 240Mhz / 4 ; = 60Mhz ; USB_DIVIDER (3 << 16) = 0x00030000 ; ; USB PLL Enable (0 << 23) = 0x00000000 ; MPLL and UPLL reset (3<<26) = 0x0C000000 ; LP CTL (0<<24) = 0x00000000 ; ------------- ; 0x2C034000 ldr r0, =0x2C034000
ldr r4, =10000
; Wait PLL statibilisation waitClock sub r4, r4, #1 cmp r4, #0 bne waitClock
; Now wait the MPLL is reset, so wait on the MPLL lock bit WaitForMPLL ldr r0, [r1, #CRM_MPCTL_OFFSET] tst r0, #MPLL_LOCK_FLAG beq WaitForMPLL
; Now wait the UPLL is reset, so wait on the UPLL lock bit WaitForUPLL ldr r0, [r1, #CRM_UPCTL_OFFSET] tst r0, #UPLL_LOCK_FLAG beq WaitForUPLL
; Set normal mode command
ldr r0, =0x83218880
str r0, [r1, #ESDRAMC_ESDCTL0_OFFSET]
RETURN
LEAF_ENTRY OALCPUEnterSuspend_sz ;Entry used to calculate the size of the function nop nop ENTRY_END
END
Does anyone know what I need to change to get this working?
Cheers,
Andre
Chongbin Fan wrote:
Just a reminder: the code was expected running on some non-SDRAM memory, such as internal ram or cache.
I know I am doing the following in power.c
VOID OALCPUPowerOff(void)
{
void (*suspend_func_ptr)();
int suspend_func_size;
....
// Need to keep the following clocks gated on for successful handshake
....
// copy the suspend routine into IRAM
suspend_func_ptr = (void*)OALPAtoCA(IMAGE_WINCE_IRAM_PA_START);
suspend_func_size = (UINT32)OALCPUEnterSuspend_sz - (UINT32)OALCPUEnterSuspend + 256; //include constants
memcpy(suspend_func_ptr, OALCPUEnterSuspend, suspend_func_size );
// Enter wait-for-interrupt mode and the system will transition
// to the low-power mode configured in the CCMR above.
// OALCPUEnterWFI();
suspend_func_ptr();
// exiting suspend
if (dwSdmaStat)
{
OUTREG32(&g_pSDMA->HSTART, dwSdmaStat);
}
}
If I comment out the rest of the code except for the two lines:
mov r0,#0
mcr p15, 0, r0, c7, c0, 4 ; Enter WFI
and return it works OK, it's only when I attempt to access any of the SDRAM control registers.
"it's only when I attempt to access any of the SDRAM control registers."
Please make sure 256 is big enough to consisted of the "CSP_BASE_REG_PA_ESDCTL" stuff which was expected at the end of the function, but not sure. You can dump the image and double check.