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