1// reset-pso.S  --  PSO restore routine, invoked from Reset Vector
2// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/core-shutoff.S#1 $
3
4// Copyright (c) 2012-2013 Tensilica Inc.
5//
6// Permission is hereby granted, free of charge, to any person obtaining
7// a copy of this software and associated documentation files (the
8// "Software"), to deal in the Software without restriction, including
9// without limitation the rights to use, copy, modify, merge, publish,
10// distribute, sublicense, and/or sell copies of the Software, and to
11// permit persons to whom the Software is furnished to do so, subject to
12// the following conditions:
13//
14// The above copyright notice and this permission notice shall be included
15// in all copies or substantial portions of the Software.
16//
17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25#include <xtensa/coreasm.h>
26#include <xtensa/corebits.h>
27#include <xtensa/cacheasm.h>
28#include <xtensa/cacheattrasm.h>
29#include <xtensa/xdm-regs.h>
30#include <xtensa/xtruntime-core-state.h>
31#include "xtos-internal.h"
32
33#if XCHAL_HAVE_PSO
34	.macro	simulate_reset
35	//  Single or multiple power domains, no retention.
36	//  Just simulate reset.  Set PS:
37	movi	a5, 0x1F
38	wsr.ps	a5
39	rsync
40	//  Scramble things:
41	rotw	3
42	//  Jump to reset vector:
43	movi	a5, _ResetVector
44	jx	a5
45	.endm
46#endif
47
48
49#if XCHAL_HAVE_PSO_CDM && ! XCHAL_HAVE_PSO_FULL_RETENTION
50	//  PSO: core state save area.
51	//  This could be pretty large (includes TIE state, TLB state, many regs).
52	//
53	.section .bss, "aw"
54	.align XCHAL_TOTAL_SA_ALIGN
55	.global _xtos_pso_savearea
56	.type _xtos_pso_savearea, @object
57	.size _xtos_pso_savearea, XtosCoreStateSize
58_xtos_pso_savearea:
59	.space XtosCoreStateSize
60#endif
61
62
63	.text
64
65
66	//  This version of the _xtos_core_shutoff() function can be called from assembly-level,
67	//  where the stack might not be defined/usable, so can't do window-spill
68	//  etc.  This saves address registers per call0 ABI (all except a0/a2..a11).
69	//
70	//  On entry:  a0 = return PC, a2 = flags argument, a3..a11 = undefined/available.
71	//  All other registers are saved/restored.
72	//
73	.align	4
74	.global	_xtos_core_shutoff_nw
75	.type _xtos_core_shutoff_nw,@function
76_xtos_core_shutoff_nw:
77#if XCHAL_HAVE_PSO_CDM && ! XCHAL_HAVE_PSO_FULL_RETENTION
78	movi	a5, _xtos_core_save_nw
79#endif
80	mov	a11, a0			// ABI-independent return PC
81	j	.Lcommon_shutoff
82	.size	_xtos_core_shutoff_nw, . - _xtos_core_shutoff_nw
83
84
85
86	//  int  _xtos_core_shutoff(unsigned flags)
87	//
88	//  Save all processor state and shut-off the core.
89	//  Returns when the core wakes up, and all state was restored
90	//  (except in single power domain case, see below).
91	//
92	//  For more details see:  System SW Ref Manual, XTOS Chapter.
93	//
94	//  Possible return values:
95	//
96	//	0	core did shut-off (return via reset vector,
97	//			or after waiti for full-retention case)
98	//
99	//	1,2	core did not shut-off (other requestors were already
100	//		requesting this core to stay on at time of call)
101	//		(1 == early,  2 == late)
102	//
103	//	3	core did not shut-off (multi-power-domains no retention,
104	//			and waiti resumed; FIXME: can this happen?)
105	//
106	//	-1	core does not have PSO feature
107	//
108	//  NOTE:  in the single power domain case, this function never returns.
109	//	The external system must power the core off than back on,
110	//	and execution resumes at the reset vector.
111	//
112	//  The flags parameter indicates whether to request memory and/or debug domains
113	//  to stay powered on while the core is shut-off.  (This parameter is ignored
114	//  for the single power domain case.)  If 0, they are both allowed to
115	//  shut-off (although other external requesters may keep them powered on).
116	//  Otherwise, one or both of these bits may be specified (or'ed together):
117	//	XTOS_KEEPON_MEM		force memory domain on during core power shut-off
118	//	XTOS_KEEPON_DEBUG	force debug domain on during core power shut-off
119	//  If XTOS_KEEPON_MEM is specified, dcache writeback is NOT done.
120	//
121	//  Effectively, the flags parameter sets the value of these two PWRCTL register
122	//  bits (over ERI) during core power shut-off.  The value of these two bits
123	//  (as they were prior to calling this function) are saved, and restored on wakeup.
124	//  Thus, if the core was requesting that the debug domain be powered on, and
125	//  _xtos_core_shutoff() lets it power-off, then upon wakeup, the software restore
126	//  sequence restores debug domain power, and waits for debug power to be ON.
127	//
128	//
129	.align	4
130	.global	_xtos_core_shutoff
131	.type _xtos_core_shutoff,@function
132_xtos_core_shutoff:
133	abi_entry
134
135#if XCHAL_HAVE_PSO_CDM && ! XCHAL_HAVE_PSO_FULL_RETENTION
136	movi	a5, _xtos_core_save_entry
137#endif
138	movi	a11, 1f		// ABI-independent return PC
139	j	.Lcommon_shutoff
140
1411:	abi_return
142
143
144
145
146	.align	4
147.Lcommon_shutoff:
148
149
150
151#if XCHAL_HAVE_PSO_CDM && XCHAL_HAVE_PSO_FULL_RETENTION
152	//  Multiple power domains, full retention in HW.
153	//  Do the minimum required (things that need to be changed during shutoff):
154
155	//  Check whether other agents are keeping this core powered on,
156	//  and avoid going through save sequence if we're not going to
157	//  power down anyway.
158	movi	a3, XDM_MISC_PWRSTAT
159	rer	a6, a3
160	movi	a5, 1		// indicates other agents want this core powered on
161	bbsi.l	a6, PWRSTAT_CORE_STILL_NEEDED_SHIFT, 1f
162
163	rsil	a8, 15				// disable interrupts
164
165#  if XCHAL_HAVE_PREFETCH
166	//  Save prefetch control and disable prefetch.
167	movi	a10, 0
168	xsr.prefctl	a10
169#  endif
170
171#  if XCHAL_DCACHE_IS_WRITEBACK
172	bbsi.l	a2, PWRCTL_MEM_WAKEUP_SHIFT, 7f	// letting caches power off?
173	dcache_writeback_all	a4, a7, a9,0	// yes: writeback
174	memw					// wait for writeback to complete
1757:
176#  endif
177
178	//  Save PWRCTL, and set ShutProcOffOnPWait (for WAITI to shut-off the core).
179	//  (With dcache coherence, can this be used as signal to system
180	//  to turn off snoops to this core?)
181	//
182	movi	a4, XDM_MISC_PWRCTL
183	rer	a9, a4				// get pwrctl
184	movi	a6, PWRCTL_CORE_SHUTOFF		// aka ShutProcOffOnPWait
185	or	a7, a9, a6			// indicate WAITI will shut-off
186	xor	a9, a7, a6			// make sure it's clear in saved pwrctl
187	wer	a7, a4				// write new pwrctl
188
189	//  Make sure everything stabilizes:
190	isync
191	extw
192
193	//  With ShutProcOffOnPWait set, external agents can't change their mind.
194	//  So check again whether other agents are keeping this core powered on,
195	//  and avoid going through save sequence if we're not going to
196	//  power down anyway.
197	rer	a6, a3		// read PWRSTAT
198	movi	a5, 2		// if abort: external agent wants core powered on
199	bbsi.l	a6, PWRSTAT_CORE_STILL_NEEDED_SHIFT, .Lshutoff_late_abort
200
201	//  Set PWRCTL MEM_WAKEUP bit according to flags (whether to let mem power off).
202	movi	a6, PWRCTL_MEM_WAKEUP
203	or	a5, a7, a6	// set...
204	xor	a5, a5, a6	// ... and clear MEM_WAKEUP bit to write
205	and	a6, a2, a6	// isolate MEM_WAKEUP bit from flags
206	or	a5, a5, a6	// set MEM_WAKEUP bit to write from flags
207	//  Clear PWRCTL DEBUG_WAKEUP bit if cleared in flags (if letting debug power off).
208	movi	a6, ~PWRCTL_DEBUG_WAKEUP
209	or	a6, a2, a6	// isolate DEBUG_WAKEUP bit from flags
210	and	a6, a5, a6	// clear it if was clear in flags
211	//  Update PWRCTL
212	wer	a6, a4		// write new pwrctl
213	extw			// let the new pwrctl value settle
214
215	//  Okay, go for it -- power down (shutoff).
216
217#  if !XTOS_PSO_TEST
218	waiti	0		// now shut-off! (interrupts enabled for power-on)
219#  endif
220	//  Resumes here after power comes back on, after some interrupt taken.
221	wsr.ps	a8		// restore interrupts
222	movi	a5, 0		// successful
223	rsync			// ensure wsr.ps completes
224
225	// FIXME:  do we need to initialize caches?
226
227.Lshutoff_late_abort:
228	wer	a7, a4		// restore pwrctl (except ShutProcOffOnPWait still set)
229
230	//  Wait for debug powerup to complete (if started):
231	bbci.l	a7, PWRCTL_DEBUG_WAKEUP_SHIFT, 3f
232	movi	a6, XDM_MISC_PWRSTAT
2332:	rer	a6, a6				// read PWRSTAT
234	bbci.l	a6, PWRSTAT_DEBUG_DOMAIN_ON_SHIFT, 2b	// loop until powered up
2353:
236
237#  if XCHAL_HAVE_PREFETCH
238	wsr.prefctl	a10	// restore prefetch control
239#  endif
240
241	//  If CachesLostPower bit set, is there need to initialize caches?
242
243	wer	a9, a4		// clear ShutProcOffOnPWait
244
245	wsr.ps	a8		// restore interrupts
246	rsync			// ensure wsr.ps completes
247
2481:	mov	a2, a5
249	jx	a11		// return (to ABI-dependent code if C callable)
250
251
252
253#elif XCHAL_HAVE_PSO_CDM /*&& !XCHAL_HAVE_PSO_FULL_RETENTION*/
254	//  Multiple power domains, no hardware retention.
255	//  Do full core state save/restore in software.
256
257	//  Check whether other agents are keeping this core powered on,
258	//  and avoid going through save sequence if we're not going to
259	//  power down anyway.
260	movi	a3, XDM_MISC_PWRSTAT
261	rer	a3, a3
262	bbsi.l	a3, PWRSTAT_CORE_STILL_NEEDED_SHIFT, 1f
263
264	movi	a3, XTOS_COREF_PSO
265	or	a2, a2, a3			// indicate power shutoff in flags
266
267	movi	a3, _xtos_pso_savearea
268	movi	a4, _xtos_core_shutoff_aftersave
269	jx	a5		// continue in _xtos_core_save (past prologue)
270				// which saves processor state, powers down
271				// debug/mem per a2, shuts off prefetch and
272				// snooping, and jumps to a4
273
2741:	movi	a2, 1		// other agents want this core powered on
275	jx	a11		// return (to ABI-dependent code if C callable)
276
277	.align	4
278	//.global	_xtos_core_shutoff_aftersave
279_xtos_core_shutoff_aftersave:
280
281	//  Multiple power domains, no retention.
282
283	//  Set ShutProcOffOnPWait, for WAITI to shut-off the core.
284	//  (With dcache coherence, can this be used as signal to system
285	//  to turn off snoops to this core?)
286	//
287	movi	a4, XDM_MISC_PWRCTL
288	rer	a7, a4				// get pwrctl
289	movi	a6, PWRCTL_CORE_SHUTOFF		// aka ShutProcOffOnPWait
290	or	a7, a7, a6			// indicate WAITI will shut-off
291	wer	a7, a4				// write new pwrctl
292
293	//  Make sure everything stabilizes:
294	isync
295	extw
296
297	//  Check whether other agents are keeping this core powered on,
298	//  and avoid going through save sequence if we're not going to
299	//  power down anyway.
300	movi	a4, XDM_MISC_PWRSTAT
301	movi	a2, 2		// if abort: external agent wants core powered on
302	rer	a6, a4
303	bbsi.l	a6, PWRSTAT_CORE_STILL_NEEDED_SHIFT, .Lshutoff_late_abort
304
305	//  Call system-specific function to wait for system specific
306	//  transactions to quiesce before shutting down the processor.
307	//  This function may also abort the shutdown, however whoever
308	//  attempts it must do it carefully:  the function must know
309	//  that it's possible to abort, it must do whatever's needed
310	//  in the system to resume normal execution (e.g. restart
311	//  snoops, DMA, etc), and for power reasons the software must
312	//  avoid calling this shutdown routine in the first place if
313	//  it can know then that it would end up aborting here.
314	//
315	//  This is always a call0 function.
316	//  TBD:  can it be a C function instead?
317	//  TBD:  describe exact calling conventions, if asm call0
318
319	.weak	xtos_system_ready_for_core_shutoff
320	movi	a2, xtos_system_ready_for_core_shutoff
321	//isync
322	beqz	a2, 1f
323	callx0	a2
324	bnez	a2, .Lshutoff_late_abort	// if function returns error, abort shutdown
3251:
326
327	//  Okay, go for it -- power down (shutoff).
328
329
330#  if XTOS_PSO_TEST
331	//  Test only -- weakly simulate shutoff in sw, don't actually do it.
332	simulate_reset
333#  elif XCHAL_HAVE_INTERRUPTS
334	waiti	15		// now shut-off!
335#  elif XCHAL_HAVE_HALT
336	halt
337#  else
338#   error "PSO assumes interrupts (for WAITI) or HALT architecture (for HALT)"
339#  endif
340
341	//  Execution should not proceed here.
342	//  If we get here, some error has occurred [FIXME]
343
344	movi	a2, 3				// WAITI resumed
345
346.Lshutoff_late_abort:
347	//  We end up here if returning from shutoff request.
348	//  Here, a2 == return code.
349	//  Restore what's been clobbered (and doesn't get restored by caller):
350	//	PWRCTL, MEMCTL, return PC.
351
352	l32i	a0, a3, CS_SA_restore_label	// restore return PC
353
354	//  Restore PWRCTL.
355	movi	a4, XDM_MISC_PWRCTL
356	l32i	a5, a3, CS_SA_pwrctl		// get saved pwrctl
357	wer	a5, a4				// restore pwrctl
358	//  Wait for debug powerup to complete (if started):
359	bbci.l	a5, PWRCTL_DEBUG_WAKEUP_SHIFT, 1f
360	movi	a7, XDM_MISC_PWRSTAT
3612:	rer	a6, a7				// read PWRSTAT
362	bbci.l	a6, PWRSTAT_DEBUG_DOMAIN_ON_SHIFT, 2b	// loop until powered up
3631:
364
365	//  Restore MEMCTL.
366#  if XCHAL_USE_MEMCTL
367	l32i	a5, a3, CS_SA_memctl
368	wsr.memctl	a5
369#  endif
370
371	//  Clear the signature, to mark save area as no longer valid.
372	s32i	a2, a3, CS_SA_signature
373#  if XCHAL_DCACHE_IS_WRITEBACK
374	dhwb	a3, CS_SA_signature
375#  endif
376
377	ret			// return from _xtos_core_save_common
378
379
380
381#elif XCHAL_HAVE_PSO
382	//  Single power domain.  (No retention.)
383
384	rsil	a8, 15				// disable interrupts
385
386#  if XCHAL_HAVE_PREFETCH
387	//  Disable prefetch.
388	movi	a10, 0
389	wsr.memctl	a10
390#  endif
391
392#  if XCHAL_DCACHE_IS_WRITEBACK
393	bbsi.l	a2, PWRCTL_MEM_WAKEUP_SHIFT, 7f	// letting caches power off?
394	dcache_writeback_all	a4, a5, a6, 0	// yes: writeback
395	memw					// wait for writeback to complete
3967:
397#  endif
398
3991:	waiti	15		// wait for shut-off
400	j	1b		// loop until we get powered off
401
402
403
404#else
405	//  No PSO.
406	movi	a2, -1
407	jx	a11		// return (to ABI-dependent code if C callable)
408
409#endif
410
411
412
413
414#if XCHAL_HAVE_PSO_CDM
415# if XCHAL_HAVE_PSO_FULL_RETENTION
416
417# else /* not full retention */
418
419
420# endif /* !retention */
421#endif /* multi power domains */
422
423
424	.size	_xtos_core_shutoff, . - _xtos_core_shutoff
425
426