i.MX35 suspend CPU and DDR2 from IRAM

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

i.MX35 suspend CPU and DDR2 from IRAM

641 Views
richardk
Contributor I

Hello!

I have to put my device into a very deep low power mode from Linux 2.6.38 and therefore, it's necessary to suspend all components, including CPU und DDR2.

What I found out so far is that I have to copy the core assembler function into the processor's internal memory and execute it from there. Basically, it looks like this:

cpaddr = iram_alloc(SZ_1K, &iram_addr);

if(!cpaddr) return -ENOMEM;

suspend_iram_base = __arm_ioremap(iram_addr, SZ_1K, MT_HIGH_VECTORS);

memcpy(suspend_iram_base, cpu_v6_sdram_off, SZ_1K);

flush_icache_range(suspend_iram_base, suspend_iram_base + SZ_1K);

flush_cache_all();

__asm__ __volatile__(

  "ldr r0, %0\n"

  "ldr r1, %1\n"

  "ldr r2, %2\n"

  "blx r2\n"

  "nop\n"

  : : "m" (esdctl_addr),

      "m" (csd0_addr),

      "m" (suspend_iram_base));

So far everything works as expected, I can verify code execution from internal memory (in virtual address space) with the JTAG debugger.

If I understand it all correctly, I have to do the following in the IRAM function:

- disable interrupts and caches

- set the SDRAM controller into precharge power down mode

- execute a precharge all command and access memory with A10 high (e.g. 0x400) to effectively close all banks

- put the CPU into standby by executing a WFI instruction

- re-enable everything afterwards (left out in the source code below)

ENTRY(cpu_v6_sdram_off)

  @ r0: esdctl base address

  @ r1: csd0 address with a10 high

  cpsid   if

  @ disable I and D cache

  mrc     p15, 0, r2, c1, c0, 0

  bic     r2, r2, #0x00001000  @ disable I cache

  bic     r2, r2, #0x00000004  @ disable D cache

  mcr     p15, 0, r2, c1, c0, 0

  @ invalidate I cache

  mov     r2, #0

  mcr     p15, 0, r2, c7, c5, 0

  @ clear and invalidate D cache

  mov     r2, #0

  mcr     p15, 0, r2, c7, c14, 0

  @ precharge power down mode

  ldr     r2, [r0]

  bic     r2, r2, #0xc00

  orr     r2, r2, #0x400

  str     r2, [r0]

  @ precharge all command

  mov     r2, #0x92

  lsl     r2, #24

  orr     r2, r2, #0x228000

  orr     r2, r2, #0x0400

  str     r2, [r0]

  mov     r2, #0x12

  lsl     r2, #24

  orr     r2, r2, #0x340000

  orr     r2, r2, #0x5600

  orr     r2, r2, #0x78

  str     r2, [r1] @ dummy write access

  @ execute wait for interrupt

  mov     r1, #0

  mcr     p15, 0, r1, c7, c10, 4

  mcr     p15, 0, r1, c7, c0, 4

  cpsie   if

  bx      lr

ENDPROC(cpu_v6_sdram_off)

The problem is at the point where the RAM is accessed with a dummy write. It simply results in a data abort exception and then the CPU gets lost.

If I leave this part out, the DDR2 doesn't seem to be put into low power mode, because the current consumption doesn't go down.

Now I'm totally stuck and out of ideas here. Could someone please give me a hint what I'm doing wrong or what I'm missing here?

Or is there any documentation or source code available demonstrating the whole procedure for the i.MX35 on Linux?

0 Kudos
3 Replies

494 Views
YixingKong
Senior Contributor IV

Richardk

This discussion is closed since no activity. If you still need help, please feel free to reply with an update to this discussion, or create another discussion.

Thanks,

Yixing

0 Kudos

494 Views
YixingKong
Senior Contributor IV

Richardk

We have not got your response yet and will close the discussion in 3 days. If you still need help, please feel free to reply with an update to this discussion.

Thanks,

Yixing

0 Kudos

494 Views
YixingKong
Senior Contributor IV

Richardk

We are sorry for getting back to you so late. Are you still stuck with the issue? If you have somehow to resolved the issue, can we close the discussion? If you still need help, please feel free to reply with an update to this discussion.

Thanks,

Yixing

0 Kudos