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