Back to home page

LXR

 
 

    


0001 /* sleep.S: power saving mode entry
0002  *
0003  * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
0004  * Written by David Woodhouse (dwmw2@infradead.org)
0005  *
0006  * This program is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU General Public License
0008  * as published by the Free Software Foundation; either version
0009  * 2 of the License, or (at your option) any later version.
0010  *
0011  */
0012 
0013 #include <linux/sys.h>
0014 #include <linux/linkage.h>
0015 #include <asm/setup.h>
0016 #include <asm/segment.h>
0017 #include <asm/page.h>
0018 #include <asm/ptrace.h>
0019 #include <asm/errno.h>
0020 #include <asm/cache.h>
0021 #include <asm/spr-regs.h>
0022 
0023 #define __addr_MASK 0xfeff9820  /* interrupt controller mask */
0024 
0025 #define __addr_FR55X_DRCN   0xfeff0218      /* Address of DRCN register */
0026 #define FR55X_DSTS_OFFSET   -4      /* Offset from DRCN to DSTS */
0027 #define FR55X_SDRAMC_DSTS_SSI   0x00000002  /* indicates that the SDRAM is in self-refresh mode */
0028 
0029 #define __addr_FR4XX_DRCN   0xfe000430      /* Address of DRCN register */
0030 #define FR4XX_DSTS_OFFSET   -8      /* Offset from DRCN to DSTS */
0031 #define FR4XX_SDRAMC_DSTS_SSI   0x00000001  /* indicates that the SDRAM is in self-refresh mode */
0032 
0033 #define SDRAMC_DRCN_SR  0x00000001  /* transition SDRAM into self-refresh mode */
0034 
0035     .section    .bss
0036     .balign     8
0037     .globl      __sleep_save_area
0038 __sleep_save_area:
0039     .space      16
0040 
0041 
0042     .text
0043     .balign     4
0044 
0045 .macro li v r
0046     sethi.p     %hi(\v),\r
0047     setlo       %lo(\v),\r
0048 .endm
0049 
0050 #ifdef CONFIG_PM
0051 ###############################################################################
0052 #
0053 # CPU suspension routine
0054 # - void frv_cpu_suspend(unsigned long pdm_mode)
0055 #
0056 ###############################################################################
0057     .globl      frv_cpu_suspend
0058         .type       frv_cpu_suspend,@function
0059 frv_cpu_suspend:
0060 
0061     #----------------------------------------------------
0062     # save hsr0, psr, isr, and lr for resume code
0063     #----------------------------------------------------
0064     li      __sleep_save_area,gr11
0065 
0066     movsg       hsr0,gr4
0067     movsg       psr,gr5
0068     movsg       isr,gr6
0069     movsg       lr,gr7
0070     stdi        gr4,@(gr11,#0)
0071     stdi        gr6,@(gr11,#8)
0072 
0073     # store the return address from sleep in GR14, and its complement in GR13 as a check
0074     li      __ramboot_resume,gr14
0075 #ifdef CONFIG_MMU
0076     # Resume via RAMBOOT# will turn MMU off, so bootloader needs a physical address.
0077     sethi.p     %hi(__page_offset),gr13
0078     setlo       %lo(__page_offset),gr13
0079     sub     gr14,gr13,gr14
0080 #endif
0081     not     gr14,gr13
0082 
0083     #----------------------------------------------------
0084     # preload and lock into icache that code which may have to run
0085     # when dram is in self-refresh state.
0086     #----------------------------------------------------
0087     movsg       hsr0, gr3
0088     li      HSR0_ICE,gr4
0089     or      gr3,gr4,gr3
0090     movgs       gr3,hsr0
0091     or      gr3,gr8,gr7 // add the sleep bits for later
0092 
0093     li      #__icache_lock_start,gr3
0094     li      #__icache_lock_end,gr4
0095 1:  icpl        gr3,gr0,#1
0096     addi        gr3,#L1_CACHE_BYTES,gr3
0097     cmp     gr4,gr3,icc0
0098     bhi     icc0,#0,1b
0099 
0100     # disable exceptions
0101     movsg       psr,gr8
0102     andi.p      gr8,#~PSR_PIL,gr8
0103     andi        gr8,~PSR_ET,gr8
0104     movgs       gr8,psr
0105     ori     gr8,#PSR_ET,gr8
0106 
0107     srli        gr8,#28,gr4
0108     subicc      gr4,#3,gr0,icc0
0109     beq     icc0,#0,1f
0110     # FR4xx
0111     li      __addr_FR4XX_DRCN,gr4
0112     li      FR4XX_SDRAMC_DSTS_SSI,gr5
0113     li      FR4XX_DSTS_OFFSET,gr6
0114     bra     __icache_lock_start
0115 1:
0116     # FR5xx
0117     li      __addr_FR55X_DRCN,gr4
0118     li      FR55X_SDRAMC_DSTS_SSI,gr5
0119     li      FR55X_DSTS_OFFSET,gr6
0120     bra     __icache_lock_start
0121 
0122     .size       frv_cpu_suspend, .-frv_cpu_suspend
0123 
0124 #
0125 # the final part of the sleep sequence...
0126 # - we want it to be be cacheline aligned so we can lock it into the icache easily
0127 #  On entry:    gr7 holds desired hsr0 sleep value
0128 #               gr8 holds desired psr sleep value
0129 #
0130     .balign     L1_CACHE_BYTES
0131         .type       __icache_lock_start,@function
0132 __icache_lock_start:
0133 
0134     #----------------------------------------------------
0135     # put SDRAM in self-refresh mode
0136     #----------------------------------------------------
0137 
0138     # Flush all data in the cache using the DCEF instruction.
0139     dcef        @(gr0,gr0),#1
0140 
0141     # Stop DMAC transfer
0142 
0143     # Execute dummy load from SDRAM
0144     ldi     @(gr11,#0),gr11
0145 
0146     # put the SDRAM into self-refresh mode
0147     ld              @(gr4,gr0),gr11
0148     ori     gr11,#SDRAMC_DRCN_SR,gr11
0149     st      gr11,@(gr4,gr0)
0150     membar
0151 
0152     # wait for SDRAM to reach self-refresh mode
0153 1:  ld      @(gr4,gr6),gr11
0154     andcc       gr11,gr5,gr11,icc0
0155     beq     icc0,#0,1b
0156 
0157     #  Set the GPIO register so that the IRQ[3:0] pins become valid, as required.
0158     #  Set the clock mode (CLKC register) as required.
0159     #     - At this time, also set the CLKC register P0 bit.
0160 
0161     # Set the HSR0 register PDM field.
0162     movgs       gr7,hsr0
0163 
0164     # Execute NOP 32 times.
0165     .rept       32
0166     nop
0167     .endr
0168 
0169 #if 0 // Fujitsu recommend to skip this and will update docs.
0170     #      Release the interrupt mask setting of the MASK register of the
0171     #      interrupt controller if necessary.
0172     sti     gr10,@(gr9,#0)
0173     membar
0174 #endif
0175 
0176     # Set the PSR register ET bit to 1 to enable interrupts.
0177     movgs       gr8,psr
0178 
0179     ###################################################
0180     # this is only reached if waking up via interrupt
0181     ###################################################
0182 
0183     # Execute NOP 32 times.
0184     .rept       32
0185     nop
0186     .endr
0187 
0188     #----------------------------------------------------
0189     # wake SDRAM from self-refresh mode
0190     #----------------------------------------------------
0191     ld              @(gr4,gr0),gr11
0192     andi        gr11,#~SDRAMC_DRCN_SR,gr11
0193     st      gr11,@(gr4,gr0)
0194     membar
0195 2:
0196     ld      @(gr4,gr6),gr11 // Wait for it to come back...
0197     andcc       gr11,gr5,gr0,icc0
0198     bne     icc0,0,2b
0199 
0200     # wait for the SDRAM to stabilise
0201     li      0x0100000,gr3
0202 3:  subicc      gr3,#1,gr3,icc0
0203     bne     icc0,#0,3b
0204 
0205     # now that DRAM is back, this is the end of the code which gets
0206     # locked in icache.
0207 __icache_lock_end:
0208     .size       __icache_lock_start, .-__icache_lock_start
0209 
0210     # Fall-through to the RAMBOOT# wakeup path
0211 
0212 ###############################################################################
0213 #
0214 #  resume from suspend re-entry point reached via RAMBOOT# and bootloader
0215 #
0216 ###############################################################################
0217 __ramboot_resume:
0218 
0219     #----------------------------------------------------
0220     # restore hsr0, psr, isr, and leave saved lr in gr7
0221     #----------------------------------------------------
0222     li      __sleep_save_area,gr11
0223 #ifdef CONFIG_MMU
0224     movsg       hsr0,gr4
0225     sethi.p     %hi(HSR0_EXMMU),gr3
0226     setlo       %lo(HSR0_EXMMU),gr3
0227     andcc       gr3,gr4,gr0,icc0
0228     bne     icc0,#0,2f
0229 
0230     # need to use physical address
0231     sethi.p     %hi(__page_offset),gr3
0232     setlo       %lo(__page_offset),gr3
0233     sub     gr11,gr3,gr11
0234 
0235     # flush all tlb entries
0236     setlos      #64,gr4
0237     setlos.p    #PAGE_SIZE,gr5
0238     setlos      #0,gr6
0239 1:
0240     tlbpr       gr6,gr0,#6,#0
0241     subicc.p    gr4,#1,gr4,icc0
0242     add     gr6,gr5,gr6
0243     bne     icc0,#2,1b
0244 
0245     # need a temporary mapping for the current physical address we are
0246     # using between time MMU is enabled and jump to virtual address is
0247     # made.
0248     sethi.p     %hi(0x00000000),gr4
0249     setlo       %lo(0x00000000),gr4     ; physical address
0250     setlos      #xAMPRx_L|xAMPRx_M|xAMPRx_SS_256Mb|xAMPRx_S_KERNEL|xAMPRx_V,gr5
0251     or      gr4,gr5,gr5
0252 
0253     movsg       cxnr,gr13
0254     or      gr4,gr13,gr4
0255 
0256     movgs       gr4,iamlr1          ; mapped from real address 0
0257     movgs       gr5,iampr1          ; cached kernel memory at 0x00000000
0258 2:
0259 #endif
0260 
0261     lddi        @(gr11,#0),gr4 ; hsr0, psr
0262     lddi        @(gr11,#8),gr6 ; isr, lr
0263     movgs       gr4,hsr0
0264     bar
0265 
0266 #ifdef CONFIG_MMU
0267     sethi.p     %hi(1f),gr11
0268     setlo       %lo(1f),gr11
0269     jmpl        @(gr11,gr0)
0270 1:
0271     movgs       gr0,iampr1  ; get rid of temporary mapping
0272 #endif
0273     movgs       gr5,psr
0274     movgs       gr6,isr
0275 
0276     #----------------------------------------------------
0277     # unlock the icache which was locked before going to sleep
0278     #----------------------------------------------------
0279     li      __icache_lock_start,gr3
0280     li      __icache_lock_end,gr4
0281 1:  icul        gr3
0282     addi        gr3,#L1_CACHE_BYTES,gr3
0283     cmp     gr4,gr3,icc0
0284     bhi     icc0,#0,1b
0285 
0286     #----------------------------------------------------
0287     # back to business as usual
0288     #----------------------------------------------------
0289     jmpl        @(gr7,gr0)      ;
0290 
0291 #endif /* CONFIG_PM */
0292 
0293 ###############################################################################
0294 #
0295 # CPU core sleep mode routine
0296 #
0297 ###############################################################################
0298     .globl      frv_cpu_core_sleep
0299         .type       frv_cpu_core_sleep,@function
0300 frv_cpu_core_sleep:
0301 
0302     # Preload into icache.
0303     li      #__core_sleep_icache_lock_start,gr3
0304     li      #__core_sleep_icache_lock_end,gr4
0305 
0306 1:  icpl        gr3,gr0,#1
0307     addi        gr3,#L1_CACHE_BYTES,gr3
0308     cmp     gr4,gr3,icc0
0309     bhi     icc0,#0,1b
0310 
0311     bra __core_sleep_icache_lock_start
0312 
0313     .balign L1_CACHE_BYTES
0314 __core_sleep_icache_lock_start:
0315 
0316     # (1) Set the PSR register ET bit to 0 to disable interrupts.
0317     movsg       psr,gr8
0318     andi.p      gr8,#~(PSR_PIL),gr8
0319     andi        gr8,#~(PSR_ET),gr4
0320     movgs       gr4,psr
0321 
0322 #if 0 // Fujitsu recommend to skip this and will update docs.
0323     # (2) Set '1' to all bits in the MASK register of the interrupt
0324     #     controller and mask interrupts.
0325     sethi.p     %hi(__addr_MASK),gr9
0326     setlo       %lo(__addr_MASK),gr9
0327     sethi.p     %hi(0xffff0000),gr4
0328     setlo       %lo(0xffff0000),gr4
0329     ldi     @(gr9,#0),gr10
0330     sti     gr4,@(gr9,#0)
0331 #endif
0332     # (3) Flush all data in the cache using the DCEF instruction.
0333     dcef        @(gr0,gr0),#1
0334 
0335     # (4) Execute the memory barrier instruction
0336     membar
0337 
0338     # (5) Set the GPIO register so that the IRQ[3:0] pins become valid, as required.
0339     # (6) Set the clock mode (CLKC register) as required.
0340     #     - At this time, also set the CLKC register P0 bit.
0341     # (7) Set the HSR0 register PDM field to  001 .
0342     movsg       hsr0,gr4
0343     ori     gr4,HSR0_PDM_CORE_SLEEP,gr4
0344     movgs       gr4,hsr0
0345 
0346     # (8) Execute NOP 32 times.
0347     .rept       32
0348     nop
0349     .endr
0350 
0351 #if 0 // Fujitsu recommend to skip this and will update docs.
0352     # (9) Release the interrupt mask setting of the MASK register of the
0353     #     interrupt controller if necessary.
0354     sti     gr10,@(gr9,#0)
0355     membar
0356 #endif
0357 
0358     # (10) Set the PSR register ET bit to 1 to enable interrupts.
0359     movgs       gr8,psr
0360 
0361 __core_sleep_icache_lock_end:
0362 
0363     # Unlock from icache
0364     li  __core_sleep_icache_lock_start,gr3
0365     li  __core_sleep_icache_lock_end,gr4
0366 1:  icul        gr3
0367     addi        gr3,#L1_CACHE_BYTES,gr3
0368     cmp     gr4,gr3,icc0
0369     bhi     icc0,#0,1b
0370 
0371     bralr
0372 
0373     .size       frv_cpu_core_sleep, .-frv_cpu_core_sleep