1 /* sleep.S: power saving mode entry
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
4 * Written by David Woodhouse (dwmw2@infradead.org)
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.
13 #include <linux/sys.h>
14 #include <linux/linkage.h>
15 #include <asm/setup.h>
16 #include <asm/segment.h>
18 #include <asm/ptrace.h>
19 #include <asm/errno.h>
20 #include <asm/cache.h>
21 #include <asm/spr-regs.h>
23 #define __addr_MASK 0xfeff9820 /* interrupt controller mask */
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 */
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 */
33 #define SDRAMC_DRCN_SR 0x00000001 /* transition SDRAM into self-refresh mode */
37 .globl __sleep_save_area
51 ###############################################################################
53 # CPU suspension routine
54 # - void frv_cpu_suspend(unsigned long pdm_mode)
56 ###############################################################################
57 .globl frv_cpu_suspend
58 .type frv_cpu_suspend,@function
61 #----------------------------------------------------
62 # save hsr0, psr, isr, and lr for resume code
63 #----------------------------------------------------
64 li __sleep_save_area,gr11
73 # store the return address from sleep in GR14, and its complement in GR13 as a check
74 li __ramboot_resume,gr14
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
83 #----------------------------------------------------
84 # preload and lock into icache that code which may have to run
85 # when dram is in self-refresh state.
86 #----------------------------------------------------
91 or gr3,gr8,gr7 // add the sleep bits for later
93 li #__icache_lock_start,gr3
94 li #__icache_lock_end,gr4
96 addi gr3,#L1_CACHE_BYTES,gr3
102 andi.p gr8,#~PSR_PIL,gr8
108 subicc gr4,#3,gr0,icc0
111 li __addr_FR4XX_DRCN,gr4
112 li FR4XX_SDRAMC_DSTS_SSI,gr5
113 li FR4XX_DSTS_OFFSET,gr6
114 bra __icache_lock_start
117 li __addr_FR55X_DRCN,gr4
118 li FR55X_SDRAMC_DSTS_SSI,gr5
119 li FR55X_DSTS_OFFSET,gr6
120 bra __icache_lock_start
122 .size frv_cpu_suspend, .-frv_cpu_suspend
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
130 .balign L1_CACHE_BYTES
131 .type __icache_lock_start,@function
134 #----------------------------------------------------
135 # put SDRAM in self-refresh mode
136 #----------------------------------------------------
138 # Flush all data in the cache using the DCEF instruction.
143 # Execute dummy load from SDRAM
146 # put the SDRAM into self-refresh mode
148 ori gr11,#SDRAMC_DRCN_SR,gr11
152 # wait for SDRAM to reach self-refresh mode
153 1: ld @(gr4,gr6),gr11
154 andcc gr11,gr5,gr11,icc0
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.
161 # Set the HSR0 register PDM field.
164 # Execute NOP 32 times.
170 # Set the PSR register ET bit to 1 to enable interrupts.
173 ###################################################
174 # this is only reached if waking up via interrupt
175 ###################################################
177 # Execute NOP 32 times.
182 #----------------------------------------------------
183 # wake SDRAM from self-refresh mode
184 #----------------------------------------------------
186 andi gr11,#~SDRAMC_DRCN_SR,gr11
190 ld @(gr4,gr6),gr11 // Wait for it to come back...
191 andcc gr11,gr5,gr0,icc0
194 # wait for the SDRAM to stabilise
196 3: subicc gr3,#1,gr3,icc0
199 # now that DRAM is back, this is the end of the code which gets
202 .size __icache_lock_start, .-__icache_lock_start
204 # Fall-through to the RAMBOOT# wakeup path
206 ###############################################################################
208 # resume from suspend re-entry point reached via RAMBOOT# and bootloader
210 ###############################################################################
213 #----------------------------------------------------
214 # restore hsr0, psr, isr, and leave saved lr in gr7
215 #----------------------------------------------------
216 li __sleep_save_area,gr11
219 sethi.p %hi(HSR0_EXMMU),gr3
220 setlo %lo(HSR0_EXMMU),gr3
221 andcc gr3,gr4,gr0,icc0
224 # need to use physical address
225 sethi.p %hi(__page_offset),gr3
226 setlo %lo(__page_offset),gr3
229 # flush all tlb entries
231 setlos.p #PAGE_SIZE,gr5
235 subicc.p gr4,#1,gr4,icc0
239 # need a temporary mapping for the current physical address we are
240 # using between time MMU is enabled and jump to virtual address is
242 sethi.p %hi(0x00000000),gr4
243 setlo %lo(0x00000000),gr4 ; physical address
244 setlos #xAMPRx_L|xAMPRx_M|xAMPRx_SS_256Mb|xAMPRx_S_KERNEL|xAMPRx_V,gr5
250 movgs gr4,iamlr1 ; mapped from real address 0
251 movgs gr5,iampr1 ; cached kernel memory at 0x00000000
255 lddi @(gr11,#0),gr4 ; hsr0, psr
256 lddi @(gr11,#8),gr6 ; isr, lr
265 movgs gr0,iampr1 ; get rid of temporary mapping
270 #----------------------------------------------------
271 # unlock the icache which was locked before going to sleep
272 #----------------------------------------------------
273 li __icache_lock_start,gr3
274 li __icache_lock_end,gr4
276 addi gr3,#L1_CACHE_BYTES,gr3
280 #----------------------------------------------------
281 # back to business as usual
282 #----------------------------------------------------
285 #endif /* CONFIG_PM */
287 ###############################################################################
289 # CPU core sleep mode routine
291 ###############################################################################
292 .globl frv_cpu_core_sleep
293 .type frv_cpu_core_sleep,@function
296 # Preload into icache.
297 li #__core_sleep_icache_lock_start,gr3
298 li #__core_sleep_icache_lock_end,gr4
301 addi gr3,#L1_CACHE_BYTES,gr3
305 bra __core_sleep_icache_lock_start
307 .balign L1_CACHE_BYTES
308 __core_sleep_icache_lock_start:
310 # (1) Set the PSR register ET bit to 0 to disable interrupts.
312 andi.p gr8,#~(PSR_PIL),gr8
313 andi gr8,#~(PSR_ET),gr4
316 # (3) Flush all data in the cache using the DCEF instruction.
319 # (4) Execute the memory barrier instruction
322 # (5) Set the GPIO register so that the IRQ[3:0] pins become valid, as required.
323 # (6) Set the clock mode (CLKC register) as required.
324 # - At this time, also set the CLKC register P0 bit.
325 # (7) Set the HSR0 register PDM field to 001 .
327 ori gr4,HSR0_PDM_CORE_SLEEP,gr4
330 # (8) Execute NOP 32 times.
336 # (10) Set the PSR register ET bit to 1 to enable interrupts.
339 __core_sleep_icache_lock_end:
342 li __core_sleep_icache_lock_start,gr3
343 li __core_sleep_icache_lock_end,gr4
345 addi gr3,#L1_CACHE_BYTES,gr3
351 .size frv_cpu_core_sleep, .-frv_cpu_core_sleep