]> git.sur5r.net Git - freertos/blob
1806274c7f657440b730de291a69ac31d559f605
[freertos] /
1 /******************************************************************************
2 *
3 * Copyright (C) 2010 - 2015 Xilinx, Inc.  All rights reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
30 *
31 ******************************************************************************/
32 /*****************************************************************************/
33 /**
34 *
35 * @file xscugic.c
36 * @addtogroup scugic_v3_1
37 * @{
38 *
39 * Contains required functions for the XScuGic driver for the Interrupt
40 * Controller. See xscugic.h for a detailed description of the driver.
41 *
42 * <pre>
43 * MODIFICATION HISTORY:
44 *
45 * Ver   Who  Date     Changes
46 * ----- ---- -------- --------------------------------------------------------
47 * 1.00a drg  01/19/10 First release
48 * 1.01a sdm  11/09/11 Changes are made in function XScuGic_CfgInitialize. Since
49 *                     "Config" entry is now made as pointer in the XScuGic
50 *                     structure, necessary changes are made.
51 *                     The HandlerTable can now be populated through the low
52 *                     level routine XScuGic_RegisterHandler added in this
53 *                     release. Hence necessary checks are added not to
54 *                     overwrite the HandlerTable entriesin function
55 *                     XScuGic_CfgInitialize.
56 * 1.03a srt  02/27/13 Added APIs
57 *                       - XScuGic_SetPriTrigTypeByDistAddr()
58 *                       - XScuGic_GetPriTrigTypeByDistAddr()
59 *                     Removed Offset calculation macros, defined in _hw.h
60 *                     (CR 702687)
61 *                         Added support to direct interrupts to the appropriate CPU. Earlier
62 *                         interrupts were directed to CPU1 (hard coded). Now depending
63 *                         upon the CPU selected by the user (xparameters.h), interrupts
64 *                         will be directed to the relevant CPU. This fixes CR 699688.
65 *
66 * 1.04a hk   05/04/13 Assigned EffectiveAddr to CpuBaseAddress in
67 *                         XScuGic_CfgInitialize. Fix for CR#704400 to remove warnings.
68 *                         Moved functions XScuGic_SetPriTrigTypeByDistAddr and
69 *             XScuGic_GetPriTrigTypeByDistAddr to xscugic_hw.c.
70 *                         This is fix for CR#705621.
71 * 1.06a asa  16/11/13 Fix for CR#749178. Assignment for EffectiveAddr
72 *                         in function XScuGic_CfgInitialize is removed as it was
73 *                     a bug.
74 * 3.00  kvn  02/13/14 Modified code for MISRA-C:2012 compliance.
75 * 3.01  pkp      06/19/15 Added XScuGic_InterruptMaptoCpu API for an interrupt
76 *                         target CPU mapping
77 * 3.02  pkp      11/09/15 Modified DistributorInit function for AMP case to add
78 *                                         the current cpu to interrupt processor targets registers
79 * 3.2   asa  02/29/16 Modified DistributorInit function for Zynq AMP case. The
80 *                         distributor is left uninitialized for Zynq AMP. It is assumed
81 *             that the distributor will be initialized by Linux master. However
82 *             for CortexR5 case, the earlier code is left unchanged where the
83 *             the interrupt processor target registers in the distributor is
84 *             initialized with the corresponding CPU ID on which the application
85 *             built over the scugic driver runs.
86 *             These changes fix CR#937243.
87 *
88 *
89 * </pre>
90 *
91 ******************************************************************************/
92
93 /***************************** Include Files *********************************/
94 #include "xil_types.h"
95 #include "xil_assert.h"
96 #include "xscugic.h"
97 #include "xparameters.h"
98
99 /************************** Constant Definitions *****************************/
100
101
102 /**************************** Type Definitions *******************************/
103
104
105 /***************** Macros (Inline Functions) Definitions *********************/
106
107 /************************** Variable Definitions *****************************/
108
109 /************************** Function Prototypes ******************************/
110
111 static void StubHandler(void *CallBackRef);
112
113 /*****************************************************************************/
114 /**
115 *
116 * DistributorInit initializes the distributor of the GIC. The
117 * initialization entails:
118 *
119 * - Write the trigger mode, priority and target CPU
120 * - All interrupt sources are disabled
121 * - Enable the distributor
122 *
123 * @param        InstancePtr is a pointer to the XScuGic instance.
124 * @param        CpuID is the Cpu ID to be initialized.
125 *
126 * @return       None
127 *
128 * @note         None.
129 *
130 ******************************************************************************/
131 static void DistributorInit(XScuGic *InstancePtr, u32 CpuID)
132 {
133         u32 Int_Id;
134         u32 LocalCpuID = CpuID;
135
136 #if USE_AMP==1
137         #warning "Building GIC for AMP"
138 #ifdef ARMR5
139     u32 RegValue;
140
141         /*
142          * The overall distributor should not be initialized in AMP case where
143          * another CPU is taking care of it.
144          */
145         LocalCpuID |= LocalCpuID << 8U;
146         LocalCpuID |= LocalCpuID << 16U;
147         for (Int_Id = 32U; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id=Int_Id+4U) {
148                 RegValue = XScuGic_DistReadReg(InstancePtr,
149                                                 XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id));
150                 RegValue |= LocalCpuID;
151                 XScuGic_DistWriteReg(InstancePtr,
152                                      XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id),
153                                      RegValue);
154         }
155 #endif
156         return;
157 #endif
158
159         Xil_AssertVoid(InstancePtr != NULL);
160         XScuGic_DistWriteReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET, 0U);
161
162         /*
163          * Set the security domains in the int_security registers for
164          * non-secure interrupts
165          * All are secure, so leave at the default. Set to 1 for non-secure
166          * interrupts.
167          */
168
169         /*
170          * For the Shared Peripheral Interrupts INT_ID[MAX..32], set:
171          */
172
173         /*
174          * 1. The trigger mode in the int_config register
175          * Only write to the SPI interrupts, so start at 32
176          */
177         for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; Int_Id=Int_Id+16U) {
178                 /*
179                  * Each INT_ID uses two bits, or 16 INT_ID per register
180                  * Set them all to be level sensitive, active HIGH.
181                  */
182                 XScuGic_DistWriteReg(InstancePtr,
183                                         XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id),
184                                         0U);
185         }
186
187
188 #define DEFAULT_PRIORITY    0xa0a0a0a0U
189         for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; Int_Id=Int_Id+4U) {
190                 /*
191                  * 2. The priority using int the priority_level register
192                  * The priority_level and spi_target registers use one byte per
193                  * INT_ID.
194                  * Write a default value that can be changed elsewhere.
195                  */
196                 XScuGic_DistWriteReg(InstancePtr,
197                                         XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id),
198                                         DEFAULT_PRIORITY);
199         }
200
201         for (Int_Id = 32U; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id=Int_Id+4U) {
202                 /*
203                  * 3. The CPU interface in the spi_target register
204                  * Only write to the SPI interrupts, so start at 32
205                  */
206                 LocalCpuID |= LocalCpuID << 8U;
207                 LocalCpuID |= LocalCpuID << 16U;
208
209                 XScuGic_DistWriteReg(InstancePtr,
210                                      XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id),
211                                      LocalCpuID);
212         }
213
214         for (Int_Id = 0U; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id=Int_Id+32U) {
215                 /*
216                  * 4. Enable the SPI using the enable_set register. Leave all
217                  * disabled for now.
218                  */
219                 XScuGic_DistWriteReg(InstancePtr,
220                 XSCUGIC_EN_DIS_OFFSET_CALC(XSCUGIC_DISABLE_OFFSET, Int_Id),
221                         0xFFFFFFFFU);
222
223         }
224
225         XScuGic_DistWriteReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET,
226                                                 XSCUGIC_EN_INT_MASK);
227
228 }
229
230 /*****************************************************************************/
231 /**
232 *
233 * CPUInitialize initializes the CPU Interface of the GIC. The initialization entails:
234 *
235 *       - Set the priority of the CPU
236 *       - Enable the CPU interface
237 *
238 * @param        InstancePtr is a pointer to the XScuGic instance.
239 *
240 * @return       None
241 *
242 * @note         None.
243 *
244 ******************************************************************************/
245 static void CPUInitialize(XScuGic *InstancePtr)
246 {
247         /*
248          * Program the priority mask of the CPU using the Priority mask register
249          */
250         XScuGic_CPUWriteReg(InstancePtr, XSCUGIC_CPU_PRIOR_OFFSET, 0xF0U);
251
252
253         /*
254          * If the CPU operates in both security domains, set parameters in the
255          * control_s register.
256          * 1. Set FIQen=1 to use FIQ for secure interrupts,
257          * 2. Program the AckCtl bit
258          * 3. Program the SBPR bit to select the binary pointer behavior
259          * 4. Set EnableS = 1 to enable secure interrupts
260          * 5. Set EnbleNS = 1 to enable non secure interrupts
261          */
262
263         /*
264          * If the CPU operates only in the secure domain, setup the
265          * control_s register.
266          * 1. Set FIQen=1,
267          * 2. Set EnableS=1, to enable the CPU interface to signal secure interrupts.
268          * Only enable the IRQ output unless secure interrupts are needed.
269          */
270         XScuGic_CPUWriteReg(InstancePtr, XSCUGIC_CONTROL_OFFSET, 0x07U);
271
272 }
273
274 /*****************************************************************************/
275 /**
276 *
277 * CfgInitialize a specific interrupt controller instance/driver. The
278 * initialization entails:
279 *
280 * - Initialize fields of the XScuGic structure
281 * - Initial vector table with stub function calls
282 * - All interrupt sources are disabled
283 *
284 * @param        InstancePtr is a pointer to the XScuGic instance.
285 * @param        ConfigPtr is a pointer to a config table for the particular
286 *               device this driver is associated with.
287 * @param        EffectiveAddr is the device base address in the virtual memory
288 *               address space. The caller is responsible for keeping the address
289 *               mapping from EffectiveAddr to the device physical base address
290 *               unchanged once this function is invoked. Unexpected errors may
291 *               occur if the address mapping changes after this function is
292 *               called. If address translation is not used, use
293 *               Config->BaseAddress for this parameters, passing the physical
294 *               address instead.
295 *
296 * @return
297 *               - XST_SUCCESS if initialization was successful
298 *
299 * @note         None.
300 *
301 ******************************************************************************/
302 s32  XScuGic_CfgInitialize(XScuGic *InstancePtr,
303                                 XScuGic_Config *ConfigPtr,
304                                 u32 EffectiveAddr)
305 {
306         u32 Int_Id;
307         u32 Cpu_Id = (u32)XPAR_CPU_ID + (u32)1;
308         (void) EffectiveAddr;
309
310         Xil_AssertNonvoid(InstancePtr != NULL);
311         Xil_AssertNonvoid(ConfigPtr != NULL);
312
313         if(InstancePtr->IsReady != XIL_COMPONENT_IS_READY) {
314
315                 InstancePtr->IsReady = 0;
316                 InstancePtr->Config = ConfigPtr;
317
318
319                 for (Int_Id = 0U; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id++) {
320                         /*
321                         * Initalize the handler to point to a stub to handle an
322                         * interrupt which has not been connected to a handler. Only
323                         * initialize it if the handler is 0 which means it was not
324                         * initialized statically by the tools/user. Set the callback
325                         * reference to this instance so that unhandled interrupts
326                         * can be tracked.
327                         */
328                         if      ((InstancePtr->Config->HandlerTable[Int_Id].Handler == NULL)) {
329                                 InstancePtr->Config->HandlerTable[Int_Id].Handler =
330                                                                         StubHandler;
331                         }
332                         InstancePtr->Config->HandlerTable[Int_Id].CallBackRef =
333                                                                 InstancePtr;
334                 }
335
336                 DistributorInit(InstancePtr, Cpu_Id);
337                 CPUInitialize(InstancePtr);
338
339                 InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
340         }
341
342         return XST_SUCCESS;
343 }
344
345 /*****************************************************************************/
346 /**
347 *
348 * Makes the connection between the Int_Id of the interrupt source and the
349 * associated handler that is to run when the interrupt is recognized. The
350 * argument provided in this call as the Callbackref is used as the argument
351 * for the handler when it is called.
352 *
353 * @param        InstancePtr is a pointer to the XScuGic instance.
354 * @param        Int_Id contains the ID of the interrupt source and should be
355 *               in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1
356 * @param        Handler to the handler for that interrupt.
357 * @param        CallBackRef is the callback reference, usually the instance
358 *               pointer of the connecting driver.
359 *
360 * @return
361 *
362 *               - XST_SUCCESS if the handler was connected correctly.
363 *
364 * @note
365 *
366 * WARNING: The handler provided as an argument will overwrite any handler
367 * that was previously connected.
368 *
369 ****************************************************************************/
370 s32  XScuGic_Connect(XScuGic *InstancePtr, u32 Int_Id,
371                       Xil_InterruptHandler Handler, void *CallBackRef)
372 {
373         /*
374          * Assert the arguments
375          */
376         Xil_AssertNonvoid(InstancePtr != NULL);
377         Xil_AssertNonvoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS);
378         Xil_AssertNonvoid(Handler != NULL);
379         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
380
381         /*
382          * The Int_Id is used as an index into the table to select the proper
383          * handler
384          */
385         InstancePtr->Config->HandlerTable[Int_Id].Handler = Handler;
386         InstancePtr->Config->HandlerTable[Int_Id].CallBackRef = CallBackRef;
387
388         return XST_SUCCESS;
389 }
390
391 /*****************************************************************************/
392 /**
393 *
394 * Updates the interrupt table with the Null Handler and NULL arguments at the
395 * location pointed at by the Int_Id. This effectively disconnects that interrupt
396 * source from any handler. The interrupt is disabled also.
397 *
398 * @param        InstancePtr is a pointer to the XScuGic instance to be worked on.
399 * @param        Int_Id contains the ID of the interrupt source and should
400 *               be in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1
401 *
402 * @return       None.
403 *
404 * @note         None.
405 *
406 ****************************************************************************/
407 void XScuGic_Disconnect(XScuGic *InstancePtr, u32 Int_Id)
408 {
409         u32 Mask;
410
411         /*
412          * Assert the arguments
413          */
414         Xil_AssertVoid(InstancePtr != NULL);
415         Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS);
416         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
417
418         /*
419          * The Int_Id is used to create the appropriate mask for the
420          * desired bit position. Int_Id currently limited to 0 - 31
421          */
422         Mask = 0x00000001U << (Int_Id % 32U);
423
424         /*
425          * Disable the interrupt such that it won't occur while disconnecting
426          * the handler, only disable the specified interrupt id without modifying
427          * the other interrupt ids
428          */
429         XScuGic_DistWriteReg(InstancePtr, (u32)XSCUGIC_DISABLE_OFFSET +
430                                                 ((Int_Id / 32U) * 4U), Mask);
431
432         /*
433          * Disconnect the handler and connect a stub, the callback reference
434          * must be set to this instance to allow unhandled interrupts to be
435          * tracked
436          */
437         InstancePtr->Config->HandlerTable[Int_Id].Handler = StubHandler;
438         InstancePtr->Config->HandlerTable[Int_Id].CallBackRef = InstancePtr;
439 }
440
441 /*****************************************************************************/
442 /**
443 *
444 * Enables the interrupt source provided as the argument Int_Id. Any pending
445 * interrupt condition for the specified Int_Id will occur after this function is
446 * called.
447 *
448 * @param        InstancePtr is a pointer to the XScuGic instance.
449 * @param        Int_Id contains the ID of the interrupt source and should be
450 *               in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1
451 *
452 * @return       None.
453 *
454 * @note         None.
455 *
456 ****************************************************************************/
457 void XScuGic_Enable(XScuGic *InstancePtr, u32 Int_Id)
458 {
459         u32 Mask;
460
461         /*
462          * Assert the arguments
463          */
464         Xil_AssertVoid(InstancePtr != NULL);
465         Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS);
466         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
467
468         /*
469          * The Int_Id is used to create the appropriate mask for the
470          * desired bit position. Int_Id currently limited to 0 - 31
471          */
472         Mask = 0x00000001U << (Int_Id % 32U);
473
474         /*
475          * Enable the selected interrupt source by setting the
476          * corresponding bit in the Enable Set register.
477          */
478         XScuGic_DistWriteReg(InstancePtr, (u32)XSCUGIC_ENABLE_SET_OFFSET +
479                                                 ((Int_Id / 32U) * 4U), Mask);
480 }
481
482 /*****************************************************************************/
483 /**
484 *
485 * Disables the interrupt source provided as the argument Int_Id such that the
486 * interrupt controller will not cause interrupts for the specified Int_Id. The
487 * interrupt controller will continue to hold an interrupt condition for the
488 * Int_Id, but will not cause an interrupt.
489 *
490 * @param        InstancePtr is a pointer to the XScuGic instance.
491 * @param        Int_Id contains the ID of the interrupt source and should be
492 *               in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1
493 *
494 * @return       None.
495 *
496 * @note         None.
497 *
498 ****************************************************************************/
499 void XScuGic_Disable(XScuGic *InstancePtr, u32 Int_Id)
500 {
501         u32 Mask;
502
503         /*
504          * Assert the arguments
505          */
506         Xil_AssertVoid(InstancePtr != NULL);
507         Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS);
508         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
509
510         /*
511          * The Int_Id is used to create the appropriate mask for the
512          * desired bit position. Int_Id currently limited to 0 - 31
513          */
514         Mask = 0x00000001U << (Int_Id % 32U);
515
516         /*
517          * Disable the selected interrupt source by setting the
518          * corresponding bit in the IDR.
519          */
520         XScuGic_DistWriteReg(InstancePtr, (u32)XSCUGIC_DISABLE_OFFSET +
521                                                 ((Int_Id / 32U) * 4U), Mask);
522 }
523
524 /*****************************************************************************/
525 /**
526 *
527 * Allows software to simulate an interrupt in the interrupt controller.  This
528 * function will only be successful when the interrupt controller has been
529 * started in simulation mode.  A simulated interrupt allows the interrupt
530 * controller to be tested without any device to drive an interrupt input
531 * signal into it.
532 *
533 * @param        InstancePtr is a pointer to the XScuGic instance.
534 * @param        Int_Id is the software interrupt ID to simulate an interrupt.
535 * @param        Cpu_Id is the list of CPUs to send the interrupt.
536 *
537 * @return
538 *
539 * XST_SUCCESS if successful, or XST_FAILURE if the interrupt could not be
540 * simulated
541 *
542 * @note         None.
543 *
544 ******************************************************************************/
545 s32  XScuGic_SoftwareIntr(XScuGic *InstancePtr, u32 Int_Id, u32 Cpu_Id)
546 {
547         u32 Mask;
548
549         /*
550          * Assert the arguments
551          */
552         Xil_AssertNonvoid(InstancePtr != NULL);
553         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
554         Xil_AssertNonvoid(Int_Id <= 15U) ;
555         Xil_AssertNonvoid(Cpu_Id <= 255U) ;
556
557
558         /*
559          * The Int_Id is used to create the appropriate mask for the
560          * desired interrupt. Int_Id currently limited to 0 - 15
561          * Use the target list for the Cpu ID.
562          */
563         Mask = ((Cpu_Id << 16U) | Int_Id) &
564                 (XSCUGIC_SFI_TRIG_CPU_MASK | XSCUGIC_SFI_TRIG_INTID_MASK);
565
566         /*
567          * Write to the Software interrupt trigger register. Use the appropriate
568          * CPU Int_Id.
569          */
570         XScuGic_DistWriteReg(InstancePtr, XSCUGIC_SFI_TRIG_OFFSET, Mask);
571
572         /* Indicate the interrupt was successfully simulated */
573
574         return XST_SUCCESS;
575 }
576
577 /*****************************************************************************/
578 /**
579 *
580 * A stub for the asynchronous callback. The stub is here in case the upper
581 * layers forget to set the handler.
582 *
583 * @param        CallBackRef is a pointer to the upper layer callback reference
584 *
585 * @return       None.
586 *
587 * @note         None.
588 *
589 ******************************************************************************/
590 static void StubHandler(void *CallBackRef) {
591         /*
592          * verify that the inputs are valid
593          */
594         Xil_AssertVoid(CallBackRef != NULL);
595
596         /*
597          * Indicate another unhandled interrupt for stats
598          */
599         ((XScuGic *)((void *)CallBackRef))->UnhandledInterrupts++;
600 }
601
602 /****************************************************************************/
603 /**
604 * Sets the interrupt priority and trigger type for the specificd IRQ source.
605 *
606 * @param        InstancePtr is a pointer to the instance to be worked on.
607 * @param        Int_Id is the IRQ source number to modify
608 * @param        Priority is the new priority for the IRQ source. 0 is highest
609 *                       priority, 0xF8 (248) is lowest. There are 32 priority levels
610 *                       supported with a step of 8. Hence the supported priorities are
611 *                       0, 8, 16, 32, 40 ..., 248.
612 * @param        Trigger is the new trigger type for the IRQ source.
613 * Each bit pair describes the configuration for an INT_ID.
614 * SFI    Read Only    b10 always
615 * PPI    Read Only    depending on how the PPIs are configured.
616 *                    b01    Active HIGH level sensitive
617 *                    b11 Rising edge sensitive
618 * SPI                LSB is read only.
619 *                    b01    Active HIGH level sensitive
620 *                    b11 Rising edge sensitive/
621 *
622 * @return       None.
623 *
624 * @note         None.
625 *
626 *****************************************************************************/
627 void XScuGic_SetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id,
628                                         u8 Priority, u8 Trigger)
629 {
630         u32 RegValue;
631         u8 LocalPriority;
632         LocalPriority = Priority;
633
634         Xil_AssertVoid(InstancePtr != NULL);
635         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
636         Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS);
637         Xil_AssertVoid(Trigger <= (u8)XSCUGIC_INT_CFG_MASK);
638         Xil_AssertVoid(LocalPriority <= (u8)XSCUGIC_MAX_INTR_PRIO_VAL);
639
640         /*
641          * Determine the register to write to using the Int_Id.
642          */
643         RegValue = XScuGic_DistReadReg(InstancePtr,
644                         XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id));
645
646         /*
647          * The priority bits are Bits 7 to 3 in GIC Priority Register. This
648          * means the number of priority levels supported are 32 and they are
649          * in steps of 8. The priorities can be 0, 8, 16, 32, 48, ... etc.
650          * The lower order 3 bits are masked before putting it in the register.
651          */
652         LocalPriority = LocalPriority & (u8)XSCUGIC_INTR_PRIO_MASK;
653         /*
654          * Shift and Mask the correct bits for the priority and trigger in the
655          * register
656          */
657         RegValue &= ~(XSCUGIC_PRIORITY_MASK << ((Int_Id%4U)*8U));
658         RegValue |= (u32)LocalPriority << ((Int_Id%4U)*8U);
659
660         /*
661          * Write the value back to the register.
662          */
663         XScuGic_DistWriteReg(InstancePtr, XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id),
664                                 RegValue);
665
666         /*
667          * Determine the register to write to using the Int_Id.
668          */
669         RegValue = XScuGic_DistReadReg(InstancePtr,
670                         XSCUGIC_INT_CFG_OFFSET_CALC (Int_Id));
671
672         /*
673          * Shift and Mask the correct bits for the priority and trigger in the
674          * register
675          */
676         RegValue &= ~(XSCUGIC_INT_CFG_MASK << ((Int_Id%16U)*2U));
677         RegValue |= (u32)Trigger << ((Int_Id%16U)*2U);
678
679         /*
680          * Write the value back to the register.
681          */
682         XScuGic_DistWriteReg(InstancePtr, XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id),
683                                 RegValue);
684
685 }
686
687 /****************************************************************************/
688 /**
689 * Gets the interrupt priority and trigger type for the specificd IRQ source.
690 *
691 * @param        InstancePtr is a pointer to the instance to be worked on.
692 * @param        Int_Id is the IRQ source number to modify
693 * @param        Priority is a pointer to the value of the priority of the IRQ
694 *               source. This is a return value.
695 * @param        Trigger is pointer to the value of the trigger of the IRQ
696 *               source. This is a return value.
697 *
698 * @return       None.
699 *
700 * @note         None
701 *
702 *****************************************************************************/
703 void XScuGic_GetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id,
704                                         u8 *Priority, u8 *Trigger)
705 {
706         u32 RegValue;
707
708         Xil_AssertVoid(InstancePtr != NULL);
709         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
710         Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS);
711         Xil_AssertVoid(Priority != NULL);
712         Xil_AssertVoid(Trigger != NULL);
713
714         /*
715          * Determine the register to read to using the Int_Id.
716          */
717         RegValue = XScuGic_DistReadReg(InstancePtr,
718             XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id));
719
720         /*
721          * Shift and Mask the correct bits for the priority and trigger in the
722          * register
723          */
724         RegValue = RegValue >> ((Int_Id%4U)*8U);
725         *Priority = (u8)(RegValue & XSCUGIC_PRIORITY_MASK);
726
727         /*
728          * Determine the register to read to using the Int_Id.
729          */
730         RegValue = XScuGic_DistReadReg(InstancePtr,
731         XSCUGIC_INT_CFG_OFFSET_CALC (Int_Id));
732
733         /*
734          * Shift and Mask the correct bits for the priority and trigger in the
735          * register
736          */
737         RegValue = RegValue >> ((Int_Id%16U)*2U);
738
739         *Trigger = (u8)(RegValue & XSCUGIC_INT_CFG_MASK);
740 }
741 /****************************************************************************/
742 /**
743 * Sets the target CPU for the interrupt of a peripheral
744 *
745 * @param        InstancePtr is a pointer to the instance to be worked on.
746 * @param        Cpu_Id is a CPU number for which the interrupt has to be targeted
747 * @param        Int_Id is the IRQ source number to modify
748 *
749 * @return       None.
750 *
751 * @note         None
752 *
753 *****************************************************************************/
754 void XScuGic_InterruptMaptoCpu(XScuGic *InstancePtr, u8 Cpu_Id, u32 Int_Id)
755 {
756         u32 RegValue, Offset;
757         RegValue = XScuGic_DistReadReg(InstancePtr,
758                         XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id));
759
760         Offset =  (Int_Id & 0x3);
761
762         RegValue = (RegValue | (~(0xFF << (Offset*8))) );
763         RegValue |= ((Cpu_Id) << (Offset*8));
764
765         XScuGic_DistWriteReg(InstancePtr,
766                                                  XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id),
767                                                  RegValue);
768 }
769 /** @} */