/* sleep.S: power saving mode entry1*2* Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.3* Written by David Woodhouse ([email protected])4*5* This program is free software; you can redistribute it and/or6* modify it under the terms of the GNU General Public License7* as published by the Free Software Foundation; either version8* 2 of the License, or (at your option) any later version.9*10*/1112#include <linux/sys.h>13#include <linux/linkage.h>14#include <asm/setup.h>15#include <asm/segment.h>16#include <asm/page.h>17#include <asm/ptrace.h>18#include <asm/errno.h>19#include <asm/cache.h>20#include <asm/spr-regs.h>2122#define __addr_MASK 0xfeff9820 /* interrupt controller mask */2324#define __addr_FR55X_DRCN 0xfeff0218 /* Address of DRCN register */25#define FR55X_DSTS_OFFSET -4 /* Offset from DRCN to DSTS */26#define FR55X_SDRAMC_DSTS_SSI 0x00000002 /* indicates that the SDRAM is in self-refresh mode */2728#define __addr_FR4XX_DRCN 0xfe000430 /* Address of DRCN register */29#define FR4XX_DSTS_OFFSET -8 /* Offset from DRCN to DSTS */30#define FR4XX_SDRAMC_DSTS_SSI 0x00000001 /* indicates that the SDRAM is in self-refresh mode */3132#define SDRAMC_DRCN_SR 0x00000001 /* transition SDRAM into self-refresh mode */3334.section .bss35.balign 836.globl __sleep_save_area37__sleep_save_area:38.space 16394041.text42.balign 44344.macro li v r45sethi.p %hi(\v),\r46setlo %lo(\v),\r47.endm4849#ifdef CONFIG_PM50###############################################################################51#52# CPU suspension routine53# - void frv_cpu_suspend(unsigned long pdm_mode)54#55###############################################################################56.globl frv_cpu_suspend57.type frv_cpu_suspend,@function58frv_cpu_suspend:5960#----------------------------------------------------61# save hsr0, psr, isr, and lr for resume code62#----------------------------------------------------63li __sleep_save_area,gr116465movsg hsr0,gr466movsg psr,gr567movsg isr,gr668movsg lr,gr769stdi gr4,@(gr11,#0)70stdi gr6,@(gr11,#8)7172# store the return address from sleep in GR14, and its complement in GR13 as a check73li __ramboot_resume,gr1474#ifdef CONFIG_MMU75# Resume via RAMBOOT# will turn MMU off, so bootloader needs a physical address.76sethi.p %hi(__page_offset),gr1377setlo %lo(__page_offset),gr1378sub gr14,gr13,gr1479#endif80not gr14,gr138182#----------------------------------------------------83# preload and lock into icache that code which may have to run84# when dram is in self-refresh state.85#----------------------------------------------------86movsg hsr0, gr387li HSR0_ICE,gr488or gr3,gr4,gr389movgs gr3,hsr090or gr3,gr8,gr7 // add the sleep bits for later9192li #__icache_lock_start,gr393li #__icache_lock_end,gr4941: icpl gr3,gr0,#195addi gr3,#L1_CACHE_BYTES,gr396cmp gr4,gr3,icc097bhi icc0,#0,1b9899# disable exceptions100movsg psr,gr8101andi.p gr8,#~PSR_PIL,gr8102andi gr8,~PSR_ET,gr8103movgs gr8,psr104ori gr8,#PSR_ET,gr8105106srli gr8,#28,gr4107subicc gr4,#3,gr0,icc0108beq icc0,#0,1f109# FR4xx110li __addr_FR4XX_DRCN,gr4111li FR4XX_SDRAMC_DSTS_SSI,gr5112li FR4XX_DSTS_OFFSET,gr6113bra __icache_lock_start1141:115# FR5xx116li __addr_FR55X_DRCN,gr4117li FR55X_SDRAMC_DSTS_SSI,gr5118li FR55X_DSTS_OFFSET,gr6119bra __icache_lock_start120121.size frv_cpu_suspend, .-frv_cpu_suspend122123#124# the final part of the sleep sequence...125# - we want it to be be cacheline aligned so we can lock it into the icache easily126# On entry: gr7 holds desired hsr0 sleep value127# gr8 holds desired psr sleep value128#129.balign L1_CACHE_BYTES130.type __icache_lock_start,@function131__icache_lock_start:132133#----------------------------------------------------134# put SDRAM in self-refresh mode135#----------------------------------------------------136137# Flush all data in the cache using the DCEF instruction.138dcef @(gr0,gr0),#1139140# Stop DMAC transfer141142# Execute dummy load from SDRAM143ldi @(gr11,#0),gr11144145# put the SDRAM into self-refresh mode146ld @(gr4,gr0),gr11147ori gr11,#SDRAMC_DRCN_SR,gr11148st gr11,@(gr4,gr0)149membar150151# wait for SDRAM to reach self-refresh mode1521: ld @(gr4,gr6),gr11153andcc gr11,gr5,gr11,icc0154beq icc0,#0,1b155156# Set the GPIO register so that the IRQ[3:0] pins become valid, as required.157# Set the clock mode (CLKC register) as required.158# - At this time, also set the CLKC register P0 bit.159160# Set the HSR0 register PDM field.161movgs gr7,hsr0162163# Execute NOP 32 times.164.rept 32165nop166.endr167168#if 0 // Fujitsu recommend to skip this and will update docs.169# Release the interrupt mask setting of the MASK register of the170# interrupt controller if necessary.171sti gr10,@(gr9,#0)172membar173#endif174175# Set the PSR register ET bit to 1 to enable interrupts.176movgs gr8,psr177178###################################################179# this is only reached if waking up via interrupt180###################################################181182# Execute NOP 32 times.183.rept 32184nop185.endr186187#----------------------------------------------------188# wake SDRAM from self-refresh mode189#----------------------------------------------------190ld @(gr4,gr0),gr11191andi gr11,#~SDRAMC_DRCN_SR,gr11192st gr11,@(gr4,gr0)193membar1942:195ld @(gr4,gr6),gr11 // Wait for it to come back...196andcc gr11,gr5,gr0,icc0197bne icc0,0,2b198199# wait for the SDRAM to stabilise200li 0x0100000,gr32013: subicc gr3,#1,gr3,icc0202bne icc0,#0,3b203204# now that DRAM is back, this is the end of the code which gets205# locked in icache.206__icache_lock_end:207.size __icache_lock_start, .-__icache_lock_start208209# Fall-through to the RAMBOOT# wakeup path210211###############################################################################212#213# resume from suspend re-entry point reached via RAMBOOT# and bootloader214#215###############################################################################216__ramboot_resume:217218#----------------------------------------------------219# restore hsr0, psr, isr, and leave saved lr in gr7220#----------------------------------------------------221li __sleep_save_area,gr11222#ifdef CONFIG_MMU223movsg hsr0,gr4224sethi.p %hi(HSR0_EXMMU),gr3225setlo %lo(HSR0_EXMMU),gr3226andcc gr3,gr4,gr0,icc0227bne icc0,#0,2f228229# need to use physical address230sethi.p %hi(__page_offset),gr3231setlo %lo(__page_offset),gr3232sub gr11,gr3,gr11233234# flush all tlb entries235setlos #64,gr4236setlos.p #PAGE_SIZE,gr5237setlos #0,gr62381:239tlbpr gr6,gr0,#6,#0240subicc.p gr4,#1,gr4,icc0241add gr6,gr5,gr6242bne icc0,#2,1b243244# need a temporary mapping for the current physical address we are245# using between time MMU is enabled and jump to virtual address is246# made.247sethi.p %hi(0x00000000),gr4248setlo %lo(0x00000000),gr4 ; physical address249setlos #xAMPRx_L|xAMPRx_M|xAMPRx_SS_256Mb|xAMPRx_S_KERNEL|xAMPRx_V,gr5250or gr4,gr5,gr5251252movsg cxnr,gr13253or gr4,gr13,gr4254255movgs gr4,iamlr1 ; mapped from real address 0256movgs gr5,iampr1 ; cached kernel memory at 0x000000002572:258#endif259260lddi @(gr11,#0),gr4 ; hsr0, psr261lddi @(gr11,#8),gr6 ; isr, lr262movgs gr4,hsr0263bar264265#ifdef CONFIG_MMU266sethi.p %hi(1f),gr11267setlo %lo(1f),gr11268jmpl @(gr11,gr0)2691:270movgs gr0,iampr1 ; get rid of temporary mapping271#endif272movgs gr5,psr273movgs gr6,isr274275#----------------------------------------------------276# unlock the icache which was locked before going to sleep277#----------------------------------------------------278li __icache_lock_start,gr3279li __icache_lock_end,gr42801: icul gr3281addi gr3,#L1_CACHE_BYTES,gr3282cmp gr4,gr3,icc0283bhi icc0,#0,1b284285#----------------------------------------------------286# back to business as usual287#----------------------------------------------------288jmpl @(gr7,gr0) ;289290#endif /* CONFIG_PM */291292###############################################################################293#294# CPU core sleep mode routine295#296###############################################################################297.globl frv_cpu_core_sleep298.type frv_cpu_core_sleep,@function299frv_cpu_core_sleep:300301# Preload into icache.302li #__core_sleep_icache_lock_start,gr3303li #__core_sleep_icache_lock_end,gr43043051: icpl gr3,gr0,#1306addi gr3,#L1_CACHE_BYTES,gr3307cmp gr4,gr3,icc0308bhi icc0,#0,1b309310bra __core_sleep_icache_lock_start311312.balign L1_CACHE_BYTES313__core_sleep_icache_lock_start:314315# (1) Set the PSR register ET bit to 0 to disable interrupts.316movsg psr,gr8317andi.p gr8,#~(PSR_PIL),gr8318andi gr8,#~(PSR_ET),gr4319movgs gr4,psr320321#if 0 // Fujitsu recommend to skip this and will update docs.322# (2) Set '1' to all bits in the MASK register of the interrupt323# controller and mask interrupts.324sethi.p %hi(__addr_MASK),gr9325setlo %lo(__addr_MASK),gr9326sethi.p %hi(0xffff0000),gr4327setlo %lo(0xffff0000),gr4328ldi @(gr9,#0),gr10329sti gr4,@(gr9,#0)330#endif331# (3) Flush all data in the cache using the DCEF instruction.332dcef @(gr0,gr0),#1333334# (4) Execute the memory barrier instruction335membar336337# (5) Set the GPIO register so that the IRQ[3:0] pins become valid, as required.338# (6) Set the clock mode (CLKC register) as required.339# - At this time, also set the CLKC register P0 bit.340# (7) Set the HSR0 register PDM field to 001 .341movsg hsr0,gr4342ori gr4,HSR0_PDM_CORE_SLEEP,gr4343movgs gr4,hsr0344345# (8) Execute NOP 32 times.346.rept 32347nop348.endr349350#if 0 // Fujitsu recommend to skip this and will update docs.351# (9) Release the interrupt mask setting of the MASK register of the352# interrupt controller if necessary.353sti gr10,@(gr9,#0)354membar355#endif356357# (10) Set the PSR register ET bit to 1 to enable interrupts.358movgs gr8,psr359360__core_sleep_icache_lock_end:361362# Unlock from icache363li __core_sleep_icache_lock_start,gr3364li __core_sleep_icache_lock_end,gr43651: icul gr3366addi gr3,#L1_CACHE_BYTES,gr3367cmp gr4,gr3,icc0368bhi icc0,#0,1b369370bralr371372.size frv_cpu_core_sleep, .-frv_cpu_core_sleep373374375