File : s-bbbosu-8349e.adb
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS --
4 -- --
5 -- S Y S T E M . B B . B O A R D _ S U P P O R T --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1999-2002 Universidad Politecnica de Madrid --
10 -- Copyright (C) 2003-2005 The European Space Agency --
11 -- Copyright (C) 2003-2016, AdaCore --
12 -- --
13 -- GNAT is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 3, or (at your option) any later ver- --
16 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. --
19 -- --
20 -- --
21 -- --
22 -- --
23 -- --
24 -- You should have received a copy of the GNU General Public License and --
25 -- a copy of the GCC Runtime Library Exception along with this program; --
26 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
27 -- <http://www.gnu.org/licenses/>. --
28 -- --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
31 -- --
32 -- The port of GNARL to bare board targets was initially developed by the --
33 -- Real-Time Systems Group at the Technical University of Madrid. --
34 -- --
35 ------------------------------------------------------------------------------
36
37 with Interfaces; use Interfaces;
38
39 with System.BB.Board_Parameters; use System.BB.Board_Parameters;
40 with System.BB.Parameters;
41 with System.BB.Protection;
42
43 package body System.BB.Board_Support is
44
45 -- Mapping between priorities and interrupt source.
46
47 -- HPI is not used; MIXA, MIXB, SYSA, SYSD groups are grouped.
48
49 -- All external and internal interrupts are routed to /int.
50
51 -- Interrupt ipp_ind_ext_int[0] is configured as an external maskable
52 -- interrupt (See initialization of SEMSR).
53
54 -- MCP interrupts are not handled by the runtime.
55
56 -- External IRQ interrupts are configured as level sensitive.
57
58 -- Here is the table between IPIC priority and Interrupt source. This is
59 -- extracted from Table 8-28, using the fact that only grouped scheme are
60 -- used. Interrupt_ID is the interrupt number for the IPIC, which according
61 -- to Table 8-6 is also the interrupt vector, which by definition is also
62 -- the Ada Interrupt_ID.
63
64 -- Priority Interrupt source Interrupt_ID
65 -- 1 (HPI)
66 -- 2 MIXA0 ipi_int_internal[32] 64
67 -- 3 MIXA1 ipi_int_internal[33] 65
68 -- 4 MIXA2 ipi_int_internal[34] 66
69 -- 5 MIXA3 ipi_int_internal[35] 67
70 -- 6 (MIXB0 - Spread)
71 -- 7-10 (Reserved)
72 -- 11 (MIXA1 - Spread)
73 -- 12-15 (Reserved)
74 -- 16 MIXB0 RTC ALR 68
75 -- 17 MIXB1 MU 69
76 -- 18 MIXB2 SBA 70
77 -- 19 MIXB3 DMA 71
78 -- 20 (MIXB1 - Spread)
79 -- 21 SYSA0 TSEC1 Tx 32
80 -- 22 SYSA1 TSEC1 Rx 33
81 -- 23 SYSA2 TSEC1 Err 34
82 -- 24 SYSA3 TSEC2 Tx 35
83 -- 25 (MIXA2 - Spread)
84 -- 26 SYSA4 TSEC2 Rx 36
85 -- 27 SYSA5 TSEC2 Err 37
86 -- 28 SYSA6 USB DR 38
87 -- 29 SYSA7 USB MPH 39
88 -- 30 MIXA4 ipp_ind_ext_int[0] 48
89 -- 31 MIXA5 ipp_ind_ext_int[1] 17
90 -- 32 MIXA6 ipp_ind_ext_int[2] 18
91 -- 33 MIXA7 ipp_ind_ext_int[3] 19
92 -- 34 (MIXB2 - Spread)
93 -- 35-38 (Reserved)
94 -- 39 (MIXA3 - Spread)
95 -- 40-43 (Reserved)
96 -- 44 MIXB4 IRQ4 20
97 -- 45 MIXB5 IRQ5 21
98 -- 46 MIXB6 IRQ6 22
99 -- 47 MIXB7 IRQ7 23
100 -- 48 (MIXB3 - Spread)
101 -- 49 SYSD0 UART1 9
102 -- 50 SYSD1 UART2 10
103 -- 51 SYSD2 SEC 11
104 -- 52 (SYSD3 - Reserved)
105 -- 53 (MIXA4 - Spread)
106 -- 54 (SYSD4 - Reserved)
107 -- 55 SYSD5 I2C1 14
108 -- 56 SYSD6 I2C2 15
109 -- 57 SYSD7 SPI 16
110 -- 58 (MIXB4 - Spread)
111 -- 59 GTM4 72
112 -- 60 (Reserved)
113 -- 61 (SYSA0 - Spread)
114 -- 62 GTM8 73
115 -- 63 (Reserved)
116 -- 64 (SYSD0 - Spread)
117 -- 65 (Reserved)
118 -- 66 GPIO1 74
119 -- 67 (MIXA5 - Spread)
120 -- 68 GPIO2 75
121 -- 69 (Reserved)
122 -- 70 (SYSA1 - Spread)
123 -- 71 DDR 76
124 -- 72 (Reserved)
125 -- 73 (SYSD1 - Spread)
126 -- 74 (Reserved)
127 -- 75 LBC 77
128 -- 76 (MIXB5 - Spread)
129 -- 77 GTM2 78
130 -- 78 (Reserved)
131 -- 79 (SYSA2 - Spread)
132 -- 80 GTM6 79
133 -- 81 (Reserved)
134 -- 82 (SYSD2 - Spread)
135 -- 83 (Reserved)
136 -- 84 PMC 80
137 -- 85 (MIXA6 - Spread)
138 -- 86 (Reserved)
139 -- 87 (Reserved)
140 -- 88 (SYSA3 - Spread)
141 -- 89 (Reserved)
142 -- 90 (Reserved)
143 -- 91 (SYSD3 (Spread))
144 -- 92 (Reserved)
145 -- 93 (Reserved)
146 -- 94 (MIXB6 (Spread))
147 -- 95 GTM3 84
148 -- 96 (Reserved)
149 -- 97 (SYSA4 (Spread))
150 -- 98 GTM7 85
151 -- 99 (Reserved)
152 -- 100 (SYSD4 - Spread)
153 -- 101 (Reserved)
154 -- 102 (Reserved)
155 -- 103 (MIXA7 - Spread)
156 -- 104 (Reserved)
157 -- 105 (Reserved)
158 -- 106 (SYSA5 - Spread)
159 -- 107 (Reserved)
160 -- 108 (Reserved)
161 -- 109 (SYSD5 - Spread)
162 -- 110 (Reserved)
163 -- 111 (Reserved)
164 -- 112 (MIXB7 - Spread)
165 -- 113 GTM1 90
166 -- 114 (Reserved)
167 -- 115 (SYSA6 - Spread)
168 -- 116 GTM5 91
169 -- 117 (Reserved)
170 -- 118 (SYSD6 - Spread)
171 -- 119 (Reserved)
172 -- 120 (Reserved)
173 -- 121 (Reserved)
174 -- 122 (Reserved)
175 -- 123 (SYSA7 - Spread)
176 -- 124 (Reserved)
177 -- 125 (Reserved)
178 -- 126 (SYSD7 - Spread)
179 -- 127 (Reserved)
180 -- 128 (Reserved)
181
182 procedure Define_Interrupt_Priority
183 (Interrupt : System.BB.Interrupts.Interrupt_ID;
184 Priority : Interrupt_Priority;
185 Mask_Bit : Natural);
186 pragma Export (Ada, Define_Interrupt_Priority,
187 "__gnat_define_interrupt_priority");
188 -- This is a user service to define the priority of interrupts and its
189 -- corresponding mask bit. It can be called at most once per interrupt.
190
191 use System.BB.Interrupts;
192
193 subtype Mask_Bit_Number is Natural range 0 .. 95;
194 -- Bit number in the SIMSR_H/SIMSR_L/SEMSR registers. Bit numbers 0 to 31
195 -- means bit 0 (MSB) to 31 (LSB) of SIMSR_H, bit numbers 32 to 63 means
196 -- bit 0 (MSB) to 31 (LSB) of SIMSR_L, and bit numbers 64 to 95 means
197 -- bit 0 (MSB) to 31 (LSB) of SEMSR.
198
199 type Interrupt_Priorities_Type is
200 array (System.BB.Interrupts.Interrupt_ID
201 range 0 .. System.BB.Parameters.Number_Of_Interrupt_ID - 1)
202 of Any_Priority;
203 -- Type for the interrupt to priority map
204
205 Interrupt_Priorities : Interrupt_Priorities_Type := (others => 0);
206 -- Map that associate an interrupt id with its priority
207
208 type Priority_Mask is record
209 SIMSR_H : Unsigned_32;
210 -- SIMSR_H value
211
212 SIMSR_L : Unsigned_32;
213 -- SIMSR_L value
214
215 SEMSR : Unsigned_32;
216 -- SEMSR value
217 end record;
218
219 type Priority_Mask_Map_Type is
220 array (Priority'Last .. Interrupt_Priority'Last) of Priority_Mask;
221 -- Interrupt mask values for each interrupt priority and for non-interrupt
222 -- priorities (Priority'Last is used for that case).
223
224 Priority_Masks : Priority_Mask_Map_Type := (others => (0, 0, 0));
225 -- Mask for eash priority. Initially all interrupts are masked
226
227 SEMSR : Unsigned_32;
228 for SEMSR'Address use IMMRBAR + 16#0738#;
229 pragma Volatile (SEMSR);
230 pragma Import (Ada, SEMSR);
231 -- System External interrupt Mask Register
232
233 SIMSR_H : Unsigned_32;
234 for SIMSR_H'Address use IMMRBAR + 16#0720#;
235 pragma Volatile (SIMSR_H);
236 pragma Import (Ada, SIMSR_H);
237 -- System Internal interrupt Mask Register (High)
238
239 SIMSR_L : Unsigned_32;
240 for SIMSR_L'Address use IMMRBAR + 16#0724#;
241 pragma Volatile (SIMSR_L);
242 pragma Import (Ada, SIMSR_L);
243 -- System Internal interrupt Mask Register (Low)
244
245 ----------------------
246 -- Initialize_Board --
247 ----------------------
248
249 procedure Initialize_Board is
250 SICFR : Unsigned_32;
251 for SICFR'Address use IMMRBAR + 16#0700#;
252 pragma Volatile (SICFR);
253 pragma Import (Ada, SICFR);
254
255 SIPRR_A : Unsigned_32;
256 for SIPRR_A'Address use IMMRBAR + 16#0710#;
257 pragma Volatile (SIPRR_A);
258 pragma Import (Ada, SIPRR_A);
259
260 SIPRR_D : Unsigned_32;
261 for SIPRR_D'Address use IMMRBAR + 16#071C#;
262 pragma Volatile (SIPRR_D);
263 pragma Import (Ada, SIPRR_D);
264
265 SICNR : Unsigned_32;
266 for SICNR'Address use IMMRBAR + 16#0728#;
267 pragma Volatile (SICNR);
268 pragma Import (Ada, SICNR);
269
270 SMPRR_A : Unsigned_32;
271 for SMPRR_A'Address use IMMRBAR + 16#0730#;
272 pragma Volatile (SMPRR_A);
273 pragma Import (Ada, SMPRR_A);
274
275 SMPRR_B : Unsigned_32;
276 for SMPRR_B'Address use IMMRBAR + 16#0734#;
277 pragma Volatile (SMPRR_B);
278 pragma Import (Ada, SMPRR_B);
279
280 SECNR : Unsigned_32;
281 for SECNR'Address use IMMRBAR + 16#073C#;
282 pragma Volatile (SECNR);
283 pragma Import (Ada, SECNR);
284
285 begin
286 -- Initialize IPIC
287
288 -- At that point, all interrupts should be masked in the MSR
289
290 -- H M M I I H
291 -- P P P P P P
292 -- I S S S S E
293 -- B A D A T
294
295 SICFR := 2#0_0000000_0_0_0_0_0_00_0_000000_00_00000000#;
296
297 -- SYSA 0P 1P 2P 3P -- 4P 5P 6P 7P --
298
299 SIPRR_A := 2#000_001_010_011_0000_100_101_110_111_0000#;
300
301 -- SYSD 0P 1P 2P 3P -- 4P 5P 6P 7P --
302
303 SIPRR_D := 2#000_001_010_011_0000_100_101_110_111_0000#;
304
305 -- SYSD0T 1T SYSA0T 1T
306
307 SICNR := 2#00_00_000000000000_00000000_00_00_0000#;
308
309 -- SMPRR_A 0P 1P 2P 3P -- 4P 5P 6P 7P --
310
311 SMPRR_A := 2#000_001_010_011_0000_100_101_110_111_0000#;
312
313 -- SMPRR_B 0P 1P 2P 3P -- 4P 5P 6P 7P --
314
315 SMPRR_B := 2#000_001_010_011_0000_100_101_110_111_0000#;
316
317 -- MIXB0T 1T MIXA0T 1T EDI
318
319 SECNR := 2#00_00_0000_00_00_0000_00000000_00000000#;
320
321 -- Mask all interrupts, and steer ipp_ind_ext_int[0] as external
322 -- interrupt request.
323
324 SIMSR_H := 2#00000000_00000000_00000000_000_00_000#;
325 SIMSR_L := 2#00000000_00000000_0_000_00_0000_00_0000#;
326 SEMSR := 2#00000000_00000000_0_000000000000000#;
327 end Initialize_Board;
328
329 ---------------------------
330 -- Clear_Alarm_Interrupt --
331 ---------------------------
332
333 procedure Clear_Alarm_Interrupt is
334 begin
335 -- Nothing to do on standard powerpc
336
337 null;
338 end Clear_Alarm_Interrupt;
339
340 ---------------------------
341 -- Get_Interrupt_Request --
342 ---------------------------
343
344 function Get_Interrupt_Request
345 (Vector : CPU_Specific.Vector_Id) return Interrupt_ID
346 is
347 pragma Unreferenced (Vector);
348
349 SIVCR : Unsigned_32;
350 for SIVCR'Address use IMMRBAR + 16#0704#;
351 pragma Volatile (SIVCR);
352 pragma Import (Ada, SIVCR);
353 -- The SIVCR register contains the regular unmasked interrupt source
354 -- of the highest priority level.
355
356 begin
357 return System.BB.Interrupts.Interrupt_ID (SIVCR and 16#7F#);
358 end Get_Interrupt_Request;
359
360 -------------------------------
361 -- Install_Interrupt_Handler --
362 -------------------------------
363
364 procedure Install_Interrupt_Handler
365 (Handler : Address;
366 Interrupt : Interrupts.Interrupt_ID;
367 Prio : Interrupt_Priority)
368 is
369 pragma Unreferenced (Interrupt, Prio);
370 begin
371 CPU_Specific.Install_Exception_Handler
372 (Handler, CPU_Specific.External_Interrupt_Excp);
373 end Install_Interrupt_Handler;
374
375 ---------------------------
376 -- Priority_Of_Interrupt --
377 ---------------------------
378
379 function Priority_Of_Interrupt
380 (Interrupt : System.BB.Interrupts.Interrupt_ID) return System.Any_Priority
381 is
382 Result : constant Any_Priority := Interrupt_Priorities (Interrupt);
383
384 begin
385 -- The priority of an interrupt should be in the Interrupt_Priority
386 -- range. A failure indicates a spurious interrupt, or an interrupt
387 -- that was unmasked directly.
388
389 pragma Assert (Result in Interrupt_Priority);
390
391 return Result;
392 end Priority_Of_Interrupt;
393
394 ----------------
395 -- Power_Down --
396 ----------------
397
398 procedure Power_Down is
399 begin
400 null;
401 end Power_Down;
402
403 -----------------------------
404 -- Clear_Interrupt_Request --
405 -----------------------------
406
407 procedure Clear_Interrupt_Request
408 (Interrupt : System.BB.Interrupts.Interrupt_ID)
409 is
410 begin
411 -- Nothing to do for the IPIC
412 null;
413 end Clear_Interrupt_Request;
414
415 --------------------------
416 -- Set_Current_Priority --
417 --------------------------
418
419 procedure Set_Current_Priority (Priority : Integer) is
420 begin
421 -- Note that Priority cannot be the last one, as this procedure is
422 -- unable to disable the decrementer interrupt.
423
424 pragma Assert (Priority /= Interrupt_Priority'Last);
425
426 -- Must be called with MSR.IE set to 0, to avoid unprioritized
427 -- interrupt delivery.
428
429 if Priority < System.Interrupt_Priority'First then
430 SIMSR_H := Priority_Masks (System.Priority'Last).SIMSR_H;
431 SIMSR_L := Priority_Masks (System.Priority'Last).SIMSR_L;
432 SEMSR := Priority_Masks (System.Priority'Last).SEMSR;
433 else
434 SIMSR_H := Priority_Masks (Priority).SIMSR_H;
435 SIMSR_L := Priority_Masks (Priority).SIMSR_L;
436 SEMSR := Priority_Masks (Priority).SEMSR;
437 end if;
438 end Set_Current_Priority;
439
440 -------------------------------
441 -- Define_Interrupt_Priority --
442 -------------------------------
443
444 procedure Define_Interrupt_Priority
445 (Interrupt : System.BB.Interrupts.Interrupt_ID;
446 Priority : Interrupt_Priority;
447 Mask_Bit : Natural)
448 is
449 Mask : Unsigned_32;
450 -- Bit to set in the mask register
451
452 subtype Int32_Bit_Number is Natural range 0 .. 31;
453 -- Constrain the right operand of exponentiation so that the compiler
454 -- is able to replace it by a shift.
455
456 begin
457 -- Check the priority was never defined for this interrupt
458
459 pragma Assert (Interrupt_Priorities (Interrupt) = 0);
460
461 Protection.Enter_Kernel;
462
463 -- Save the values
464
465 Interrupt_Priorities (Interrupt) := Priority;
466
467 -- Regenerate masks
468
469 case Mask_Bit_Number (Mask_Bit) is
470 when 0 .. 31 =>
471 Mask := 2 ** Int32_Bit_Number (31 - Mask_Bit);
472
473 for P in System.Priority'Last .. Priority - 1 loop
474 Priority_Masks (P).SIMSR_H :=
475 Priority_Masks (P).SIMSR_H or Mask;
476 end loop;
477
478 when 32 .. 63 =>
479 Mask := 2 ** Int32_Bit_Number (63 - Mask_Bit);
480
481 for P in System.Priority'Last .. Priority - 1 loop
482 Priority_Masks (P).SIMSR_L :=
483 Priority_Masks (P).SIMSR_L or Mask;
484 end loop;
485
486 when 64 .. 95 =>
487 Mask := 2 ** Int32_Bit_Number (95 - Mask_Bit);
488
489 for P in System.Priority'Last .. Priority - 1 loop
490 Priority_Masks (P).SEMSR :=
491 Priority_Masks (P).SEMSR or Mask;
492 end loop;
493 end case;
494
495 -- Will set mask registers
496
497 Protection.Leave_Kernel;
498 end Define_Interrupt_Priority;
499
500 end System.BB.Board_Support;