dpm.S 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #include <linux/linkage.h>
  2. #include <asm/blackfin.h>
  3. #include <asm/dpmc.h>
  4. #include <asm/context.S>
  5. #define PM_STACK (COREA_L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
  6. .section .l1.text
  7. ENTRY(_enter_hibernate)
  8. /* switch stack to L1 scratch, prepare for ddr srfr */
  9. P0.H = HI(PM_STACK);
  10. P0.L = LO(PM_STACK);
  11. SP = P0;
  12. call _bf609_ddr_sr;
  13. call _bfin_hibernate_syscontrol;
  14. P0.H = HI(DPM0_RESTORE4);
  15. P0.L = LO(DPM0_RESTORE4);
  16. P1.H = _bf609_pm_data;
  17. P1.L = _bf609_pm_data;
  18. [P0] = P1;
  19. P0.H = HI(DPM0_CTL);
  20. P0.L = LO(DPM0_CTL);
  21. R3.H = HI(0x00000010);
  22. R3.L = LO(0x00000010);
  23. bfin_init_pm_bench_cycles;
  24. [P0] = R3;
  25. SSYNC;
  26. ENDPROC(_enter_hibernate)
  27. /* DPM wake up interrupt won't wake up core on bf60x if its core IMASK
  28. * is disabled. This behavior differ from bf5xx serial processor.
  29. */
  30. ENTRY(_dummy_deepsleep)
  31. [--sp] = SYSCFG;
  32. [--sp] = (R7:0,P5:0);
  33. cli r0;
  34. /* get wake up interrupt ID */
  35. P0.l = LO(SEC_SCI_BASE + SEC_CSID);
  36. P0.h = HI(SEC_SCI_BASE + SEC_CSID);
  37. R0 = [P0];
  38. /* ACK wake up interrupt in SEC */
  39. P1.l = LO(SEC_END);
  40. P1.h = HI(SEC_END);
  41. [P1] = R0;
  42. SSYNC;
  43. /* restore EVT 11 entry */
  44. p0.h = hi(EVT11);
  45. p0.l = lo(EVT11);
  46. p1.h = _evt_evt11;
  47. p1.l = _evt_evt11;
  48. [p0] = p1;
  49. SSYNC;
  50. (R7:0,P5:0) = [sp++];
  51. SYSCFG = [sp++];
  52. RTI;
  53. ENDPROC(_dummy_deepsleep)
  54. ENTRY(_enter_deepsleep)
  55. LINK 0xC;
  56. [--sp] = (R7:0,P5:0);
  57. /* Change EVT 11 entry to dummy handler for wake up event */
  58. p0.h = hi(EVT11);
  59. p0.l = lo(EVT11);
  60. p1.h = _dummy_deepsleep;
  61. p1.l = _dummy_deepsleep;
  62. [p0] = p1;
  63. P0.H = HI(PM_STACK);
  64. P0.L = LO(PM_STACK);
  65. EX_SCRATCH_REG = SP;
  66. SP = P0;
  67. SSYNC;
  68. /* should put ddr to self refresh mode before sleep */
  69. call _bf609_ddr_sr;
  70. /* Set DPM controller to deep sleep mode */
  71. P0.H = HI(DPM0_CTL);
  72. P0.L = LO(DPM0_CTL);
  73. R3.H = HI(0x00000008);
  74. R3.L = LO(0x00000008);
  75. [P0] = R3;
  76. CSYNC;
  77. /* Enable evt 11 in IMASK before idle, otherwise core doesn't wake up. */
  78. r0.l = 0x800;
  79. r0.h = 0;
  80. sti r0;
  81. SSYNC;
  82. bfin_init_pm_bench_cycles;
  83. /* Fall into deep sleep in idle*/
  84. idle;
  85. SSYNC;
  86. /* Restore PLL after wake up from deep sleep */
  87. call _bf609_resume_ccbuf;
  88. /* turn ddr out of self refresh mode */
  89. call _bf609_ddr_sr_exit;
  90. SP = EX_SCRATCH_REG;
  91. (R7:0,P5:0) = [SP++];
  92. UNLINK;
  93. RTS;
  94. ENDPROC(_enter_deepsleep)
  95. .section .text
  96. ENTRY(_bf609_hibernate)
  97. bfin_cpu_reg_save;
  98. bfin_core_mmr_save;
  99. P0.H = _bf609_pm_data;
  100. P0.L = _bf609_pm_data;
  101. R1.H = 0xDEAD;
  102. R1.L = 0xBEEF;
  103. R2.H = .Lpm_resume_here;
  104. R2.L = .Lpm_resume_here;
  105. [P0++] = R1;
  106. [P0++] = R2;
  107. [P0++] = SP;
  108. P1.H = _enter_hibernate;
  109. P1.L = _enter_hibernate;
  110. call (P1);
  111. .Lpm_resume_here:
  112. bfin_core_mmr_restore;
  113. bfin_cpu_reg_restore;
  114. [--sp] = RETI; /* Clear Global Interrupt Disable */
  115. SP += 4;
  116. RTS;
  117. ENDPROC(_bf609_hibernate)