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