suspend-imx53.S 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. /*
  3. * Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
  4. */
  5. /*
  6. */
  7. #include <linux/linkage.h>
  8. #define M4IF_MCR0_OFFSET (0x008C)
  9. #define M4IF_MCR0_FDVFS (0x1 << 11)
  10. #define M4IF_MCR0_FDVACK (0x1 << 27)
  11. .align 3
  12. /*
  13. * ==================== low level suspend ====================
  14. *
  15. * On entry
  16. * r0: pm_info structure address;
  17. *
  18. * suspend ocram space layout:
  19. * ======================== high address ======================
  20. * .
  21. * .
  22. * .
  23. * ^
  24. * ^
  25. * ^
  26. * imx53_suspend code
  27. * PM_INFO structure(imx5_cpu_suspend_info)
  28. * ======================== low address =======================
  29. */
  30. /* Offsets of members of struct imx5_cpu_suspend_info */
  31. #define SUSPEND_INFO_MX53_M4IF_V_OFFSET 0x0
  32. #define SUSPEND_INFO_MX53_IOMUXC_V_OFFSET 0x4
  33. #define SUSPEND_INFO_MX53_IO_COUNT_OFFSET 0x8
  34. #define SUSPEND_INFO_MX53_IO_STATE_OFFSET 0xc
  35. ENTRY(imx53_suspend)
  36. stmfd sp!, {r4,r5,r6,r7}
  37. /* Save pad config */
  38. ldr r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET]
  39. cmp r1, #0
  40. beq skip_pad_conf_1
  41. add r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET
  42. ldr r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET]
  43. 1:
  44. ldr r5, [r2], #12 /* IOMUXC register offset */
  45. ldr r6, [r3, r5] /* current value */
  46. str r6, [r2], #4 /* save area */
  47. subs r1, r1, #1
  48. bne 1b
  49. skip_pad_conf_1:
  50. /* Set FDVFS bit of M4IF_MCR0 to request DDR to enter self-refresh */
  51. ldr r1, [r0, #SUSPEND_INFO_MX53_M4IF_V_OFFSET]
  52. ldr r2,[r1, #M4IF_MCR0_OFFSET]
  53. orr r2, r2, #M4IF_MCR0_FDVFS
  54. str r2,[r1, #M4IF_MCR0_OFFSET]
  55. /* Poll FDVACK bit of M4IF_MCR to wait for DDR to enter self-refresh */
  56. wait_sr_ack:
  57. ldr r2,[r1, #M4IF_MCR0_OFFSET]
  58. ands r2, r2, #M4IF_MCR0_FDVACK
  59. beq wait_sr_ack
  60. /* Set pad config */
  61. ldr r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET]
  62. cmp r1, #0
  63. beq skip_pad_conf_2
  64. add r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET
  65. ldr r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET]
  66. 2:
  67. ldr r5, [r2], #4 /* IOMUXC register offset */
  68. ldr r6, [r2], #4 /* clear */
  69. ldr r7, [r3, r5]
  70. bic r7, r7, r6
  71. ldr r6, [r2], #8 /* set */
  72. orr r7, r7, r6
  73. str r7, [r3, r5]
  74. subs r1, r1, #1
  75. bne 2b
  76. skip_pad_conf_2:
  77. /* Zzz, enter stop mode */
  78. wfi
  79. nop
  80. nop
  81. nop
  82. nop
  83. /* Restore pad config */
  84. ldr r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET]
  85. cmp r1, #0
  86. beq skip_pad_conf_3
  87. add r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET
  88. ldr r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET]
  89. 3:
  90. ldr r5, [r2], #12 /* IOMUXC register offset */
  91. ldr r6, [r2], #4 /* saved value */
  92. str r6, [r3, r5]
  93. subs r1, r1, #1
  94. bne 3b
  95. skip_pad_conf_3:
  96. /* Clear FDVFS bit of M4IF_MCR0 to request DDR to exit self-refresh */
  97. ldr r1, [r0, #SUSPEND_INFO_MX53_M4IF_V_OFFSET]
  98. ldr r2,[r1, #M4IF_MCR0_OFFSET]
  99. bic r2, r2, #M4IF_MCR0_FDVFS
  100. str r2,[r1, #M4IF_MCR0_OFFSET]
  101. /* Poll FDVACK bit of M4IF_MCR to wait for DDR to exit self-refresh */
  102. wait_ar_ack:
  103. ldr r2,[r1, #M4IF_MCR0_OFFSET]
  104. ands r2, r2, #M4IF_MCR0_FDVACK
  105. bne wait_ar_ack
  106. /* Restore registers */
  107. ldmfd sp!, {r4,r5,r6,r7}
  108. mov pc, lr
  109. ENDPROC(imx53_suspend)
  110. ENTRY(imx53_suspend_sz)
  111. .word . - imx53_suspend