We try to implement suspend/resume in Linux with LPSTOP2 support (retain 16KB of data) on vanilla/mainline Linux kernel. Similar to the i.MX6 and Timesys Linux 3.0 kernel suspend/resume support, I relocate an assembler function into SRAM and go to deep sleep in there.
So far, the sleep part does the following steps:
- Save current memory registers
- Setup CCM_LPCR, GPC_PGCR and friends
- Flush D-cache
- Put the memory explicitly in self-refresh mode using LP_CMD(0xA), and wait for completion of this command
- Setup GPR0/GPR1 register
- Execute WFI instruction
The resume function executes this steps:
- Invalidate L1 cache
- Mask interrupts
- Ungate UART, ANADIG, SCSM, GPC, CCM, WKUP and MMDC
- Enable slow oscillators
- Enable fast oscillators and select external FOSC
- Enable PLL1/PLL2 and wait for lock (we use PLL2 as memory clock source...)
- Restore memory registers
- [Set PWUP_SREF_EX in CR34, see 2 below]
- Start memory controller (set START bit of DDRMC_CR00)
- Stopping self-refresh mode using LP_CMD(0x9)
- Jump to standard Linux resume routine in DDR memory (cpu_resume)
This works quite reliable, including jumping back to DDR and continue executing C-code. Currently, somewhere in the code located in DDR RAM, the kernel crashes. It is not yet clear why, but this is not my main concern here.
However, what I discovered when connecting a scope, that the memory controller is driving the RESET# signal to low, both when putting the memory into sleep state as well as when waking up the memory (see attached scope screenshots). We do have an external pull-up on the DDR3 RESET# (yellow in scope) signal as well as a pull-down on the CKE (blue in scope) signal. Those are my questions:
- Is it ok that the memory controller issues a reset right before going to sleep (as shown in DDR3_SelfRefreshEntry.TIF). In my understanding, this resets the DDR3 memory, which would invalidate the self-refresh command... If reset commands are not harmful while in self-refresh, I guess the pull-up for the RESET# signal would not be required...?
- Is it ok that the memory controller issues a reset right when waking up (see DDR3_SelfRefreshExit.TIF). I found the PWUP_SREF_EX bit, however when setting this bit, I cannot access the memory after initialization... (DDR3_SelfRefreshExitWith_PWUP_SREF_EX.TIF)
- In chapter 34.6.6 Low Power Operation, the text says that Self-Refresh with Memory Clock Gating and Self-Refresh with Memory and Controller Clock Gating is only valid for LPDDR2. What does this mean exactly? As fair as I understood the low power architecture, the MMDC (memory controller) is in PD1, hence it will be turned off. In my understanding, this would mean that Memory and Controller Clock will be gated... Is DDR3 self-refresh with LPSTOPx modes possible at all?