1/*
2 * interAptiv/start.S
3 *
4 *  Created on: Jan 12, 2011
5 *  Author: MIPS TECHNOLOGIES, INC
6 *  Start of boot code for interAptiv Family of Cores
7*/
8/*
9Unpublished work (c) MIPS Technologies, Inc.  All rights reserved.  Unpublished rights reserved
10under the copyright laws of the United States of America and other countries.
11
12This code is confidential and proprietary to MIPS Technologies, Inc. ("MIPS Technologies") and
13may be disclosed only as permitted in writing by MIPS Technologies or an authorized third party.
14Any copying, reproducing, modifying, use or disclosure of this code (in whole or in part) that is
15not expressly permitted in writing by MIPS Technologies or an authorized third party is strictly
16prohibited. At a minimum, this code is protected under trade secret, unfair competition, and
17copyright laws. Violations thereof may result in criminal penalties and fines.
18
19MIPS Technologies reserves the right to change this code to improve function, design or
20otherwise. MIPS Technologies does not assume any liability arising out of the application or use
21of this code, or of any error or omission in such code.  Any warranties, whether express, statutory,
22implied or otherwise, including but not limited to the implied warranties of merchantability or
23fitness for a particular purpose, are excluded.  Except as expressly provided in any written license
24agreement from MIPS Technologies or an authorized third party, the furnishing of this code does
25not give recipient any license to any intellectual property rights, including any patent rights, that
26cover this code.
27
28This code shall not be exported, reexported, transferred, or released, directly or indirectly, in
29violation of the law of any country or international law, regulation, treaty, Executive Order,
30statute, amendments or supplements thereto.  Should a conflict arise regarding the export,
31reexport, transfer, or release of this code, the laws of the United States of America shall be
32the governing law.
33
34This code may only be disclosed to the United States government ("Government"), or to
35Government users, with prior written consent from MIPS Technologies or an authorized third
36party.  This code constitutes one or more of the following: commercial computer software,
37commercial computer software documentation or other commercial items.  If the user of this
38code, or any related documentation of any kind, including related technical data or manuals, is an
39agency, department, or other entity of the Government, the use, duplication, reproduction, release,
40modification, disclosure, or transfer of this code, or any related documentation of any kind, is
41restricted in accordance with Federal Acquisition Regulation 12.212 for civilian agencies and
42Defense Federal Acquisition Regulation Supplement 227.7202 for military agencies.  The use of
43this code by the Government is further restricted in accordance with the terms of the license
44agreement(s) and/or applicable contract terms and conditions covering this code from MIPS
45Technologies or an authorized third party.
46*/
47
48#include <boot.h>
49#include <m32c0.h>
50#include <regdef.h>
51#include <cps.h>
52
53/* EL Change.  Add address for optional user-specified vpe wakeup function.  */
54
55#ifdef TX_THREAD_SMP_WAKEUP_LOGIC
56    .globl      TX_THREAD_SMP_WAKEUP_LOGIC_SETUP
57#endif
58
59/* EL Change End.  */
60
61
62	.set	noreorder           // Don't allow the assembler to reorder instructions.
63	.set	noat                // Don't allow the assembler to use r1(at) for synthetic instr.
64/**************************************************************************************
65    R E S E T   E X C E P T I O N   H A N D L E R
66**************************************************************************************/
67// RAMHACK: Removed boot exception handlers.
68/**************************************************************************************
69    B O O T   E X C E P T I O N   H A N D L E R S
70**************************************************************************************/
71
72// RAMHACK: Removed boot exception handlers.
73
74
75/**************************************************************************************
76    R A M   E X C E P T I O N   H A N D L E R S
77**************************************************************************************/
78
79.section ".vector_0x000","ax"
80    .globl tlb_refill_exception
81tlb_refill_exception:
82    sdbbp
83
84.section ".vector_0x100","ax"
85    .globl cache_error_exception
86cache_error_exception:
87    sdbbp
88
89.section ".vector_0x180","ax"
90    .globl general_exception
91general_exception:
92
93/* EL Change: Branch to ThreadX error handling.  */
94
95    la       k0, _tx_error_exceptions
96    jalr     k1, k0
97    nop
98
99/* EL Change end.  */
100
101
102    sdbbp
103
104.section ".vector_0x200","ax"
105    .globl iv1_interrupt
106iv1_interrupt:
107
108/* EL Change: Branch to ThreadX error handling.  */
109
110    la      k0, _tx_exception_handler
111    jalr    k1, k0
112    nop
113
114/* Disable previous exception handler, since ThreadX is taking care of all exceptions now.  */
115#if 0
116    li      k0, MALTA_DISP_ADDR			// Malta ASCII character display.
117    mfc0    k1, C0_EBASE				// Get cp0 EBase
118    ext     k1, k1, 0, 10				// Extract CPUNum
119    sll     k1, k1, 3					// Build offset for display char.
120    addiu   k1, 8
121    addu    k0, k0, k1					// Pointer to a single display character.
122    li      k1, 'H'						// Indicate that this vpe is in the handler.
123    sw      k1, 0(k0)					// Write ASCII char to Malta ASCII display.
124
125    li      k0, (GIC_SH_WEDGE | GIC_BASE_ADDR)
126    mfc0    k1, C0_EBASE                // Get cp0 EBase
127    ext     k1, k1, 0, 10				// Extract CPUNum
128    addiu   k1, 0x20					// Offset to base of IPI interrupts.
129    sw      k1, 0(k0)					// Clear this IPI.
130
131    la      k0, start_test
132    mfc0    k1, C0_EBASE				// Get cp0 EBase
133    ext     k1, k1, 0, 10				// Extract CPUNum
134    sll     k1, k1, 2
135    addu    k0, k0, k1					// index into CMP global "C" variable start_test
136
137    lw      k1, 0(k0)	# Pickup start_test value
138    addiu   k1, k1, 1	# Increment start_test value
139
140    sw      k1, 0(k0)					// Release "cpu"/vpe to execute "C" test code.
141    eret
142    nop
143#endif
144
145/* EL Change end.  */
146
147
148.section ".vector_0x280","ax"
149    .globl xtlb_refill
150xtlb_refill:
151    sdbbp
152
153.section ".vector_0x300","ax"
154    .globl cache_error
155cache_error:
156    sdbbp
157
158
159/**************************************************************************************
160**************************************************************************************/
161// RAMHACK: Entry point is _start (execution is started here in (uncached) kseg0.
162
163.section ".text","ax"
164               /* (with vaddr[12..0] = 0 for alignment with GCR_CO_RESET_BASE). */
165
166	.globl _start
167_start:
168    b       verify_isa          # Note: Real systems might want to save/dump full context.
169    nop
170    .globl verify_isa
171verify_isa: // Verify device ISA meets code requirements (MIPS32R2 or later.)
172    mfc0    a0, C0_CONFIG				// Read CP0 Config
173    srl     a0, 10					// Shift [AT AR] into LSBs.
174    andi    a3, a0, 0x18				// Inspect CP0 Config[AT]
175    beqz    a3, is_mips32				// Branch if executing on MIPS32 ISA.
176    andi    a3, a0, 0x07				// Inspect CP0 Config[AR]
177    sdbbp 								// Failed assertion: MIPS32R2.
178    .globl is_mips32
179is_mips32:
180    bnez    a3, init_common_resources	// Continue if ISA is MIPS32R2 or later.
181    nop
182    sdbbp								// Failed assertion MIPS32R2.
183/**************************************************************************************
184 What is initialized on execution depends on the core/vpe executing it.
185 (A non-MT device is treated as tc0/vpe0, non-CMP device is treated as core0.)
186**************************************************************************************/
187    .globl init_common_resources
188init_common_resources:  // initializes resources for virtual or physical "cpu".
189    la a2,init_gpr		// Fill register file with set  value.
190    jalr a2
191    nop
192    la a2,	set_gpr_boot_values  // Fill register file boot info.
193    jalr a2
194    nop
195
196    // Clear Malta Display if processor 0
197    bnez    r9_vpe_num, clear_done
198    lui v0, 0xbf00
199    li v1, 0x20
200    sw v1, 1048(v0)
201    sw v1, 1056(v0)
202    sw v1, 1064(v0)
203    sw v1, 1072(v0)
204    sw v1, 1080(v0)
205    sw v1, 1088(v0)
206    sw v1, 1096(v0)
207    sw v1, 1104(v0)
208    .globl clear_done
209clear_done:
210
211    la a2,     init_cp0    // Init CP0 Status, Count, Compare, Watch*, and Cause.
212    jalr a2
213    nop
214
215 	// Determine if we have a TLB
216	mfc0    v1, C0_CONFIG			// read C0_Config
217	ext	    v1, v1, 7, 3			// extract MT field
218	li	    a3, 0x1					// load a 1 to check against
219	bne	    v1, a3, done_tlb		// no tlb?
220	nop
221
222	// determined if this is VPE 0 so skip shared TLB check
223    beqz    r9_vpe_num, do_tlb		// VPE 0?
224    nop
225
226    // Must be VPE1 determined if TLB is shared if it is skip init_tlb (already done by VPE0)
227    mfc0    a0, $0, 1				// MVPControl
228    ext     a0, a0, 3, 1    		// MVPControl[STLB]
229    beq		a0, zero, done_tlb		// TLB shared?
230	nop
231
232do_tlb:
233    la a2,     init_tlb    			// Generate unique EntryHi contents per entry pair.
234    jalr a2
235    nop
236    .globl done_tlb
237done_tlb:
238    la a2,     init_gic    // Configure the global interrupt controller.
239    jalr a2
240    nop
241
242    bnez    r9_vpe_num, init_done // If we are not a vpe0 then we are done.
243    nop
244    .globl init_core_resources
245init_core_resources:    // We are a vpe0.
246
247    la a2,     disable_L23   // Disable L2/L3 caches
248    jalr a2
249    nop
250
251    la a2,     init_icache // Initialize the L1 instruction cache. (Executing using I$ on return.)
252    jalr a2
253    nop
254
255// The changing of Kernel mode cacheability must be done from KSEG1
256// Since the code is executing from KSEG0 It needs to do a jump to KSEG1 change K0 and jump back to KSEG0
257	la a2,		change_k0_cca
258	li      	a1, 0xf
259	ins     	a2, a1, 29, 1 // changed to KSEG1 address by setting bit 29
260    jalr a2
261    nop
262
263// L1 Cache icache is now enabled
264
265    la a2,     init_dcache // Initialize the L1 data cache
266    jalr a2
267    nop
268
269    la a2,     init_itc    // Initialize Inter-Thread Communications unit
270    jalr a2
271    nop
272
273    bnez    r8_core_num, init_sys_resources_done // Only core0/vpe0 needs to init systems resources.
274    nop
275
276    .globl init_sys_resources
277init_sys_resources:     // We are core0 vpe0.
278    la a2,     init_cpc    // Initialize the CPS CPC (Cluster Power Controller.)
279    jalr a2
280    nop
281
282    la a2,     init_cm     // Initialize the CPS CM (Coherence Manager.)
283    jalr a2
284    nop
285
286#ifdef DENALI
287    la a2,     init_CoreFPGA6_mem     // Initialize the ROC-it2 MC (Memory Controller.)
288    jalr a2
289    nop
290#endif
291
292    la a2,     copy_c2_ram // Copy "C" code and data to RAM and zero bss (uncached.)
293    jalr a2
294    nop
295
296    la a2,     init_L23   // Initialize the unified L2 and L3 caches
297    jalr a2
298    nop
299
300    /* EL Change.  Ensure that the VPE release flag is cleared ahead of BSS clear.  */
301
302    la      $8, _tx_thread_smp_release_cores_flag   # Build address of release flag
303    sw      $0, 0($8)                               # Clear the flag explicity to make other VPEs don't see it before everything is initialized
304
305    /* EL end Change.  */
306
307
308    la a2,     release_mp  // Release other cores to execute this boot code.
309    jalr a2
310    nop
311
312init_sys_resources_done:		// All Cores (VPE0)
313
314    la a2,     join_domain // Join the Coherence  domain. (OK to use D$ on return.)
315    jalr a2
316    nop
317
318    la a2,     init_vpe1   // Set up MT ASE vpe1 to execute this boot code also.
319    jalr a2
320    nop
321
322    /* EL Change.  Add optional user-specified VPE wakeup setup code call.  */
323
324#ifdef TX_THREAD_SMP_WAKEUP_LOGIC
325
326    /* Call optional user-specific code for VPE initialization.  */
327
328    subu    $29, 8                              # Allocate space to save ra
329    sw      $31, 4($29)                         # Save R31
330    la      $9, TX_THREAD_SMP_WAKEUP_LOGIC_SETUP
331    jalr    $9                                  # User-specified VPE setup logic
332    nop                                         #
333    lw      $31, 4($29)                         # Restore ra
334    addu    $29, 8                              # De-allocate stack storage
335#endif
336
337    /* EL Change End.  */
338
339    .globl init_done
340init_done:
341
342    /* EL Change.  Removed call to demo code and instead setup for ThreadX execution.   */
343
344    /* For all VPEs, store the cpu number into the UserLocal field so it is easy to pickup.  */
345
346    mtc0    r23_cpu_num, $4,2                   # Save the logical VPE in UserLocal so we don't have calculate it over and over!  */
347
348    /* Save the stack pointer in the array indexed by cpu number.  */
349
350    la      $8, _tx_thread_system_stack_ptr     # Build address of base of system stack array
351    sll     $9, r23_cpu_num, 2                  # Build offset into array
352    addu    $8, $8, $9                          # Build address of array entry
353    sw      $29, 0($8)                          # Store system stack for each VPE
354
355    /* Setup status register in preparation for entering ThreadX.  */
356
357    mfc0    $8, $12                             # Pickup SR
358    li      $9, 0xFFFFFFF8                      # Build mask to clear error, exception bits
359    and     $8, $8, $9                          # Clear bits
360    ori     $8, $8, 1                           # Disable all interrupts
361    mtc0    $8, $12                             # Setup the status register
362    ehb                                         #
363
364    /* Check for Core 0, VPE 0 for processing ThreadX initialization.  All other VPEs will wait until the first
365       VPE has completed initialization before running.  */
366
367    bne     r23_cpu_num, $0, _additional_vpe    # If non-zero, an additional vpe is present
368    nop                                         #
369
370    /* Core 0, VPE 0 processing.  */
371
372    /* Save some information in globals.  */
373
374    la      $8, _tx_thread_smp_detected_cores   # Build address of total number of cores detected
375    addiu   $9, r19_more_cores, 1               # Calculate the total cores
376    sw      $9, 0($8)                           # Save in global variable
377
378    la      $8, _tx_thread_smp_detected_vpes_per_core # Build address of VPEs per core detected
379    addiu   $9, r20_more_vpes, 1                # Caculate the total vpes per core
380    sw      $9, 0($8)                           # Save in global variable
381
382
383    /* Simply branch to main to finish initializing ThreadX SMP.  */
384
385    bal     main                                # Branch to main
386    nop                                         #
387
388    /* If return, branch to all_done code.  */
389
390    b      all_done
391    nop
392
393
394_additional_vpe:
395
396
397    /* Additional VPE, transfer control to ThreadX.  */
398
399    b       _tx_thread_smp_initialize_wait          # Enter ThreadX for additional VPEs
400    nop
401
402    .globl all_done
403all_done:
404    b       all_done
405
406/* Comment out the previous "init_done" code since it is replaced with ThreadX-specfic code.  */
407#if 0
408
409    mtc0    r23_cpu_num, $4,2              # Setup UserLocal
410
411    // Prepare for eret to main (sp and gp set up per vpe in init_gpr).
412    la      ra, all_done	// If main return then go to all_done:.
413    la      a1, main
414    mtc0    a1, C0_ERRPC 			// ErrorEPC
415
416    // initialize global variable num_cores.
417//    la      a1, num_cores
418    // RAMHACK: caches are coherent use cached reference to "C" static "num_cores".
419    // ins     a1, r1_all_ones, 29, 1 // Uncached kseg1
420//    add     a0, r19_more_cores, 1
421//    sw      a0, 0(a1)
422
423    // Prepare arguments for main()
424    move    a0, r23_cpu_num			// main(arg0) is the "cpu" number (cp0 EBase[CPUNUM].)
425    move    a1, r8_core_num			// main(arg1) is the core number.
426    move    a2, r9_vpe_num			// main(arg2) is the vpe number.
427    addiu   a3, r20_more_vpes, 1	// main(arg3) is the number of vpe on this core.
428
429    // RAMHACK: Main appears to take first arg from r16 (s0) in GHS build?
430    move    s0, r23_cpu_num			// main(arg0) is the "cpu" number (cp0 EBase[CPUNUM].)
431
432    eret    // Exit reset exception handler for this vpe and start execution of main().
433
434
435/**************************************************************************************
436**************************************************************************************/
437    .globl all_done
438all_done:
439
440    // Main returns the "cpu" number
441    // All cpu spin on atomic potato++
442
443//    la a1, potato
444
445try_again:
446    ll a0, 0(a1)
447    addiu a0, a0, 1
448    sc a0, 0(a1)      // Attempt atomic potato++
449
450    beq a0, $0, try_again       // Fail, retry.
451    nop
452
453    b try_again                           // Success, do again.
454    nop
455
456    b       all_done
457    nop
458#endif
459    /* EL Change end.  */
460
461
462