Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * Based on swsusp_32.S, modified for FSL BookE by
0004  * Anton Vorontsov <avorontsov@ru.mvista.com>
0005  * Copyright (c) 2009-2010 MontaVista Software, LLC.
0006  */
0007 
0008 #include <linux/threads.h>
0009 #include <asm/processor.h>
0010 #include <asm/page.h>
0011 #include <asm/cputable.h>
0012 #include <asm/thread_info.h>
0013 #include <asm/ppc_asm.h>
0014 #include <asm/asm-offsets.h>
0015 #include <asm/mmu.h>
0016 
0017 /*
0018  * Structure for storing CPU registers on the save area.
0019  */
0020 #define SL_SP       0
0021 #define SL_PC       4
0022 #define SL_MSR      8
0023 #define SL_TCR      0xc
0024 #define SL_SPRG0    0x10
0025 #define SL_SPRG1    0x14
0026 #define SL_SPRG2    0x18
0027 #define SL_SPRG3    0x1c
0028 #define SL_SPRG4    0x20
0029 #define SL_SPRG5    0x24
0030 #define SL_SPRG6    0x28
0031 #define SL_SPRG7    0x2c
0032 #define SL_TBU      0x30
0033 #define SL_TBL      0x34
0034 #define SL_R2       0x38
0035 #define SL_CR       0x3c
0036 #define SL_LR       0x40
0037 #define SL_R12      0x44    /* r12 to r31 */
0038 #define SL_SIZE     (SL_R12 + 80)
0039 
0040     .section .data
0041     .align  5
0042 
0043 _GLOBAL(swsusp_save_area)
0044     .space  SL_SIZE
0045 
0046 
0047     .section .text
0048     .align  5
0049 
0050 _GLOBAL(swsusp_arch_suspend)
0051     lis r11,swsusp_save_area@h
0052     ori r11,r11,swsusp_save_area@l
0053 
0054     mflr    r0
0055     stw r0,SL_LR(r11)
0056     mfcr    r0
0057     stw r0,SL_CR(r11)
0058     stw r1,SL_SP(r11)
0059     stw r2,SL_R2(r11)
0060     stmw    r12,SL_R12(r11)
0061 
0062     /* Save MSR & TCR */
0063     mfmsr   r4
0064     stw r4,SL_MSR(r11)
0065     mfspr   r4,SPRN_TCR
0066     stw r4,SL_TCR(r11)
0067 
0068     /* Get a stable timebase and save it */
0069 1:  mfspr   r4,SPRN_TBRU
0070     stw r4,SL_TBU(r11)
0071     mfspr   r5,SPRN_TBRL
0072     stw r5,SL_TBL(r11)
0073     mfspr   r3,SPRN_TBRU
0074     cmpw    r3,r4
0075     bne 1b
0076 
0077     /* Save SPRGs */
0078     mfspr   r4,SPRN_SPRG0
0079     stw r4,SL_SPRG0(r11)
0080     mfspr   r4,SPRN_SPRG1
0081     stw r4,SL_SPRG1(r11)
0082     mfspr   r4,SPRN_SPRG2
0083     stw r4,SL_SPRG2(r11)
0084     mfspr   r4,SPRN_SPRG3
0085     stw r4,SL_SPRG3(r11)
0086     mfspr   r4,SPRN_SPRG4
0087     stw r4,SL_SPRG4(r11)
0088     mfspr   r4,SPRN_SPRG5
0089     stw r4,SL_SPRG5(r11)
0090     mfspr   r4,SPRN_SPRG6
0091     stw r4,SL_SPRG6(r11)
0092     mfspr   r4,SPRN_SPRG7
0093     stw r4,SL_SPRG7(r11)
0094 
0095     /* Call the low level suspend stuff (we should probably have made
0096      * a stackframe...
0097      */
0098     bl  swsusp_save
0099 
0100     /* Restore LR from the save area */
0101     lis r11,swsusp_save_area@h
0102     ori r11,r11,swsusp_save_area@l
0103     lwz r0,SL_LR(r11)
0104     mtlr    r0
0105 
0106     blr
0107 
0108 _GLOBAL(swsusp_arch_resume)
0109     sync
0110 
0111     /* Load ptr the list of pages to copy in r3 */
0112     lis r11,(restore_pblist)@h
0113     ori r11,r11,restore_pblist@l
0114     lwz r3,0(r11)
0115 
0116     /* Copy the pages. This is a very basic implementation, to
0117      * be replaced by something more cache efficient */
0118 1:
0119     li  r0,256
0120     mtctr   r0
0121     lwz r5,pbe_address(r3)  /* source */
0122     lwz r6,pbe_orig_address(r3) /* destination */
0123 2:
0124     lwz r8,0(r5)
0125     lwz r9,4(r5)
0126     lwz r10,8(r5)
0127     lwz r11,12(r5)
0128     addi    r5,r5,16
0129     stw r8,0(r6)
0130     stw r9,4(r6)
0131     stw r10,8(r6)
0132     stw r11,12(r6)
0133     addi    r6,r6,16
0134     bdnz    2b
0135     lwz r3,pbe_next(r3)
0136     cmpwi   0,r3,0
0137     bne 1b
0138 
0139     bl flush_dcache_L1
0140     bl flush_instruction_cache
0141 
0142     lis r11,swsusp_save_area@h
0143     ori r11,r11,swsusp_save_area@l
0144 
0145     /*
0146      * Mappings from virtual addresses to physical addresses may be
0147      * different than they were prior to restoring hibernation state. 
0148      * Invalidate the TLB so that the boot CPU is using the new
0149      * mappings.
0150      */
0151     bl  _tlbil_all
0152 
0153     lwz r4,SL_SPRG0(r11)
0154     mtspr   SPRN_SPRG0,r4
0155     lwz r4,SL_SPRG1(r11)
0156     mtspr   SPRN_SPRG1,r4
0157     lwz r4,SL_SPRG2(r11)
0158     mtspr   SPRN_SPRG2,r4
0159     lwz r4,SL_SPRG3(r11)
0160     mtspr   SPRN_SPRG3,r4
0161     lwz r4,SL_SPRG4(r11)
0162     mtspr   SPRN_SPRG4,r4
0163     lwz r4,SL_SPRG5(r11)
0164     mtspr   SPRN_SPRG5,r4
0165     lwz r4,SL_SPRG6(r11)
0166     mtspr   SPRN_SPRG6,r4
0167     lwz r4,SL_SPRG7(r11)
0168     mtspr   SPRN_SPRG7,r4
0169 
0170     /* restore the MSR */
0171     lwz r3,SL_MSR(r11)
0172     mtmsr   r3
0173 
0174     /* Restore TB */
0175     li  r3,0
0176     mtspr   SPRN_TBWL,r3
0177     lwz r3,SL_TBU(r11)
0178     lwz r4,SL_TBL(r11)
0179     mtspr   SPRN_TBWU,r3
0180     mtspr   SPRN_TBWL,r4
0181 
0182     /* Restore TCR and clear any pending bits in TSR. */
0183     lwz r4,SL_TCR(r11)
0184     mtspr   SPRN_TCR,r4
0185     lis r4, (TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS)@h
0186     mtspr   SPRN_TSR,r4
0187 
0188     /* Kick decrementer */
0189     li  r0,1
0190     mtdec   r0
0191 
0192     /* Restore the callee-saved registers and return */
0193     lwz r0,SL_CR(r11)
0194     mtcr    r0
0195     lwz r2,SL_R2(r11)
0196     lmw r12,SL_R12(r11)
0197     lwz r1,SL_SP(r11)
0198     lwz r0,SL_LR(r11)
0199     mtlr    r0
0200 
0201     li  r3,0
0202     blr