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