linux/arch/frv/kernel/sleep.S
<<
>>
Prefs
   1/* sleep.S: power saving mode entry
   2 *
   3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
   4 * Written by David Woodhouse (dwmw2@infradead.org)
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the License, or (at your option) any later version.
  10 *
  11 */
  12
  13#include <linux/sys.h>
  14#include <linux/linkage.h>
  15#include <asm/setup.h>
  16#include <asm/segment.h>
  17#include <asm/page.h>
  18#include <asm/ptrace.h>
  19#include <asm/errno.h>
  20#include <asm/cache.h>
  21#include <asm/spr-regs.h>
  22
  23#define __addr_MASK     0xfeff9820      /* interrupt controller mask */
  24
  25#define __addr_FR55X_DRCN       0xfeff0218      /* Address of DRCN register */
  26#define FR55X_DSTS_OFFSET       -4              /* Offset from DRCN to DSTS */
  27#define FR55X_SDRAMC_DSTS_SSI   0x00000002      /* indicates that the SDRAM is in self-refresh mode */
  28
  29#define __addr_FR4XX_DRCN       0xfe000430      /* Address of DRCN register */
  30#define FR4XX_DSTS_OFFSET       -8              /* Offset from DRCN to DSTS */
  31#define FR4XX_SDRAMC_DSTS_SSI   0x00000001      /* indicates that the SDRAM is in self-refresh mode */
  32
  33#define SDRAMC_DRCN_SR  0x00000001      /* transition SDRAM into self-refresh mode */
  34
  35        .section        .bss
  36        .balign         8
  37        .globl          __sleep_save_area
  38__sleep_save_area:
  39        .space          16
  40
  41
  42        .text
  43        .balign         4
  44
  45.macro li v r
  46        sethi.p         %hi(\v),\r
  47        setlo           %lo(\v),\r
  48.endm
  49
  50#ifdef CONFIG_PM
  51###############################################################################
  52#
  53# CPU suspension routine
  54# - void frv_cpu_suspend(unsigned long pdm_mode)
  55#
  56###############################################################################
  57        .globl          frv_cpu_suspend
  58        .type           frv_cpu_suspend,@function
  59frv_cpu_suspend:
  60
  61        #----------------------------------------------------
  62        # save hsr0, psr, isr, and lr for resume code
  63        #----------------------------------------------------
  64        li              __sleep_save_area,gr11
  65
  66        movsg           hsr0,gr4
  67        movsg           psr,gr5
  68        movsg           isr,gr6
  69        movsg           lr,gr7
  70        stdi            gr4,@(gr11,#0)
  71        stdi            gr6,@(gr11,#8)
  72
  73        # store the return address from sleep in GR14, and its complement in GR13 as a check
  74        li              __ramboot_resume,gr14
  75#ifdef CONFIG_MMU
  76        # Resume via RAMBOOT# will turn MMU off, so bootloader needs a physical address.
  77        sethi.p         %hi(__page_offset),gr13
  78        setlo           %lo(__page_offset),gr13
  79        sub             gr14,gr13,gr14
  80#endif
  81        not             gr14,gr13
  82
  83        #----------------------------------------------------
  84        # preload and lock into icache that code which may have to run
  85        # when dram is in self-refresh state.
  86        #----------------------------------------------------
  87        movsg           hsr0, gr3
  88        li              HSR0_ICE,gr4
  89        or              gr3,gr4,gr3
  90        movgs           gr3,hsr0
  91        or              gr3,gr8,gr7     // add the sleep bits for later
  92
  93        li              #__icache_lock_start,gr3
  94        li              #__icache_lock_end,gr4
  951:      icpl            gr3,gr0,#1
  96        addi            gr3,#L1_CACHE_BYTES,gr3
  97        cmp             gr4,gr3,icc0
  98        bhi             icc0,#0,1b
  99
 100        # disable exceptions
 101        movsg           psr,gr8
 102        andi.p          gr8,#~PSR_PIL,gr8
 103        andi            gr8,~PSR_ET,gr8
 104        movgs           gr8,psr
 105        ori             gr8,#PSR_ET,gr8
 106
 107        srli            gr8,#28,gr4
 108        subicc          gr4,#3,gr0,icc0
 109        beq             icc0,#0,1f
 110        # FR4xx
 111        li              __addr_FR4XX_DRCN,gr4
 112        li              FR4XX_SDRAMC_DSTS_SSI,gr5
 113        li              FR4XX_DSTS_OFFSET,gr6
 114        bra             __icache_lock_start
 1151:
 116        # FR5xx
 117        li              __addr_FR55X_DRCN,gr4
 118        li              FR55X_SDRAMC_DSTS_SSI,gr5
 119        li              FR55X_DSTS_OFFSET,gr6
 120        bra             __icache_lock_start
 121
 122        .size           frv_cpu_suspend, .-frv_cpu_suspend
 123
 124#
 125# the final part of the sleep sequence...
 126# - we want it to be be cacheline aligned so we can lock it into the icache easily
 127#  On entry:    gr7 holds desired hsr0 sleep value
 128#               gr8 holds desired psr sleep value
 129#
 130        .balign         L1_CACHE_BYTES
 131        .type           __icache_lock_start,@function
 132__icache_lock_start:
 133
 134        #----------------------------------------------------
 135        # put SDRAM in self-refresh mode
 136        #----------------------------------------------------
 137
 138        # Flush all data in the cache using the DCEF instruction.
 139        dcef            @(gr0,gr0),#1
 140
 141        # Stop DMAC transfer
 142
 143        # Execute dummy load from SDRAM
 144        ldi             @(gr11,#0),gr11
 145
 146        # put the SDRAM into self-refresh mode
 147        ld              @(gr4,gr0),gr11
 148        ori             gr11,#SDRAMC_DRCN_SR,gr11
 149        st              gr11,@(gr4,gr0)
 150        membar
 151
 152        # wait for SDRAM to reach self-refresh mode
 1531:      ld              @(gr4,gr6),gr11
 154        andcc           gr11,gr5,gr11,icc0
 155        beq             icc0,#0,1b
 156
 157        #  Set the GPIO register so that the IRQ[3:0] pins become valid, as required.
 158        #  Set the clock mode (CLKC register) as required.
 159        #     - At this time, also set the CLKC register P0 bit.
 160
 161        # Set the HSR0 register PDM field.
 162        movgs           gr7,hsr0
 163
 164        # Execute NOP 32 times.
 165        .rept           32
 166        nop
 167        .endr
 168
 169#if 0 // Fujitsu recommend to skip this and will update docs.
 170        #      Release the interrupt mask setting of the MASK register of the
 171        #      interrupt controller if necessary.
 172        sti             gr10,@(gr9,#0)
 173        membar
 174#endif
 175
 176        # Set the PSR register ET bit to 1 to enable interrupts.
 177        movgs           gr8,psr
 178
 179        ###################################################
 180        # this is only reached if waking up via interrupt
 181        ###################################################
 182
 183        # Execute NOP 32 times.
 184        .rept           32
 185        nop
 186        .endr
 187
 188        #----------------------------------------------------
 189        # wake SDRAM from self-refresh mode
 190        #----------------------------------------------------
 191        ld              @(gr4,gr0),gr11
 192        andi            gr11,#~SDRAMC_DRCN_SR,gr11
 193        st              gr11,@(gr4,gr0)
 194        membar
 1952:
 196        ld              @(gr4,gr6),gr11 // Wait for it to come back...
 197        andcc           gr11,gr5,gr0,icc0
 198        bne             icc0,0,2b
 199
 200        # wait for the SDRAM to stabilise
 201        li              0x0100000,gr3
 2023:      subicc          gr3,#1,gr3,icc0
 203        bne             icc0,#0,3b
 204
 205        # now that DRAM is back, this is the end of the code which gets
 206        # locked in icache.
 207__icache_lock_end:
 208        .size           __icache_lock_start, .-__icache_lock_start
 209
 210        # Fall-through to the RAMBOOT# wakeup path
 211
 212###############################################################################
 213#
 214#  resume from suspend re-entry point reached via RAMBOOT# and bootloader
 215#
 216###############################################################################
 217__ramboot_resume:
 218
 219        #----------------------------------------------------
 220        # restore hsr0, psr, isr, and leave saved lr in gr7
 221        #----------------------------------------------------
 222        li              __sleep_save_area,gr11
 223#ifdef CONFIG_MMU
 224        movsg           hsr0,gr4
 225        sethi.p         %hi(HSR0_EXMMU),gr3
 226        setlo           %lo(HSR0_EXMMU),gr3
 227        andcc           gr3,gr4,gr0,icc0
 228        bne             icc0,#0,2f
 229
 230        # need to use physical address
 231        sethi.p         %hi(__page_offset),gr3
 232        setlo           %lo(__page_offset),gr3
 233        sub             gr11,gr3,gr11
 234
 235        # flush all tlb entries
 236        setlos          #64,gr4
 237        setlos.p        #PAGE_SIZE,gr5
 238        setlos          #0,gr6
 2391:
 240        tlbpr           gr6,gr0,#6,#0
 241        subicc.p        gr4,#1,gr4,icc0
 242        add             gr6,gr5,gr6
 243        bne             icc0,#2,1b
 244
 245        # need a temporary mapping for the current physical address we are
 246        # using between time MMU is enabled and jump to virtual address is
 247        # made.
 248        sethi.p         %hi(0x00000000),gr4
 249        setlo           %lo(0x00000000),gr4             ; physical address
 250        setlos          #xAMPRx_L|xAMPRx_M|xAMPRx_SS_256Mb|xAMPRx_S_KERNEL|xAMPRx_V,gr5
 251        or              gr4,gr5,gr5
 252
 253        movsg           cxnr,gr13
 254        or              gr4,gr13,gr4
 255
 256        movgs           gr4,iamlr1                      ; mapped from real address 0
 257        movgs           gr5,iampr1                      ; cached kernel memory at 0x00000000
 2582:
 259#endif
 260
 261        lddi            @(gr11,#0),gr4 ; hsr0, psr
 262        lddi            @(gr11,#8),gr6 ; isr, lr
 263        movgs           gr4,hsr0
 264        bar
 265
 266#ifdef CONFIG_MMU
 267        sethi.p         %hi(1f),gr11
 268        setlo           %lo(1f),gr11
 269        jmpl            @(gr11,gr0)
 2701:
 271        movgs           gr0,iampr1      ; get rid of temporary mapping
 272#endif
 273        movgs           gr5,psr
 274        movgs           gr6,isr
 275
 276        #----------------------------------------------------
 277        # unlock the icache which was locked before going to sleep
 278        #----------------------------------------------------
 279        li              __icache_lock_start,gr3
 280        li              __icache_lock_end,gr4
 2811:      icul            gr3
 282        addi            gr3,#L1_CACHE_BYTES,gr3
 283        cmp             gr4,gr3,icc0
 284        bhi             icc0,#0,1b
 285
 286        #----------------------------------------------------
 287        # back to business as usual
 288        #----------------------------------------------------
 289        jmpl            @(gr7,gr0)              ;
 290
 291#endif /* CONFIG_PM */
 292
 293###############################################################################
 294#
 295# CPU core sleep mode routine
 296#
 297###############################################################################
 298        .globl          frv_cpu_core_sleep
 299        .type           frv_cpu_core_sleep,@function
 300frv_cpu_core_sleep:
 301
 302        # Preload into icache.
 303        li              #__core_sleep_icache_lock_start,gr3
 304        li              #__core_sleep_icache_lock_end,gr4
 305
 3061:      icpl            gr3,gr0,#1
 307        addi            gr3,#L1_CACHE_BYTES,gr3
 308        cmp             gr4,gr3,icc0
 309        bhi             icc0,#0,1b
 310
 311        bra     __core_sleep_icache_lock_start
 312
 313        .balign L1_CACHE_BYTES
 314__core_sleep_icache_lock_start:
 315
 316        # (1) Set the PSR register ET bit to 0 to disable interrupts.
 317        movsg           psr,gr8
 318        andi.p          gr8,#~(PSR_PIL),gr8
 319        andi            gr8,#~(PSR_ET),gr4
 320        movgs           gr4,psr
 321
 322#if 0 // Fujitsu recommend to skip this and will update docs.
 323        # (2) Set '1' to all bits in the MASK register of the interrupt
 324        #     controller and mask interrupts.
 325        sethi.p         %hi(__addr_MASK),gr9
 326        setlo           %lo(__addr_MASK),gr9
 327        sethi.p         %hi(0xffff0000),gr4
 328        setlo           %lo(0xffff0000),gr4
 329        ldi             @(gr9,#0),gr10
 330        sti             gr4,@(gr9,#0)
 331#endif
 332        # (3) Flush all data in the cache using the DCEF instruction.
 333        dcef            @(gr0,gr0),#1
 334
 335        # (4) Execute the memory barrier instruction
 336        membar
 337
 338        # (5) Set the GPIO register so that the IRQ[3:0] pins become valid, as required.
 339        # (6) Set the clock mode (CLKC register) as required.
 340        #     - At this time, also set the CLKC register P0 bit.
 341        # (7) Set the HSR0 register PDM field to  001 .
 342        movsg           hsr0,gr4
 343        ori             gr4,HSR0_PDM_CORE_SLEEP,gr4
 344        movgs           gr4,hsr0
 345
 346        # (8) Execute NOP 32 times.
 347        .rept           32
 348        nop
 349        .endr
 350
 351#if 0 // Fujitsu recommend to skip this and will update docs.
 352        # (9) Release the interrupt mask setting of the MASK register of the
 353        #     interrupt controller if necessary.
 354        sti             gr10,@(gr9,#0)
 355        membar
 356#endif
 357
 358        # (10) Set the PSR register ET bit to 1 to enable interrupts.
 359        movgs           gr8,psr
 360
 361__core_sleep_icache_lock_end:
 362
 363        # Unlock from icache
 364        li      __core_sleep_icache_lock_start,gr3
 365        li      __core_sleep_icache_lock_end,gr4
 3661:      icul            gr3
 367        addi            gr3,#L1_CACHE_BYTES,gr3
 368        cmp             gr4,gr3,icc0
 369        bhi             icc0,#0,1b
 370
 371        bralr
 372
 373        .size           frv_cpu_core_sleep, .-frv_cpu_core_sleep
 374