self-refresh.S 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*
  2. * Copyright (C) 2014-2015 Altera Corporation. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms and conditions of the GNU General Public License,
  6. * version 2, as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope it will be useful, but WITHOUT
  9. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  11. * more details.
  12. *
  13. * You should have received a copy of the GNU General Public License along with
  14. * this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include <linux/linkage.h>
  17. #include <asm/assembler.h>
  18. #define MAX_LOOP_COUNT 1000
  19. /* Register offset */
  20. #define SDR_CTRLGRP_LOWPWREQ_ADDR 0x54
  21. #define SDR_CTRLGRP_LOWPWRACK_ADDR 0x58
  22. /* Bitfield positions */
  23. #define SELFRSHREQ_POS 3
  24. #define SELFRSHREQ_MASK 0x8
  25. #define SELFRFSHACK_POS 1
  26. #define SELFRFSHACK_MASK 0x2
  27. /*
  28. * This code assumes that when the bootloader configured
  29. * the sdram controller for the DDR on the board it
  30. * configured the following fields depending on the DDR
  31. * vendor/configuration:
  32. *
  33. * sdr.ctrlcfg.lowpwreq.selfrfshmask
  34. * sdr.ctrlcfg.lowpwrtiming.clkdisablecycles
  35. * sdr.ctrlcfg.dramtiming4.selfrfshexit
  36. */
  37. .arch armv7-a
  38. .text
  39. .align 3
  40. /*
  41. * socfpga_sdram_self_refresh
  42. *
  43. * r0 : sdr_ctl_base_addr
  44. * r1 : temp storage of return value
  45. * r2 : temp storage of register values
  46. * r3 : loop counter
  47. *
  48. * return value: lower 16 bits: loop count going into self refresh
  49. * upper 16 bits: loop count exiting self refresh
  50. */
  51. ENTRY(socfpga_sdram_self_refresh)
  52. /* Enable dynamic clock gating in the Power Control Register. */
  53. mrc p15, 0, r2, c15, c0, 0
  54. orr r2, r2, #1
  55. mcr p15, 0, r2, c15, c0, 0
  56. /* Enable self refresh: set sdr.ctrlgrp.lowpwreq.selfrshreq = 1 */
  57. ldr r2, [r0, #SDR_CTRLGRP_LOWPWREQ_ADDR]
  58. orr r2, r2, #SELFRSHREQ_MASK
  59. str r2, [r0, #SDR_CTRLGRP_LOWPWREQ_ADDR]
  60. /* Poll until sdr.ctrlgrp.lowpwrack.selfrfshack == 1 or hit max loops */
  61. mov r3, #0
  62. while_ack_0:
  63. ldr r2, [r0, #SDR_CTRLGRP_LOWPWRACK_ADDR]
  64. and r2, r2, #SELFRFSHACK_MASK
  65. cmp r2, #SELFRFSHACK_MASK
  66. beq ack_1
  67. add r3, #1
  68. cmp r3, #MAX_LOOP_COUNT
  69. bne while_ack_0
  70. ack_1:
  71. mov r1, r3
  72. /*
  73. * Execute an ISB instruction to ensure that all of the
  74. * CP15 register changes have been committed.
  75. */
  76. isb
  77. /*
  78. * Execute a barrier instruction to ensure that all cache,
  79. * TLB and branch predictor maintenance operations issued
  80. * by any CPU in the cluster have completed.
  81. */
  82. dsb
  83. dmb
  84. wfi
  85. /* Disable self-refresh: set sdr.ctrlgrp.lowpwreq.selfrshreq = 0 */
  86. ldr r2, [r0, #SDR_CTRLGRP_LOWPWREQ_ADDR]
  87. bic r2, r2, #SELFRSHREQ_MASK
  88. str r2, [r0, #SDR_CTRLGRP_LOWPWREQ_ADDR]
  89. /* Poll until sdr.ctrlgrp.lowpwrack.selfrfshack == 0 or hit max loops */
  90. mov r3, #0
  91. while_ack_1:
  92. ldr r2, [r0, #SDR_CTRLGRP_LOWPWRACK_ADDR]
  93. and r2, r2, #SELFRFSHACK_MASK
  94. cmp r2, #SELFRFSHACK_MASK
  95. bne ack_0
  96. add r3, #1
  97. cmp r3, #MAX_LOOP_COUNT
  98. bne while_ack_1
  99. ack_0:
  100. /*
  101. * Prepare return value:
  102. * Shift loop count for exiting self refresh into upper 16 bits.
  103. * Leave loop count for requesting self refresh in lower 16 bits.
  104. */
  105. mov r3, r3, lsl #16
  106. add r1, r1, r3
  107. /* Disable dynamic clock gating in the Power Control Register. */
  108. mrc p15, 0, r2, c15, c0, 0
  109. bic r2, r2, #1
  110. mcr p15, 0, r2, c15, c0, 0
  111. mov r0, r1 @ return value
  112. bx lr @ return
  113. ENDPROC(socfpga_sdram_self_refresh)
  114. ENTRY(socfpga_sdram_self_refresh_sz)
  115. .word . - socfpga_sdram_self_refresh