1/***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12/**************************************************************************/
13/**************************************************************************/
14/**                                                                       */
15/** ThreadX Component                                                     */
16/**                                                                       */
17/**   Initialize                                                          */
18/**                                                                       */
19/**************************************************************************/
20/**************************************************************************/
21
22
23#define GIC_SH_WEDGE    0xbbdc0280          /* For Inter-processor interrupts on MALTA board.  */
24
25    INITIAL_SR          =   0xFF00          # All IM bits set
26    SW_INTERRUPT_0      =   0x0100          # Software interrupt 0
27    SW_INTERRUPT_1      =   0x0200          # Software interrupt 1
28    INTERRUPT_0         =   0x0400          # Interrupt 0
29    INTERRUPT_1         =   0x0800          # Interrupt 1
30    INTERRUPT_2         =   0x1000          # Interrupt 2
31    INTERRUPT_3         =   0x2000          # Interrupt 3
32    INTERRUPT_4         =   0x4000          # Interrupt 4
33    INTERRUPT_5         =   0x8000          # Interrupt 5
34    EXCEPTION_VECTOR    =   0x00000180      # General exception vector
35    TEN_MS_COUNT        =   120000          # 10 ms clock rate
36
37    .text
38    .set        noreorder
39/**************************************************************************/
40/*                                                                        */
41/*  FUNCTION                                               RELEASE        */
42/*                                                                        */
43/*    _tx_initialize_low_level                      MIPS32_interAptiv/GNU */
44/*                                                           6.2.1        */
45/*  AUTHOR                                                                */
46/*                                                                        */
47/*    Scott Larson, Microsoft Corporation                                 */
48/*                                                                        */
49/*  DESCRIPTION                                                           */
50/*                                                                        */
51/*    This function is responsible for any low-level processor            */
52/*    initialization, including setting up interrupt vectors, setting     */
53/*    up a periodic timer interrupt source, saving the system stack       */
54/*    pointer for use in ISR processing later, and finding the first      */
55/*    available RAM memory address for tx_application_define.             */
56/*                                                                        */
57/*  INPUT                                                                 */
58/*                                                                        */
59/*    None                                                                */
60/*                                                                        */
61/*  OUTPUT                                                                */
62/*                                                                        */
63/*    None                                                                */
64/*                                                                        */
65/*  CALLS                                                                 */
66/*                                                                        */
67/*    None                                                                */
68/*                                                                        */
69/*  CALLED BY                                                             */
70/*                                                                        */
71/*    _tx_initialize_kernel_enter           ThreadX entry function        */
72/*                                                                        */
73/*  RELEASE HISTORY                                                       */
74/*                                                                        */
75/*    DATE              NAME                      DESCRIPTION             */
76/*                                                                        */
77/*  03-08-2023      Scott Larson            Initial Version 6.2.1         */
78/*                                                                        */
79/**************************************************************************/
80/* VOID   _tx_initialize_low_level(VOID)
81{  */
82    .globl  _tx_initialize_low_level
83_tx_initialize_low_level:
84
85    di                                          # Ensure interrupts are disabled
86    ehb                                         #
87    mfc0    $8, $12                             # Pickup current SR
88    ori     $8, $8, INITIAL_SR                  # Build initial SR
89    mtc0    $8, $12                             # Setup SR
90
91    /* Save the system stack pointer.  */
92    /* _tx_thread_system_stack_ptr = (VOID_PTR) (SP);  */
93
94    la      $8, _tx_thread_system_stack_ptr     # Pickup address of system
95                                        /*      #   stack pointer  */
96    sw      $29, ($8)                           # Save system stack pointer
97
98
99    /* Save the first available memory address.  */
100    /* _tx_initialize_unused_memory =  (VOID_PTR) _free_memory;  */
101
102    la      $9, _free_memory                    # Pickup first free address
103    la      $10, _tx_initialize_unused_memory   # Pickup address of unused
104                                        /*      #   memory  */
105    sw      $9, ($10)                           # Save unused memory address
106
107
108    /*  Set up the counter/compare registers to generate a periodic interrupt.  */
109
110    mtc0    $0, $9                              # Initialize CP0 timer count register to zero
111    ehb                                         #
112    li      $9,TEN_MS_COUNT                     # Default value
113    mtc0    $9, $11                             # Set timer compare register
114    ehb                                         #
115
116
117    /* Done, return to caller.  */
118
119    j       $31                                 # Return to caller
120    nop                                         # Delay slot
121/* }  */
122
123
124    /* Define the interrupt/exception handler trampoline code.  This needs to
125       be copied to address 0x80000180 cached or 0xA0000180 non-cache.  */
126
127    .globl  _tx_exception_trampoline
128_tx_exception_trampoline:
129    la      $26,_tx_exception_handler           # Pickup exception handler address
130    j       $26                                 # Jump to exception handler
131    nop                                         # Delay slot
132    nop                                         # Fill with nops....
133    nop                                         #
134    nop                                         #
135    nop                                         #
136    nop                                         #
137_tx_exception_trampoline_end:
138
139
140
141    /* Define the actual interrupt/exception handler.  Since this routine must handle
142       multiple exceptions, the context save/restore functions are called automatically.
143       Application specific ISR processing added to this routine must be inserted into
144       the proper place and use registers in accordance with the MIPS compiler, i.e.
145       $16-$23 (s0-s7) and $30 (s8) must be saved if they are used.  C functions called
146       from this area will automatically save/restore these registers if they are used.  */
147
148    .globl  _tx_exception_handler
149_tx_exception_handler:
150    mfc0    $26, $13                            # Pickup the cause register
151    ehb                                         #
152    andi    $26, $26, 0x3C                      # Isolate the exception code
153    bne     $26, $0, _tx_error_exceptions       # If non-zero, an error exception is present
154    nop                                         # Delay slot
155
156    la      $27, _tx_thread_smp_system_error    # Build address to system error flag
157    lw      $27, ($27)                          # Pickup system error flag
158_system_error_loop:
159    bne     $27, $0, _system_error_loop         # If error, just sit here!
160    nop
161
162    /* Otherwise, an interrupt exception is present.  Call context save before we
163       process normal interrupts.  */
164
165    la      $26, _tx_thread_context_save        # Pickup address of context save function
166    jalr    $27,$26                             # Call context save
167    nop                                         # Delay slot
168
169    /* Perform interrupt processing here!  When context save returns, interrupts are
170       disabled and all compiler scratch registers are available.  Also, s0 is saved and
171       is used in this function to hold the contents of the CAUSE register.  */
172
173    mfc0    $16, $13                            # Pickup the cause register
174
175
176    /* Interrupts may be re-enabled after this point.  */
177
178    /* Check for Interrupt 0.  */
179
180    andi    $8, $16, INTERRUPT_0                # Isolate interrupt 0 flag
181    beqz    $8, _tx_not_interrupt_0             # If not set, skip interrupt 0 processing
182    nop                                         # Delay slot
183
184    /* Interrupt 0 processing goes here!  */
185
186#ifdef TX_ENABLE_EVENT_TRACE
187    li      $4,1                                # Build interrupt type
188    la      $9, _tx_trace_isr_enter_insert      # Build interrupt enter logging address
189    jal     $9                                  # Call interrupt enter event logging
190    nop                                         #
191#endif
192
193    /* Clear inter-processor interrupt (and increment counter).  */
194
195    mfc0    $8, $4,2                            # Pickup UserLocal (VPE number)
196    la      $9, _tx_thread_smp_inter_core_interrupts # Address of inter-processor interrupt
197    sll     $8, $8, 2                           # Build offset to proper counter index
198    addu    $9, $9, $8                          # Build address of this VPE's counter
199    lw      $8, 0($9)                           # Pickup current value
200    addiu   $8, $8, 1                           # Increment current value
201    sw      $8, 0($9)                           # Store value back
202
203    li      $8, GIC_SH_WEDGE                    #
204    mfc0    $9, $15, 1                          # Get cp0 EBase
205    ext     $9, $9, 0, 10                       # Extract CPUNum
206    addiu   $9, 0x20                            # Offset to base of IPI interrupts.
207    sw      $9, 0($8)                           # Clear this IPI.
208
209#ifdef TX_ENABLE_EVENT_TRACE
210    li      $4,1                                # Build interrupt type
211    la      $9, _tx_trace_isr_exit_insert       # Build interrupt exit logging address
212    jal     $9                                  # Call interrupt exit event logging
213    nop                                         #
214#endif
215
216_tx_not_interrupt_0:
217
218    /* Check for Interrupt 1.  */
219
220    andi    $8, $16, INTERRUPT_1                # Isolate interrupt 1 flag
221    beqz    $8, _tx_not_interrupt_1             # If not set, skip interrupt 1 processing
222    nop                                         # Delay slot
223
224    /* Interrupt 1 processing goes here!  */
225
226_tx_not_interrupt_1:
227
228    /* Check for Interrupt 2.  */
229
230    andi    $8, $16, INTERRUPT_2                # Isolate interrupt 2 flag
231    beqz    $8, _tx_not_interrupt_2             # If not set, skip interrupt 2 processing
232    nop                                         # Delay slot
233
234    /* Interrupt 2 processing goes here!  */
235
236_tx_not_interrupt_2:
237
238    /* Check for Interrupt 3.  */
239
240    andi    $8, $16, INTERRUPT_3                # Isolate interrupt 3 flag
241    beqz    $8, _tx_not_interrupt_3             # If not set, skip interrupt 3 processing
242    nop                                         # Delay slot
243
244    /* Interrupt 3 processing goes here!  */
245
246_tx_not_interrupt_3:
247
248    /* Check for Interrupt 4.  */
249
250    andi    $8, $16, INTERRUPT_4                # Isolate interrupt 4 flag
251    beqz    $8, _tx_not_interrupt_4             # If not set, skip interrupt 4 processing
252    nop                                         # Delay slot
253
254    /* Interrupt 4 processing goes here!  */
255
256_tx_not_interrupt_4:
257
258    /* Check for Interrupt 5.  */
259
260    andi    $8, $16, INTERRUPT_5                # Isolate interrupt 5 flag
261    beqz    $8, _tx_not_interrupt_5             # If not set, skip interrupt 5 processing
262    nop                                         # Delay slot
263
264    /* Interrupt 5 processing goes here!  */
265
266
267    /* Interrupt 5 is the count/compare timer interrupt.  */
268
269#ifdef TX_ENABLE_EVENT_TRACE
270    li      $4,0                                # Build interrupt type
271    la      $9, _tx_trace_isr_enter_insert      # Build interrupt enter logging address
272    jal     $9                                  # Call interrupt enter event logging
273    nop                                         #
274#endif
275
276
277    /* Interrupt 5 is the count/compare timer interrupt.  */
278
279    mtc0    $0, $9                              # Initialize CP0 count register to zero
280    ehb                                         #
281    li      $9, TEN_MS_COUNT                    # 10 ms @ 66 MHz
282    mtc0    $9, $11                             # Set compare register, reset count reg.
283    ehb                                         #
284
285    /* Call the ThreadX timer routine.  */
286
287    la      $8, _tx_timer_interrupt             # Build timer interrupt address
288    jal     $8                                  # Call timer interrupt handler
289    nop                                         #
290
291#ifdef TX_ENABLE_EVENT_TRACE
292    li      $4,0                                # Build interrupt type
293    la      $9, _tx_trace_isr_exit_insert       # Build interrupt exit logging address
294    jal     $9                                  # Call interrupt exit event logging
295    nop                                         #
296#endif
297
298_tx_not_interrupt_5:
299
300    /* Check for Software Interrupt 0.  */
301
302    andi    $8, $16, SW_INTERRUPT_0             # Isolate software interrupt 0 flag
303    beqz    $8, _tx_not_interrupt_sw_0          # If not set, skip sw interrupt 0 processing
304    nop                                         # Delay slot
305
306    /* Software interrupt 0 processing goes here!  */
307
308_tx_not_interrupt_sw_0:
309
310    /* Check for Software Interrupt 1.  */
311
312    andi    $8, $16, SW_INTERRUPT_1             # Isolate software interrupt 1 flag
313    beqz    $8, _tx_not_interrupt_sw_1          # If not set, skip sw interrupt 1 processing
314    nop                                         # Delay slot
315
316    /* Software interrupt 1 processing goes here!  */
317
318_tx_not_interrupt_sw_1:
319
320    la      $8, _tx_thread_context_restore      # Pickup address of context restore function
321    j       $8                                  # Jump to context restore - does not return!
322    nop                                         # Delay slot
323
324    /* Error Exception processing goes here!  */
325
326    .globl  _tx_error_exceptions
327_tx_error_exceptions:
328    b       _tx_error_exceptions                # Default error exception processing
329    nop                                         # Delay slot
330
331
332    /* Reference the build options and the version ID to ensure they are part of the image.  */
333    la      $8, _tx_build_options
334    la      $9, _tx_version_id
335