i.MX35 suspender CPU y DDR2 de IRAM

Tengo que poner mi dispositivo en un modo de baja potencia muy profundo desde Linux 2.6.38 y, por lo tanto, es necesario suspender todos los componentes, incluidos CPU y DDR2.

Lo que descubrí hasta ahora es que tengo que copiar la función del ensamblador central en la memoria interna del procesador y ejecutarla desde allí. Básicamente, se ve así:

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));

Hasta ahora todo funciona como se esperaba, puedo verificar la ejecución del código desde la memoria interna (en el espacio de direcciones virtuales) con el depurador JTAG.

Si lo entiendo todo correctamente, tengo que hacer lo siguiente en la función IRAM:

deshabilitar interrupciones y cachésconfigurar el controlador SDRAM en modo de apagado de precargaejecute una precarga de todos los comandos y acceda a la memoria con A10 alto (por ejemplo, 0x400) para cerrar todos los bancosponer la CPU en espera ejecutando una instrucción WFIvuelva a habilitar todo después (excluido en el código fuente a continuación)

El código correspondiente se ve así:

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)

El problema está en el punto donde se accede a la RAM con una escritura ficticia. Simplemente da como resultado una excepción de cancelación de datos y luego la CPU se pierde. Si dejo esta parte, el DDR2 no parece estar en modo de bajo consumo, porque el consumo de corriente no baja.

Ahora estoy totalmente atascado y sin ideas aquí. ¿Podría alguien darme una pista de lo que estoy haciendo mal o de lo que me estoy perdiendo aquí? ¿O hay alguna documentación o código fuente disponible que demuestre todo el procedimiento para el i.MX35 en Linux?

Respuestas a la pregunta(2)

Su respuesta a la pregunta