1/*
2 * Copyright (c) 2016 Cadence Design Systems, Inc.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6#include <xtensa/coreasm.h>
7#include <xtensa/corebits.h>
8#include <xtensa/cacheasm.h>
9#include <xtensa/cacheattrasm.h>
10#include <xtensa/xtensa-xer.h>
11#include <xtensa/xdm-regs.h>
12#include <xtensa/config/specreg.h>
13#include <xtensa/config/system.h>  /* for XSHAL_USE_ABSOLUTE_LITERALS only */
14#include <xtensa/xtruntime-core-state.h>
15
16/*
17 * The following reset vector avoids initializing certain registers already
18 * initialized by processor reset.  But it does initialize some of them
19 * anyway, for minimal support of warm restart (restarting in software by
20 * jumping to the reset vector rather than asserting hardware reset).
21 */
22
23	.begin	literal_prefix	.ResetVector
24	.section		.ResetVector.text, "ax"
25
26	.align	4
27	.global	__start
28__start:
29
30#if (!XCHAL_HAVE_HALT || defined(XTOS_UNPACK)) && XCHAL_HAVE_IMEM_LOADSTORE
31	/*
32	 *  NOTE:
33	 *
34	 *  IMPORTANT:  If you move the _ResetHandler portion to a section
35	 *  other than .ResetVector.text that is outside the range of
36	 *  the reset vector's 'j' instruction, the _ResetHandler symbol
37	 *  and a more elaborate j/movi/jx sequence are needed in
38	 *  .ResetVector.text to dispatch to the new location.
39	 */
40	j	_ResetHandler
41
42	.size	__start, . - __start
43
44#if XCHAL_HAVE_HALT
45	/*
46	 *  Xtensa TX: reset vector segment is only 4 bytes, so must place the
47	 *  unpacker code elsewhere in the memory that contains the reset
48	 *  vector.
49	 */
50#if XCHAL_RESET_VECTOR_VADDR == XCHAL_INSTRAM0_VADDR
51	.section .iram0.text, "ax"
52#elif XCHAL_RESET_VECTOR_VADDR == XCHAL_INSTROM0_VADDR
53	.section .irom0.text, "ax"
54#elif XCHAL_RESET_VECTOR_VADDR == XCHAL_URAM0_VADDR
55	.section .uram0.text, "ax"
56#else
57#warning "Xtensa TX reset vector not at start of iram0, irom0, or uram0 -- ROMing LSPs may not work"
58	.text
59#endif
60#endif /* XCHAL_HAVE_HALT */
61
62	.extern	__memctl_default
63
64	.align	4
65
66	/* tells the assembler/linker to place literals here */
67	.literal_position
68	.align	4
69	.global	_ResetHandler
70_ResetHandler:
71#endif
72
73#if !XCHAL_HAVE_HALT
74
75	/*
76	 *  Even if the processor supports the non-PC-relative L32R option,
77	 *  it will always start up in PC-relative mode.  We take advantage of
78	 *  this, and use PC-relative mode at least until we're sure the .lit4
79	 *  section is in place (which is sometimes only after unpacking).
80	 */
81	.begin	no-absolute-literals
82
83	/*
84	 * If we have dynamic cache way support, init the caches as soon
85	 * as we can, which is now. Except, if we are waking up from a
86	 * PSO event, then we need to do this slightly later.
87	 */
88#if XCHAL_HAVE_ICACHE_DYN_WAYS || XCHAL_HAVE_DCACHE_DYN_WAYS
89# if XCHAL_HAVE_PSO_CDM && !XCHAL_HAVE_PSO_FULL_RETENTION
90	 /* Do this later on in the code -- see below */
91# else
92	movi	a0, __memctl_default
93	wsr	a0, MEMCTL
94# endif
95#endif
96
97	/*
98	 * If we have PSO support, then we must check for a warm start with
99	 * caches left powered on. If the caches had been left powered on,
100	 * we must restore the state of MEMCTL to the saved state if any.
101	 * Note that MEMCTL may not be present depending on config.
102	 */
103#if XCHAL_HAVE_PSO_CDM && !XCHAL_HAVE_PSO_FULL_RETENTION
104	/* Read PWRSTAT */
105	movi	a2, XDM_MISC_PWRSTAT
106	/* Save area address - retained for later */
107	movi	a3, xthal_pso_savearea
108	/* Signature for compare - retained for later */
109	movi	a5, CORE_STATE_SIGNATURE
110	 /* PWRSTAT value - retained for later */
111	rer	a7, a2
112	/* Now bottom 2 bits are core wakeup and cache power lost */
113	extui	a4, a7, 1, 2
114	/* a4==1 means PSO wakeup, caches did not lose power */
115	bnei	a4, 1, .Lcold_start
116	/* Load save area signature field */
117	l32i	a4, a3, CS_SA_signature
118	sub	a4, a4, a5
119	/* If signature mismatch then do cold start */
120	bnez	a4, .Lcold_start
121#if XCHAL_USE_MEMCTL
122	/* Load saved MEMCTL value */
123	l32i	a4, a3, CS_SA_memctl
124	movi	a0, ~MEMCTL_INV_EN
125	/* Clear invalidate bit */
126	and	a0, a4, a0
127	wsr	a0, MEMCTL
128#endif
129	j	.Lwarm_start
130
131.Lcold_start:
132
133#if XCHAL_HAVE_ICACHE_DYN_WAYS || XCHAL_HAVE_DCACHE_DYN_WAYS
134	/*
135	 * Enable and invalidate all ways of both caches. If there is no
136	 * dynamic way support then this write will have no effect.
137	 */
138	movi	a0, __memctl_default
139	wsr	a0, MEMCTL
140#endif
141
142.Lwarm_start:
143
144#endif
145	/* a0 is always 0 in this code, used to initialize lots of things */
146	movi	a0, 0
147
148/* technically this should be under !FULL_RESET, assuming hard reset */
149#if XCHAL_HAVE_INTERRUPTS
150	/* make sure that interrupts are shut off (*before* we lower
151	 * PS.INTLEVEL and PS.EXCM!)
152	 */
153	wsr.intenable	a0
154#if (XCHAL_NUM_INTERRUPTS > 32)
155	wsr.intenable1	a0
156#endif
157#if (XCHAL_NUM_INTERRUPTS > 64)
158	wsr.intenable2	a0
159#endif
160#if (XCHAL_NUM_INTERRUPTS > 96)
161	wsr.intenable3	a0
162#endif
163#endif
164
165#if !XCHAL_HAVE_FULL_RESET
166
167/* pre-LX2 cores only */
168#if XCHAL_HAVE_CCOUNT && (XCHAL_HW_MIN_VERSION < XTENSA_HWVERSION_RB_2006_0)
169	/* not really necessary, but nice; best done very early */
170	wsr	a0, CCOUNT
171#endif
172
173	/*
174	 * For full MMU configs, put page table at an unmapped virtual address.
175	 * This ensures that accesses outside the static maps result
176	 * in miss exceptions rather than random behaviour.
177	 * Assumes XCHAL_SEG_MAPPABLE_VADDR == 0 (true in released MMU).
178	 */
179#if XCHAL_ITLB_ARF_WAYS > 0 || XCHAL_DTLB_ARF_WAYS > 0
180	wsr	a0, PTEVADDR
181#endif
182
183	/*
184	 * Debug initialization
185	 *
186	 * NOTE: DBREAKCn must be initialized before the combination of these
187	 * two things: any load/store, and a lowering of PS.INTLEVEL below
188	 * DEBUG_LEVEL.  The processor already resets IBREAKENABLE
189	 * appropriately.
190	 */
191#if XCHAL_HAVE_DEBUG
192#if XCHAL_NUM_DBREAK
193#if XCHAL_NUM_DBREAK >= 2
194	wsr	a0, DBREAKC1
195#endif
196	wsr	a0, DBREAKC0
197	dsync			 /* wait for WSRs to DBREAKCn to complete */
198#endif /* XCHAL_NUM_DBREAK */
199
200/* pre-LX cores only */
201# if XCHAL_HW_MIN_VERSION < XTENSA_HWVERSION_RA_2004_1
202	/*
203	 *  Starting in Xtensa LX, ICOUNTLEVEL resets to zero (not 15), so no
204	 *  need to initialize it.  Prior to that we do, otherwise we get an
205	 *  ICOUNT exception, 2^32 instructions after reset.
206	 */
207
208	/* are we being debugged? (detected by ICOUNTLEVEL not 15, or dropped
209	 * below 12)
210	 */
211	rsr	a2, ICOUNTLEVEL
212	/* if so, avoid initializing ICOUNTLEVEL which drops single-steps
213	 * through here
214	 * */
215	bltui	a2, 12, 1f
216	 /* avoid ICOUNT exceptions */
217	wsr	a0, ICOUNTLEVEL
218	/* wait for WSR to ICOUNTLEVEL to complete */
219	isync
2201:
221#endif
222#endif /* XCHAL_HAVE_DEBUG */
223
224#endif /* !XCHAL_HAVE_FULL_RESET */
225
226#if XCHAL_HAVE_ABSOLUTE_LITERALS
227	/* Technically, this only needs to be done under !FULL_RESET,
228	 * assuming hard reset:
229	 */
230	wsr	a0, LITBASE
231	rsync
232#endif
233
234#if XCHAL_HAVE_PSO_CDM && ! XCHAL_HAVE_PSO_FULL_RETENTION
235	/*
236	 * If we're powering up from a temporary power shut-off (PSO),
237	 * restore state saved just prior to shut-off. Note that the
238	 * MEMCTL register was already restored earlier, and as a side
239	 * effect, registers a3, a5, a7 are now preloaded with values
240	 * that we will use here.
241	 * a3 - pointer to save area base address (xthal_pso_savearea)
242	 * a5 - saved state signature (CORE_STATE_SIGNATURE)
243	 * a7 - contents of PWRSTAT register
244	 */
245
246	/* load save area signature */
247	l32i	a4, a3, CS_SA_signature
248	/* compare signature with expected one */
249	sub	a4, a4, a5
250# if XTOS_PSO_TEST
251	/* pretend PSO warm start with warm caches */
252	movi	a7, PWRSTAT_WAKEUP_RESET
253# endif
254	/* wakeup from PSO? (branch if not) */
255	bbci.l	a7, PWRSTAT_WAKEUP_RESET_SHIFT, 1f
256	/* Yes, wakeup from PSO.  Check whether state was properly saved.
257	 * speculatively clear PSO-wakeup bit  */
258	addi	a5, a7, - PWRSTAT_WAKEUP_RESET
259	/* if state not saved (corrupted?), mark as cold start */
260	movnez	a7, a5, a4
261	/* if state not saved, just continue with reset */
262	bnez	a4, 1f
263	/* Wakeup from PSO with good signature.  Now check cache status:
264	 * if caches warm, restore now  */
265	bbci.l	a7, PWRSTAT_CACHES_LOST_POWER_SHIFT, .Lpso_restore
266	/* Caches got shutoff.  Continue reset, we'll end up initializing
267	 * caches, and check again later for PSO.
268	 */
269# if XCHAL_HAVE_PRID && XCHAL_HAVE_S32C1I
270	j	.Ldonesync	 /* skip reset sync, only done for cold start */
271# endif
2721:	/*  Cold start.  (Not PSO wakeup.)  Proceed with normal full reset. */
273#endif
274
275#if XCHAL_HAVE_PRID && XCHAL_HAVE_S32C1I
276	/* Core 0 initializes the XMP synchronization variable, if present.
277	 * This operation needs to happen as early as possible in the startup
278	 * sequence so that the other cores can be released from reset.
279	 */
280	.weak _ResetSync
281	movi 	a2, _ResetSync	 /* address of sync variable */
282	rsr.prid a3		 /* core and multiprocessor ID */
283	extui 	a3, a3, 0, 8	 /* extract core ID (FIXME: need proper
284				  * constants for PRID bits to extract) */
285	beqz	a2, .Ldonesync	 /* skip if no sync variable */
286	bnez	a3, .Ldonesync	 /* only do this on core 0 */
287	s32i	a0, a2, 0	 /* clear sync variable */
288.Ldonesync:
289#endif
290#if XCHAL_HAVE_EXTERN_REGS && XCHAL_HAVE_MP_RUNSTALL
291	/* On core 0, this releases other cores.  On other cores this has no
292	 * effect, because runstall control is unconnected
293	 */
294	movi	a2, XER_MPSCORE
295	wer	a0, a2
296#endif
297
298	/*
299	 * For processors with relocatable vectors, apply any alternate
300	 * vector base given to xt-genldscripts, which sets the
301	 * _memmap_vecbase_reset symbol accordingly.
302	 */
303#if XCHAL_HAVE_VECBASE
304	/* note: absolute symbol, not a ptr */
305	movi	a2, _memmap_vecbase_reset
306	wsr	a2, vecbase
307#endif
308
309/* have ATOMCTL ? */
310#if XCHAL_HAVE_S32C1I && (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RC_2009_0)
311#if XCHAL_DCACHE_IS_COHERENT
312	/* MX -- internal for writeback, RCW otherwise */
313	movi	a3, 0x25
314#else
315	/* non-MX -- always RCW */
316	movi	a3, 0x15
317#endif /* XCHAL_DCACHE_IS_COHERENT */
318	wsr	a3, ATOMCTL
319#endif
320
321#if XCHAL_HAVE_INTERRUPTS && XCHAL_HAVE_DEBUG
322	/* lower PS.INTLEVEL here to make reset vector easier to debug */
323	rsil	a2, 1
324#endif
325
326	/* If either of the caches does not have dynamic way support, then
327	 * use the old (slow) method to init them. If the cache is absent
328	 * the macros will expand to empty.
329	 */
330#if ! XCHAL_HAVE_ICACHE_DYN_WAYS
331	icache_reset	a2, a3
332#endif
333#if ! XCHAL_HAVE_DCACHE_DYN_WAYS
334	dcache_reset	a2, a3
335#endif
336
337#if XCHAL_HAVE_PSO_CDM && ! XCHAL_HAVE_PSO_FULL_RETENTION
338	/* Here, a7 still contains status from the power status register,
339	 * or zero if signature check failed.
340	 */
341
342	/* wakeup from PSO with good signature? */
343	bbci.l	a7, PWRSTAT_WAKEUP_RESET_SHIFT, .Lcoldstart
344	/* Yes, wakeup from PSO.  Caches had been powered down, now are
345	 * initialized.
346	 */
347.Lpso_restore:
348	/* Assume memory still initialized, so all code still unpacked etc.
349	 * So we can just jump/call to relevant state restore code (wherever
350	 * located).
351	 */
352
353	/* make shutoff routine return zero */
354	movi	a2, 0
355	movi	a3, xthal_pso_savearea
356	/* Here, as below for _start, call0 is used as an unlimited-range
357	 * jump.
358	 */
359	call0	xthal_core_restore_nw
360	/*  (does not return) */
361.Lcoldstart:
362#endif
363
364#if XCHAL_HAVE_PREFETCH
365	/* Enable cache prefetch if present.  */
366	movi	a2, XCHAL_CACHE_PREFCTL_DEFAULT
367	wsr	a2, PREFCTL
368#endif
369
370	/*
371	 *  Now setup the memory attributes.  On some cores this "enables"
372	 *  caches.  We do this ahead of unpacking, so it can proceed more
373	 *  efficiently.
374	 *
375	 *  The _memmap_cacheattr_reset symbol's value (address) is defined by
376	 *  the LSP's linker script, as generated by xt-genldscripts.  If
377	 *  defines 4-bit attributes for eight 512MB regions.
378	 *
379	 *  (NOTE:  for cores with the older MMU v1 or v2, or without any
380	 *  memory protection mechanism, the following code has no effect.)
381	 */
382#if XCHAL_HAVE_MPU
383	/*  If there's an empty background map, setup foreground maps to mimic
384	 *  region protection:
385	 */
386# if XCHAL_MPU_ENTRIES >= 8 && XCHAL_MPU_BACKGROUND_ENTRIES <= 2
387	.pushsection .rodata, "a"
388	.global _xtos_mpu_attribs
389	.align 4
390_xtos_mpu_attribs:
391	/*  Illegal	(---) */
392	.word   0x00006000+XCHAL_MPU_ENTRIES-8
393	/* Writeback	(rwx Cacheable Non-shareable wb rd-alloc wr-alloc) */
394	.word   0x000F7700+XCHAL_MPU_ENTRIES-8
395	/* WBNA		(rwx Cacheable Non-shareable wb rd-alloc) */
396	.word   0x000D5700+XCHAL_MPU_ENTRIES-8
397	/* Writethru	(rwx Cacheable Non-shareable wt rd-alloc) */
398	.word   0x000C4700+XCHAL_MPU_ENTRIES-8
399	/* Bypass	(rwx Device non-interruptible system-shareable) */
400	.word   0x00006700+XCHAL_MPU_ENTRIES-8
401	.popsection
402
403	/*
404	 * We assume reset state:  all MPU entries zeroed and disabled.
405	 * Otherwise we'd need a loop to zero everything.
406	 */
407	/* note: absolute symbol, not a ptr */
408	movi	a2, _memmap_cacheattr_reset
409	movi	a3, _xtos_mpu_attribs
410	movi	a4, 0x20000000	/* 512 MB delta */
411	movi	a6, 8
412	movi	a7, 1		/* MPU entry vaddr 0, with valid bit set */
413	movi	a9, 0		/* cacheadrdis value */
414	/* enable everything temporarily while MPU updates */
415	wsr.cacheadrdis a9
416
417	/* Write eight MPU entries, from the last one going backwards
418	 * (entries n-1 thru n-8)
419	 */
4202:	extui	a8, a2, 28, 4	/* get next attribute nibble (msb first) */
421	extui	a5, a8, 0, 2	/* lower two bit indicate whether cached */
422	slli	a9, a9, 1	/* add a bit to cacheadrdis... */
423	addi	a10, a9, 1	/* set that new bit if... */
424	moveqz	a9, a10, a5	/* ... that region is non-cacheable */
425	addx4	a5, a8, a3	/* index into _xtos_mpu_attribs table */
426	addi	a8, a8, -5	/* make valid attrib indices negative */
427	movgez	a5, a3, a8	/* if not valid attrib, use Illegal */
428	l32i	a5, a5, 0	/* load access rights, memtype from table
429				 * entry
430				 */
431	slli	a2, a2, 4
432	sub	a7, a7, a4	/* next 512MB region (last to first) */
433	addi	a6, a6, -1
434	add	a5, a5, a6	/* add the index */
435	wptlb	a5, a7		/* write the MPU entry */
436	bnez	a6, 2b		/* loop until done */
437# else
438	/* default value of CACHEADRDIS for bgnd map */
439	movi	a9, XCHAL_MPU_BG_CACHEADRDIS
440# endif
441	wsr.cacheadrdis a9			 /* update cacheadrdis */
442#elif XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR \
443		|| XCHAL_HAVE_XLT_CACHEATTR \
444		|| (XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY)
445	/* note: absolute symbol, not a ptr */
446	movi	a2, _memmap_cacheattr_reset
447	/* set CACHEATTR from a2 (clobbers a3-a8) */
448	cacheattr_set
449#endif
450
451	/* Now that caches are initialized, cache coherency can be enabled. */
452#if XCHAL_DCACHE_IS_COHERENT
453# if XCHAL_HAVE_EXTERN_REGS && XCHAL_HAVE_MX && \
454		(XCHAL_HW_MIN_VERSION < XTENSA_HWVERSION_RE_2012_0)
455	/* Opt into coherence for MX (for backward compatibility / testing). */
456	movi	a3, 1
457	movi	a2, XER_CCON
458	wer	a3, a2
459# endif
460#endif
461
462	/* Enable zero-overhead loop instr buffer, and snoop responses, if
463	 * configured.  If HW erratum 453 fix is to be applied, then don't
464	 * enable loop instr buffer.
465	 */
466#if XCHAL_USE_MEMCTL && XCHAL_SNOOP_LB_MEMCTL_DEFAULT
467	movi	a3, XCHAL_SNOOP_LB_MEMCTL_DEFAULT
468	rsr	a2, MEMCTL
469	or	a2, a2, a3
470	wsr	a2, MEMCTL
471#endif
472
473	/* Caches are all up and running, clear PWRCTL.ShutProcOffOnPWait. */
474#if XCHAL_HAVE_PSO_CDM
475	movi	a2, XDM_MISC_PWRCTL
476	movi	a4, ~PWRCTL_CORE_SHUTOFF
477	rer	a3, a2
478	and	a3, a3, a4
479	wer	a3, a2
480#endif
481
482#endif /* !XCHAL_HAVE_HALT */
483
484	/*
485	 *  Unpack code and data (eg. copy ROMed segments to RAM, vectors into
486	 *  their proper location, etc).
487	 */
488
489#if defined(XTOS_UNPACK)
490	movi	a2, _rom_store_table
491	beqz	a2, unpackdone
492unpack:	l32i	a3, a2, 0	 /* start vaddr */
493	l32i	a4, a2, 4	 /* end vaddr */
494	l32i	a5, a2, 8	 /* store vaddr */
495	addi	a2, a2, 12
496	bgeu	a3, a4, upnext	 /* skip unless start < end */
497uploop:	l32i 	a6, a5, 0
498	addi	a5, a5, 4
499	s32i	a6, a3, 0
500	addi	a3, a3, 4
501	bltu	a3, a4, uploop
502	j	unpack
503upnext:	bnez	a3, unpack
504	bnez	a5, unpack
505#endif /* XTOS_UNPACK */
506
507unpackdone:
508
509#if defined(XTOS_UNPACK) || defined(XTOS_MP)
510	/*
511	 * If writeback caches are configured and enabled, unpacked data must
512	 * be written out to memory before trying to execute it:
513	 */
514	dcache_writeback_all	a2, a3, a4, 0
515	/* ensure data written back is visible to i-fetch */
516	icache_sync		a2
517	/*
518	 * Note:  no need to invalidate the i-cache after the above, because
519	 * we already invalidated it further above and did not execute
520	 * anything within unpacked regions afterwards.  [Strictly speaking,
521	 * if an unpacked region follows this code very closely, it's possible
522	 * for cache-ahead to have cached a bit of that unpacked region, so in
523	 * the future we may need to invalidate the entire i-cache here again
524	 * anyway.]
525	 */
526#endif
527
528
529#if !XCHAL_HAVE_HALT	/* skip for TX */
530
531	/*
532	 *  Now that we know the .lit4 section is present (if got unpacked)
533	 *  (and if absolute literals are used), initialize LITBASE to use it.
534	 */
535#if XCHAL_HAVE_ABSOLUTE_LITERALS && XSHAL_USE_ABSOLUTE_LITERALS
536	/*
537	 *  Switch from PC-relative to absolute (litbase-relative) L32R mode.
538	 *  Set LITBASE to 256 kB beyond the start of the literals in .lit4
539	 *  (aligns to the nearest 4 kB boundary, LITBASE does not have bits
540	 *  1..11) and set the enable bit (_lit4_start is assumed 4-byte
541	 *  aligned).
542	 */
543	movi	a2, _lit4_start + 0x40001
544	wsr	a2, LITBASE
545	rsync
546#endif /* have and use absolute literals */
547	/* we can now start using absolute literals */
548	.end	no-absolute-literals
549
550	/* Technically, this only needs to be done pre-LX2, assuming hard
551	 * reset:
552	 */
553# if XCHAL_HAVE_WINDOWED && defined(__XTENSA_WINDOWED_ABI__)
554	/* Windowed register init, so we can call windowed code (eg. C code). */
555	movi	a1, 1
556	wsr	a1, WINDOWSTART
557	/*
558	 *  The processor always clears WINDOWBASE at reset, so no need to
559	 *  clear it here.  It resets WINDOWSTART to 1 starting with LX2.0/X7.0
560	 *  (RB-2006.0).  However, assuming hard reset is not yet always
561	 *  practical, so do this anyway:
562	 */
563	wsr	a0, WINDOWBASE
564	rsync
565	movi	a0, 0			 /* possibly a different a0, clear it */
566# endif
567
568/* only pre-LX2 needs this */
569#if XCHAL_HW_MIN_VERSION < XTENSA_HWVERSION_RB_2006_0
570	/* Coprocessor option initialization */
571# if XCHAL_HAVE_CP
572	/*
573	 * To allow creating new coprocessors using TC that are not known
574	 * at GUI build time without having to explicitly enable them,
575	 * all CPENABLE bits must be set, even though they may not always
576	 * correspond to a coprocessor.
577	 */
578#ifdef CONFIG_XTENSA_LAZY_HIFI_SHARING
579	/*
580	 * Disable HiFi coprocessor by default. Should a thread try using
581         * the HiFi coprocessor, it will trigger an exception to both enable
582	 * it AND save/restore the HiFi state.
583	 */
584
585	movi	a2, 0xFF & ~(1 << XCHAL_CP_ID_AUDIOENGINELX)
586#else
587	movi	a2, 0xFF	 /* enable *all* bits, to allow dynamic TIE */
588#endif
589	wsr	a2, CPENABLE
590# endif
591
592	/*
593	 * Floating point coprocessor option initialization (at least
594	 * rounding mode, so that floating point ops give predictable results)
595	 */
596# if XCHAL_HAVE_FP && !XCHAL_HAVE_VECTORFPU2005
597/* floating-point control register (user register number) */
598#  define FCR	232
599/* floating-point status register (user register number) */
600#  define FSR	233
601	/* wait for WSR to CPENABLE to complete before accessing FP coproc
602	 * state
603	 */
604	rsync
605	wur	a0, FCR	/* clear FCR (default rounding mode, round-nearest) */
606	wur	a0, FSR	/* clear FSR */
607# endif
608#endif /* pre-LX2 */
609
610
611	/*
612	 *  Initialize memory error handler address.
613	 *  Putting this address in a register allows multiple instances of
614	 *  the same configured core (with separate program images but shared
615	 *  code memory, thus forcing memory error vector to be shared given
616	 *  it is not VECBASE relative) to have the same memory error vector,
617	 *  yet each have their own handler and associated data save area.
618	 */
619#if XCHAL_HAVE_MEM_ECC_PARITY
620	movi	a4, _MemErrorHandler
621	wsr	a4, MESAVE
622#endif
623
624
625	/*
626	 *  Initialize medium and high priority interrupt dispatchers:
627	 */
628#if HAVE_XSR
629
630/*  For asm macros; works for positive a,b smaller than 1000:  */
631# define GREATERTHAN(a,b)	(((b)-(a)) & ~0xFFF)
632
633# ifndef XCHAL_DEBUGLEVEL		/* debug option not selected? */
634#  define XCHAL_DEBUGLEVEL	99	/* bogus value outside 2..6 */
635# endif
636
637	.macro	init_vector	level
638	  .if GREATERTHAN(XCHAL_NUM_INTLEVELS+1,\level)
639	    .if XCHAL_DEBUGLEVEL-\level
640	      .weak   _Level&level&FromVector
641	      movi    a4, _Level&level&FromVector
642	      wsr     a4, EXCSAVE+\level
643	      .if GREATERTHAN(\level,XCHAL_EXCM_LEVEL)
644		movi    a5, _Pri_&level&_HandlerAddress
645		s32i    a4, a5, 0
646		/*  If user provides their own handler, that handler might
647		 *  not provide its own _Pri_<n>_HandlerAddress variable for
648		 *  linking handlers.  In that case, the reference below
649		 *  would pull in the XTOS handler anyway, causing a conflict.
650		 *  To avoid that, provide a weak version of it here:
651		 */
652		.pushsection .data, "aw"
653		.global  _Pri_&level&_HandlerAddress
654		.weak   _Pri_&level&_HandlerAddress
655		.align	4
656		_Pri_&level&_HandlerAddress: .space 4
657		.popsection
658	      .endif
659	    .endif
660	  .endif
661	.endm
662
663	init_vector	2
664	init_vector	3
665	init_vector	4
666	init_vector	5
667	init_vector	6
668
669#endif /*HAVE_XSR*/
670
671
672	/*
673	 *  Complete reset initialization outside the vector, to avoid
674	 *  requiring a vector that is larger than necessary.  This 2nd-stage
675	 *  startup code sets up the C Run-Time (CRT) and calls main().
676	 *
677	 *  Here we use call0 not because we expect any return, but because the
678	 *  assembler/linker dynamically sizes call0 as needed (with
679	 *  -mlongcalls) which it doesn't with j or jx.  Note:  This needs to
680	 *  be call0 regardless of the selected ABI.
681	 */
682	call0	_start		 /* jump to _start (in crt1-*.S) */
683	/* does not return */
684
685#else /* XCHAL_HAVE_HALT */
686
687	j	_start	/* jump to _start (in crt1-*.S) */
688			/* (TX has max 64kB IRAM, so J always in range) */
689
690	 /* Paranoia -- double-check requirements / assumptions of this Xtensa
691	  * TX code:
692	  */
693# if !defined(__XTENSA_CALL0_ABI__) || !XCHAL_HAVE_FULL_RESET \
694		|| XCHAL_HAVE_INTERRUPTS || XCHAL_HAVE_CCOUNT \
695		|| XCHAL_DTLB_ARF_WAYS || XCHAL_HAVE_DEBUG \
696		|| XCHAL_HAVE_S32C1I || XCHAL_HAVE_ABSOLUTE_LITERALS \
697		|| XCHAL_DCACHE_SIZE || XCHAL_ICACHE_SIZE || XCHAL_HAVE_PIF \
698		|| XCHAL_HAVE_WINDOWED
699#  error "Halt architecture (Xtensa TX) requires: call0 ABI, all flops reset, no exceptions or interrupts, no TLBs, no debug, no S32C1I, no LITBASE, no cache, no PIF, no windowed regs"
700# endif
701
702#endif /* XCHAL_HAVE_HALT */
703
704
705#if (!XCHAL_HAVE_HALT || defined(XTOS_UNPACK)) && XCHAL_HAVE_IMEM_LOADSTORE
706	.size	_ResetHandler, . - _ResetHandler
707#else
708	.size	__start, . - __start
709#endif
710
711	.text
712	.global xthals_hw_configid0, xthals_hw_configid1
713	.global xthals_release_major, xthals_release_minor
714	.end	literal_prefix
715