1/* 2 * Based on swsusp_32.S, modified for FSL BookE by 3 * Anton Vorontsov <avorontsov@ru.mvista.com> 4 * Copyright (c) 2009-2010 MontaVista Software, LLC. 5 */ 6 7#include <linux/threads.h> 8#include <asm/processor.h> 9#include <asm/page.h> 10#include <asm/cputable.h> 11#include <asm/thread_info.h> 12#include <asm/ppc_asm.h> 13#include <asm/asm-offsets.h> 14#include <asm/mmu.h> 15 16/* 17 * Structure for storing CPU registers on the save area. 18 */ 19#define SL_SP 0 20#define SL_PC 4 21#define SL_MSR 8 22#define SL_TCR 0xc 23#define SL_SPRG0 0x10 24#define SL_SPRG1 0x14 25#define SL_SPRG2 0x18 26#define SL_SPRG3 0x1c 27#define SL_SPRG4 0x20 28#define SL_SPRG5 0x24 29#define SL_SPRG6 0x28 30#define SL_SPRG7 0x2c 31#define SL_TBU 0x30 32#define SL_TBL 0x34 33#define SL_R2 0x38 34#define SL_CR 0x3c 35#define SL_LR 0x40 36#define SL_R12 0x44 /* r12 to r31 */ 37#define SL_SIZE (SL_R12 + 80) 38 39 .section .data 40 .align 5 41 42_GLOBAL(swsusp_save_area) 43 .space SL_SIZE 44 45 46 .section .text 47 .align 5 48 49_GLOBAL(swsusp_arch_suspend) 50 lis r11,swsusp_save_area@h 51 ori r11,r11,swsusp_save_area@l 52 53 mflr r0 54 stw r0,SL_LR(r11) 55 mfcr r0 56 stw r0,SL_CR(r11) 57 stw r1,SL_SP(r11) 58 stw r2,SL_R2(r11) 59 stmw r12,SL_R12(r11) 60 61 /* Save MSR & TCR */ 62 mfmsr r4 63 stw r4,SL_MSR(r11) 64 mfspr r4,SPRN_TCR 65 stw r4,SL_TCR(r11) 66 67 /* Get a stable timebase and save it */ 681: mfspr r4,SPRN_TBRU 69 stw r4,SL_TBU(r11) 70 mfspr r5,SPRN_TBRL 71 stw r5,SL_TBL(r11) 72 mfspr r3,SPRN_TBRU 73 cmpw r3,r4 74 bne 1b 75 76 /* Save SPRGs */ 77 mfsprg r4,0 78 stw r4,SL_SPRG0(r11) 79 mfsprg r4,1 80 stw r4,SL_SPRG1(r11) 81 mfsprg r4,2 82 stw r4,SL_SPRG2(r11) 83 mfsprg r4,3 84 stw r4,SL_SPRG3(r11) 85 mfsprg r4,4 86 stw r4,SL_SPRG4(r11) 87 mfsprg r4,5 88 stw r4,SL_SPRG5(r11) 89 mfsprg r4,6 90 stw r4,SL_SPRG6(r11) 91 mfsprg r4,7 92 stw r4,SL_SPRG7(r11) 93 94 /* Call the low level suspend stuff (we should probably have made 95 * a stackframe... 96 */ 97 bl swsusp_save 98 99 /* Restore LR from the save area */ 100 lis r11,swsusp_save_area@h 101 ori r11,r11,swsusp_save_area@l 102 lwz r0,SL_LR(r11) 103 mtlr r0 104 105 blr 106 107_GLOBAL(swsusp_arch_resume) 108 sync 109 110 /* Load ptr the list of pages to copy in r3 */ 111 lis r11,(restore_pblist)@h 112 ori r11,r11,restore_pblist@l 113 lwz r3,0(r11) 114 115 /* Copy the pages. This is a very basic implementation, to 116 * be replaced by something more cache efficient */ 1171: 118 li r0,256 119 mtctr r0 120 lwz r5,pbe_address(r3) /* source */ 121 lwz r6,pbe_orig_address(r3) /* destination */ 1222: 123 lwz r8,0(r5) 124 lwz r9,4(r5) 125 lwz r10,8(r5) 126 lwz r11,12(r5) 127 addi r5,r5,16 128 stw r8,0(r6) 129 stw r9,4(r6) 130 stw r10,8(r6) 131 stw r11,12(r6) 132 addi r6,r6,16 133 bdnz 2b 134 lwz r3,pbe_next(r3) 135 cmpwi 0,r3,0 136 bne 1b 137 138 bl flush_dcache_L1 139 bl flush_instruction_cache 140 141 lis r11,swsusp_save_area@h 142 ori r11,r11,swsusp_save_area@l 143 144 lwz r4,SL_SPRG0(r11) 145 mtsprg 0,r4 146 lwz r4,SL_SPRG1(r11) 147 mtsprg 1,r4 148 lwz r4,SL_SPRG2(r11) 149 mtsprg 2,r4 150 lwz r4,SL_SPRG3(r11) 151 mtsprg 3,r4 152 lwz r4,SL_SPRG4(r11) 153 mtsprg 4,r4 154 lwz r4,SL_SPRG5(r11) 155 mtsprg 5,r4 156 lwz r4,SL_SPRG6(r11) 157 mtsprg 6,r4 158 lwz r4,SL_SPRG7(r11) 159 mtsprg 7,r4 160 161 /* restore the MSR */ 162 lwz r3,SL_MSR(r11) 163 mtmsr r3 164 165 /* Restore TB */ 166 li r3,0 167 mtspr SPRN_TBWL,r3 168 lwz r3,SL_TBU(r11) 169 lwz r4,SL_TBL(r11) 170 mtspr SPRN_TBWU,r3 171 mtspr SPRN_TBWL,r4 172 173 /* Restore TCR and clear any pending bits in TSR. */ 174 lwz r4,SL_TCR(r11) 175 mtspr SPRN_TCR,r4 176 lis r4, (TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS)@h 177 mtspr SPRN_TSR,r4 178 179 /* Kick decrementer */ 180 li r0,1 181 mtdec r0 182 183 /* Restore the callee-saved registers and return */ 184 lwz r0,SL_CR(r11) 185 mtcr r0 186 lwz r2,SL_R2(r11) 187 lmw r12,SL_R12(r11) 188 lwz r1,SL_SP(r11) 189 lwz r0,SL_LR(r11) 190 mtlr r0 191 192 li r3,0 193 blr 194