1 /******************************************************************************
3 * Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved.
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:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
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.
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
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.
31 ******************************************************************************/
32 /*****************************************************************************/
37 * Contains required functions for the XIntc driver for the Xilinx Interrupt
38 * Controller. See xintc.h for a detailed description of the driver.
41 * MODIFICATION HISTORY:
43 * Ver Who Date Changes
44 * ----- ---- -------- --------------------------------------------------------
45 * 1.00a ecm 08/16/01 First release
46 * 1.00b jhl 02/21/02 Repartitioned the driver for smaller files
47 * 1.00b jhl 04/24/02 Made LookupConfig global and compressed ack before table
48 * in the configuration into a bit mask
49 * 1.00c rpm 10/17/03 New release. Support the static vector table created
50 * in the xintc_g.c configuration table.
51 * 1.00c rpm 04/23/04 Removed check in XIntc_Connect for a previously connected
52 * handler. Always overwrite the vector table handler with
53 * the handler provided as an argument.
54 * 1.10c mta 03/21/07 Updated to new coding style
55 * 1.11a sv 11/21/07 Updated driver to support access through a DCR bridge
56 * 2.00a ktn 10/20/09 Updated to use HAL Processor APIs.
57 * 2.04a bss 01/13/12 Added XIntc_ConnectFastHandler API for Fast Interrupt
58 * and XIntc_SetNormalIntrMode for setting to normal
60 * 2.05a bss 08/16/12 Updated to support relocatable vectors in Microblaze,
61 * updated XIntc_SetNormalIntrMode to use IntVectorAddr
62 * which is the interrupt vector address
63 * 2.06a bss 01/28/13 To support Cascade mode:
64 * Modified XIntc_Initialize,XIntc_Start,XIntc_Connect
65 * XIntc_Disconnect,XIntc_Enable,XIntc_Disable,
66 * XIntc_Acknowledge,XIntc_ConnectFastHandler and
67 * XIntc_SetNormalIntrMode APIs.
68 * Added XIntc_InitializeSlaves API.
69 * 3.0 bss 01/28/13 Modified to initialize IVAR register with
70 * XPAR_MICROBLAZE_BASE_VECTORS + 0x10 to fix
75 ******************************************************************************/
77 /***************************** Include Files *********************************/
79 #include "xil_types.h"
80 #include "xil_assert.h"
85 /************************** Constant Definitions *****************************/
88 /**************************** Type Definitions *******************************/
91 /***************** Macros (Inline Functions) Definitions *********************/
94 /************************** Variable Definitions *****************************/
97 * Array of masks associated with the bit position, improves performance
98 * in the ISR and acknowledge functions, this table is shared between all
99 * instances of the driver. XIN_CONTROLLER_MAX_INTRS is the maximum number of
100 * sources of Interrupt controller
102 u32 XIntc_BitPosMask[XIN_CONTROLLER_MAX_INTRS];
104 /************************** Function Prototypes ******************************/
106 static void StubHandler(void *CallBackRef);
107 static void XIntc_InitializeSlaves(XIntc * InstancePtr);
109 /*****************************************************************************/
112 * Initialize a specific interrupt controller instance/driver. The
113 * initialization entails:
115 * - Initialize fields of the XIntc structure
116 * - Initial vector table with stub function calls
117 * - All interrupt sources are disabled
118 * - Interrupt output is disabled
120 * @param InstancePtr is a pointer to the XIntc instance to be worked on.
121 * @param DeviceId is the unique id of the device controlled by this XIntc
122 * instance. Passing in a device id associates the generic XIntc
123 * instance to a specific device, as chosen by the caller or
124 * application developer.
127 * - XST_SUCCESS if initialization was successful
128 * - XST_DEVICE_IS_STARTED if the device has already been started
129 * - XST_DEVICE_NOT_FOUND if device configuration information was
130 * not found for a device with the supplied device ID.
132 * @note In Cascade mode this function calls XIntc_InitializeSlaves to
133 * initialiaze Slave Interrupt controllers.
135 ******************************************************************************/
136 int XIntc_Initialize(XIntc * InstancePtr, u16 DeviceId)
139 XIntc_Config *CfgPtr;
142 Xil_AssertNonvoid(InstancePtr != NULL);
145 * If the device is started, disallow the initialize and return a status
146 * indicating it is started. This allows the user to stop the device
147 * and reinitialize, but prevents a user from inadvertently initializing
149 if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) {
150 return XST_DEVICE_IS_STARTED;
154 * Lookup the device configuration in the CROM table. Use this
155 * configuration info down below when initializing this component.
157 CfgPtr = XIntc_LookupConfig(DeviceId);
158 if (CfgPtr == NULL) {
159 return XST_DEVICE_NOT_FOUND;
163 * Set some default values
165 InstancePtr->IsReady = 0;
166 InstancePtr->IsStarted = 0; /* not started */
167 InstancePtr->CfgPtr = CfgPtr;
169 InstancePtr->CfgPtr->Options = XIN_SVC_SGL_ISR_OPTION;
170 InstancePtr->CfgPtr->IntcType = CfgPtr->IntcType;
173 * Save the base address pointer such that the registers of the
174 * interrupt can be accessed
176 #if (XPAR_XINTC_USE_DCR_BRIDGE != 0)
177 InstancePtr->BaseAddress = ((CfgPtr->BaseAddress >> 2)) & 0xFFF;
179 InstancePtr->BaseAddress = CfgPtr->BaseAddress;
183 * Initialize all the data needed to perform interrupt processing for
184 * each interrupt ID up to the maximum used
186 for (Id = 0; Id < CfgPtr->NumberofIntrs; Id++) {
189 * Initalize the handler to point to a stub to handle an
190 * interrupt which has not been connected to a handler. Only
191 * initialize it if the handler is 0 or XNullHandler, which
192 * means it was not initialized statically by the tools/user.
193 * Set the callback reference to this instance so that
194 * unhandled interrupts can be tracked.
196 if ((InstancePtr->CfgPtr->HandlerTable[Id].Handler == 0) ||
197 (InstancePtr->CfgPtr->HandlerTable[Id].Handler ==
199 InstancePtr->CfgPtr->HandlerTable[Id].Handler =
202 InstancePtr->CfgPtr->HandlerTable[Id].CallBackRef = InstancePtr;
205 * Initialize the bit position mask table such that bit
206 * positions are lookups only for each interrupt id, with 0
207 * being a special case
208 * (XIntc_BitPosMask[] = { 1, 2, 4, 8, ... })
210 XIntc_BitPosMask[Id] = NextBitMask;
215 * Disable IRQ output signal
216 * Disable all interrupt sources
217 * Acknowledge all sources
219 XIntc_Out32(InstancePtr->BaseAddress + XIN_MER_OFFSET, 0);
220 XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET, 0);
221 XIntc_Out32(InstancePtr->BaseAddress + XIN_IAR_OFFSET, 0xFFFFFFFF);
224 * If the fast Interrupt mode is enabled then set all the
225 * interrupts as normal mode.
227 if(InstancePtr->CfgPtr->FastIntr == TRUE) {
228 XIntc_Out32(InstancePtr->BaseAddress + XIN_IMR_OFFSET, 0);
230 #ifdef XPAR_MICROBLAZE_BASE_VECTORS
231 for (Id = 0; Id < 32 ; Id++)
233 XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET
234 + (Id * 4), XPAR_MICROBLAZE_BASE_VECTORS
238 for (Id = 0; Id < 32 ; Id++)
240 XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET
246 /* Initialize slaves in Cascade mode*/
247 if (InstancePtr->CfgPtr->IntcType != XIN_INTC_NOCASCADE) {
248 XIntc_InitializeSlaves(InstancePtr);
252 * Indicate the instance is now ready to use, successfully initialized
254 InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
259 /*****************************************************************************/
262 * Starts the interrupt controller by enabling the output from the controller
263 * to the processor. Interrupts may be generated by the interrupt controller
264 * after this function is called.
266 * It is necessary for the caller to connect the interrupt handler of this
267 * component to the proper interrupt source. This function also starts Slave
268 * controllers in Cascade mode.
270 * @param InstancePtr is a pointer to the XIntc instance to be worked on.
271 * @param Mode determines if software is allowed to simulate interrupts or
272 * real interrupts are allowed to occur. Note that these modes are
273 * mutually exclusive. The interrupt controller hardware resets in
274 * a mode that allows software to simulate interrupts until this
275 * mode is exited. It cannot be reentered once it has been exited.
277 * One of the following values should be used for the mode.
278 * - XIN_SIMULATION_MODE enables simulation of interrupts only
279 * - XIN_REAL_MODE enables hardware interrupts only
282 * - XST_SUCCESS if the device was started successfully
283 * - XST_FAILURE if simulation mode was specified and it could not
284 * be set because real mode has already been entered.
286 * @note Must be called after XIntc initialization is completed.
288 ******************************************************************************/
289 int XIntc_Start(XIntc * InstancePtr, u8 Mode)
291 u32 MasterEnable = XIN_INT_MASTER_ENABLE_MASK;
292 XIntc_Config *CfgPtr;
296 * Assert the arguments
298 Xil_AssertNonvoid(InstancePtr != NULL);
299 Xil_AssertNonvoid((Mode == XIN_SIMULATION_MODE) ||
300 (Mode == XIN_REAL_MODE))
301 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
304 * Check for simulation mode
306 if (Mode == XIN_SIMULATION_MODE) {
307 if (MasterEnable & XIN_INT_HARDWARE_ENABLE_MASK) {
312 MasterEnable |= XIN_INT_HARDWARE_ENABLE_MASK;
316 * Indicate the instance is ready to be used and is started before we
319 InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED;
321 /* Start the Slaves for Cascade Mode */
322 if (InstancePtr->CfgPtr->IntcType != XIN_INTC_NOCASCADE) {
323 for (Index = 1; Index <= XPAR_XINTC_NUM_INSTANCES - 1; Index++)
325 CfgPtr = XIntc_LookupConfig(Index);
326 XIntc_Out32(CfgPtr->BaseAddress + XIN_MER_OFFSET,
331 /* Start the master */
332 XIntc_Out32(InstancePtr->BaseAddress + XIN_MER_OFFSET, MasterEnable);
337 /*****************************************************************************/
340 * Stops the interrupt controller by disabling the output from the controller
341 * so that no interrupts will be caused by the interrupt controller.
343 * @param InstancePtr is a pointer to the XIntc instance to be worked on.
349 ******************************************************************************/
350 void XIntc_Stop(XIntc * InstancePtr)
353 * Assert the arguments
355 Xil_AssertVoid(InstancePtr != NULL);
356 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
359 * Stop all interrupts from occurring thru the interrupt controller by
360 * disabling all interrupts in the MER register
362 XIntc_Out32(InstancePtr->BaseAddress + XIN_MER_OFFSET, 0);
364 InstancePtr->IsStarted = 0;
367 /*****************************************************************************/
370 * Makes the connection between the Id of the interrupt source and the
371 * associated handler that is to run when the interrupt is recognized. The
372 * argument provided in this call as the Callbackref is used as the argument
373 * for the handler when it is called. In Cascade mode, connects handler to
374 * Slave controller handler table depending on the interrupt Id.
376 * @param InstancePtr is a pointer to the XIntc instance to be worked on.
377 * @param Id contains the ID of the interrupt source and should be in the
378 * range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being
379 * the highest priority interrupt.
380 * @param Handler to the handler for that interrupt.
381 * @param CallBackRef is the callback reference, usually the instance
382 * pointer of the connecting driver.
386 * - XST_SUCCESS if the handler was connected correctly.
390 * WARNING: The handler provided as an argument will overwrite any handler
391 * that was previously connected.
393 ****************************************************************************/
394 int XIntc_Connect(XIntc * InstancePtr, u8 Id,
395 XInterruptHandler Handler, void *CallBackRef)
397 XIntc_Config *CfgPtr;
399 * Assert the arguments
401 Xil_AssertNonvoid(InstancePtr != NULL);
402 Xil_AssertNonvoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS);
403 Xil_AssertNonvoid(Handler != NULL);
404 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
406 /* Connect Handlers for Slave controllers in Cascade Mode */
409 CfgPtr = XIntc_LookupConfig(Id/32);
411 CfgPtr->HandlerTable[Id%32].Handler = Handler;
412 CfgPtr->HandlerTable[Id%32].CallBackRef = CallBackRef;
414 /* Connect Handlers for Master/primary controller */
417 * The Id is used as an index into the table to select the
420 InstancePtr->CfgPtr->HandlerTable[Id].Handler = Handler;
421 InstancePtr->CfgPtr->HandlerTable[Id].CallBackRef =
428 /*****************************************************************************/
431 * Updates the interrupt table with the Null Handler and NULL arguments at the
432 * location pointed at by the Id. This effectively disconnects that interrupt
433 * source from any handler. The interrupt is disabled also. In Cascade mode,
434 * disconnects handler from Slave controller handler table depending on the
437 * @param InstancePtr is a pointer to the XIntc instance to be worked on.
438 * @param Id contains the ID of the interrupt source and should be in the
439 * range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being
440 * the highest priority interrupt.
446 ****************************************************************************/
447 void XIntc_Disconnect(XIntc * InstancePtr, u8 Id)
451 XIntc_Config *CfgPtr;
454 * Assert the arguments
456 Xil_AssertVoid(InstancePtr != NULL);
457 Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS);
458 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
461 * Disable the interrupt such that it won't occur while disconnecting
462 * the handler, only disable the specified interrupt id without
463 * modifying the other interrupt ids
466 /* Disconnect Handlers for Slave controllers in Cascade Mode */
469 CfgPtr = XIntc_LookupConfig(Id/32);
471 CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET);
473 /* Convert from integer id to bit mask */
474 Mask = XIntc_BitPosMask[(Id%32)];
476 XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET,
477 (CurrentIER & ~Mask));
479 * Disconnect the handler and connect a stub, the callback
480 * reference must be set to this instance to allow unhandled
481 * interrupts to be tracked
483 CfgPtr->HandlerTable[Id%32].Handler = StubHandler;
484 CfgPtr->HandlerTable[Id%32].CallBackRef = InstancePtr;
486 /* Disconnect Handlers for Master/primary controller */
488 CurrentIER = XIntc_In32(InstancePtr->BaseAddress +
491 /* Convert from integer id to bit mask */
492 Mask = XIntc_BitPosMask[Id];
494 XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET,
495 (CurrentIER & ~Mask));
496 InstancePtr->CfgPtr->HandlerTable[Id%32].Handler =
498 InstancePtr->CfgPtr->HandlerTable[Id%32].CallBackRef =
504 /*****************************************************************************/
507 * Enables the interrupt source provided as the argument Id. Any pending
508 * interrupt condition for the specified Id will occur after this function is
509 * called. In Cascade mode, enables corresponding interrupt of Slave controllers
510 * depending on the Id.
512 * @param InstancePtr is a pointer to the XIntc instance to be worked on.
513 * @param Id contains the ID of the interrupt source and should be in the
514 * range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being
515 * the highest priority interrupt.
521 ****************************************************************************/
522 void XIntc_Enable(XIntc * InstancePtr, u8 Id)
526 XIntc_Config *CfgPtr;
529 * Assert the arguments
531 Xil_AssertVoid(InstancePtr != NULL);
532 Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS);
533 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
537 /* Enable user required Id in Slave controller */
538 CfgPtr = XIntc_LookupConfig(Id/32);
540 CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET);
542 /* Convert from integer id to bit mask */
543 Mask = XIntc_BitPosMask[(Id%32)];
545 XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET,
546 (CurrentIER | Mask));
550 * The Id is used to create the appropriate mask for the
551 * desired bit position.
553 Mask = XIntc_BitPosMask[Id];
556 * Enable the selected interrupt source by reading the
557 * interrupt enable register and then modifying only the
558 * specified interrupt id enable
560 CurrentIER = XIntc_In32(InstancePtr->BaseAddress +
562 XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET,
563 (CurrentIER | Mask));
567 /*****************************************************************************/
570 * Disables the interrupt source provided as the argument Id such that the
571 * interrupt controller will not cause interrupts for the specified Id. The
572 * interrupt controller will continue to hold an interrupt condition for the
573 * Id, but will not cause an interrupt.In Cascade mode, disables corresponding
574 * interrupt of Slave controllers depending on the Id.
576 * @param InstancePtr is a pointer to the XIntc instance to be worked on.
577 * @param Id contains the ID of the interrupt source and should be in the
578 * range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being the
579 * highest priority interrupt.
585 ****************************************************************************/
586 void XIntc_Disable(XIntc * InstancePtr, u8 Id)
590 XIntc_Config *CfgPtr;
593 * Assert the arguments
595 Xil_AssertVoid(InstancePtr != NULL);
596 Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS);
597 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
600 /* Enable user required Id in Slave controller */
601 CfgPtr = XIntc_LookupConfig(Id/32);
603 CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET);
605 /* Convert from integer id to bit mask */
606 Mask = XIntc_BitPosMask[(Id%32)];
608 XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET,
609 (CurrentIER & ~Mask));
612 * The Id is used to create the appropriate mask for the
613 * desired bit position. Id currently limited to 0 - 31
615 Mask = XIntc_BitPosMask[Id];
618 * Disable the selected interrupt source by reading the
619 * interrupt enable register and then modifying only the
620 * specified interrupt id
622 CurrentIER = XIntc_In32(InstancePtr->BaseAddress +
624 XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET,
625 (CurrentIER & ~Mask));
629 /*****************************************************************************/
632 * Acknowledges the interrupt source provided as the argument Id. When the
633 * interrupt is acknowledged, it causes the interrupt controller to clear its
634 * interrupt condition.In Cascade mode, acknowledges corresponding interrupt
635 * source of Slave controllers depending on the Id.
637 * @param InstancePtr is a pointer to the XIntc instance to be worked on.
638 * @param Id contains the ID of the interrupt source and should be in the
639 * range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being
640 * the highest priority interrupt.
646 ****************************************************************************/
647 void XIntc_Acknowledge(XIntc * InstancePtr, u8 Id)
650 XIntc_Config *CfgPtr;
653 * Assert the arguments
655 Xil_AssertVoid(InstancePtr != NULL);
656 Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS);
657 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
660 /* Enable user required Id in Slave controller */
661 CfgPtr = XIntc_LookupConfig(Id/32);
663 /* Convert from integer id to bit mask */
664 Mask = XIntc_BitPosMask[(Id%32)];
666 XIntc_Out32(CfgPtr->BaseAddress + XIN_IAR_OFFSET, Mask);
669 * The Id is used to create the appropriate mask for the
670 * desired bit position.
672 Mask = XIntc_BitPosMask[Id];
675 * Acknowledge the selected interrupt source, no read of the
676 * acknowledge register is necessary since only the bits set
677 * in the mask will be affected by the write
679 XIntc_Out32(InstancePtr->BaseAddress + XIN_IAR_OFFSET, Mask);
683 /*****************************************************************************/
686 * A stub for the asynchronous callback. The stub is here in case the upper
687 * layers forget to set the handler.
689 * @param CallBackRef is a pointer to the upper layer callback reference
695 ******************************************************************************/
696 static void StubHandler(void *CallBackRef)
699 * Verify that the inputs are valid
701 Xil_AssertVoid(CallBackRef != NULL);
704 * Indicate another unhandled interrupt for stats
706 ((XIntc *) CallBackRef)->UnhandledInterrupts++;
709 /*****************************************************************************/
712 * Looks up the device configuration based on the unique device ID. A table
713 * contains the configuration info for each device in the system.
715 * @param DeviceId is the unique identifier for a device.
717 * @return A pointer to the XIntc configuration structure for the specified
718 * device, or NULL if the device was not found.
722 ******************************************************************************/
723 XIntc_Config *XIntc_LookupConfig(u16 DeviceId)
725 XIntc_Config *CfgPtr = NULL;
728 for (Index = 0; Index < XPAR_XINTC_NUM_INSTANCES; Index++) {
729 if (XIntc_ConfigTable[Index].DeviceId == DeviceId) {
730 CfgPtr = &XIntc_ConfigTable[Index];
738 /*****************************************************************************/
741 * Makes the connection between the Id of the interrupt source and the
742 * associated handler that is to run when the interrupt is recognized.In Cascade
743 * mode, connects handler to corresponding Slave controller IVAR register
744 * depending on the Id and sets all interrupt sources of the Slave controller as
747 * @param InstancePtr is a pointer to the XIntc instance to be worked on.
748 * @param Id contains the ID of the interrupt source and should be in the
749 * range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being
750 * the highest priority interrupt.
751 * @param Handler to the handler for that interrupt.
757 * Slave controllers in Cascade Mode should have all as Fast
758 * interrupts or Normal interrupts, mixed interrupts are not
761 * WARNING: The handler provided as an argument will overwrite any handler
762 * that was previously connected.
764 ****************************************************************************/
765 int XIntc_ConnectFastHandler(XIntc *InstancePtr, u8 Id,
766 XFastInterruptHandler Handler)
771 XIntc_Config *CfgPtr;
774 * Assert the arguments
776 Xil_AssertNonvoid(InstancePtr != NULL);
777 Xil_AssertNonvoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS);
778 Xil_AssertNonvoid(Handler != NULL);
779 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
780 Xil_AssertNonvoid(InstancePtr->CfgPtr->FastIntr == TRUE);
784 /* Enable user required Id in Slave controller */
785 CfgPtr = XIntc_LookupConfig(Id/32);
787 if (CfgPtr->FastIntr != TRUE) {
788 /*Fast interrupts of slave controller are not enabled*/
792 /* Get the Enabled Interrupts */
793 CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET);
795 /* Convert from integer id to bit mask */
796 Mask = XIntc_BitPosMask[(Id%32)];
798 /* Disable the Interrupt if it was enabled before calling
801 if (CurrentIER & Mask) {
802 XIntc_Disable(InstancePtr, Id);
805 XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET +
806 ((Id%32) * 4), (u32) Handler);
808 /* Slave controllers in Cascade Mode should have all as Fast
809 * interrupts or Normal interrupts, mixed interrupts are not
812 XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0xFFFFFFFF);
814 /* Enable the Interrupt if it was enabled before calling this
817 if (CurrentIER & Mask) {
818 XIntc_Enable(InstancePtr, Id);
822 /* Get the Enabled Interrupts */
823 CurrentIER = XIntc_In32(InstancePtr->BaseAddress +
825 /* Convert from integer id to bit mask */
826 Mask = XIntc_BitPosMask[Id];
828 /* Disable the Interrupt if it was enabled before calling
831 if (CurrentIER & Mask) {
832 XIntc_Disable(InstancePtr, Id);
835 XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET +
836 (Id * 4), (u32) Handler);
838 Imr = XIntc_In32(InstancePtr->BaseAddress + XIN_IMR_OFFSET);
839 XIntc_Out32(InstancePtr->BaseAddress + XIN_IMR_OFFSET,
842 /* Enable the Interrupt if it was enabled before
843 * calling this function
845 if (CurrentIER & Mask) {
846 XIntc_Enable(InstancePtr, Id);
855 /*****************************************************************************/
858 * Sets the normal interrupt mode for the specified interrupt in the Interrupt
859 * Mode Register. In Cascade mode disconnects handler from corresponding Slave
860 * controller IVAR register depending on the Id and sets all interrupt sources
861 * of the Slave controller as normal interrupts.
863 * @param InstancePtr is a pointer to the XIntc instance to be worked on.
864 * @param Id contains the ID of the interrupt source and should be in the
865 * range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being the
866 * highest priority interrupt.
871 * Slave controllers in Cascade Mode should have all as Fast
872 * interrupts or Normal interrupts, mixed interrupts are not
875 ****************************************************************************/
876 void XIntc_SetNormalIntrMode(XIntc *InstancePtr, u8 Id)
881 XIntc_Config *CfgPtr;
884 * Assert the arguments
886 Xil_AssertVoid(InstancePtr != NULL);
887 Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS);
888 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
889 Xil_AssertVoid(InstancePtr->CfgPtr->FastIntr == TRUE);
892 /* Enable user required Id in Slave controller */
893 CfgPtr = XIntc_LookupConfig(Id/32);
895 /* Get the Enabled Interrupts */
896 CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET);
898 /* Convert from integer id to bit mask */
899 Mask = XIntc_BitPosMask[(Id%32)];
901 /* Disable the Interrupt if it was enabled before calling
904 if (CurrentIER & Mask) {
905 XIntc_Disable(InstancePtr, Id);
908 /* Slave controllers in Cascade Mode should have all as Fast
909 * interrupts or Normal interrupts, mixed interrupts are not
912 XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0x0);
914 #ifdef XPAR_MICROBLAZE_BASE_VECTORS
915 for (Id = 0; Id < 32 ; Id++)
917 XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET
918 + (Id * 4), XPAR_MICROBLAZE_BASE_VECTORS
922 for (Id = 0; Id < 32 ; Id++)
924 XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET
929 /* Enable the Interrupt if it was enabled before calling this
932 if (CurrentIER & Mask) {
933 XIntc_Enable(InstancePtr, Id);
939 /* Get the Enabled Interrupts */
940 CurrentIER = XIntc_In32(InstancePtr->BaseAddress + XIN_IER_OFFSET);
941 Mask = XIntc_BitPosMask[Id];/* Convert from integer id to bit mask */
944 /* Disable the Interrupt if it was enabled before
945 * calling this function
947 if (CurrentIER & Mask) {
948 XIntc_Disable(InstancePtr, Id);
952 * Disable the selected interrupt as Fast Interrupt by reading the
953 * interrupt mode register and then modifying only the
954 * specified interrupt id
956 Imr = XIntc_In32(InstancePtr->BaseAddress + XIN_IMR_OFFSET);
957 XIntc_Out32(InstancePtr->BaseAddress + XIN_IMR_OFFSET,
960 #ifdef XPAR_MICROBLAZE_BASE_VECTORS
961 for (Id = 0; Id < 32 ; Id++)
963 XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET
964 + (Id * 4), XPAR_MICROBLAZE_BASE_VECTORS
968 for (Id = 0; Id < 32 ; Id++)
970 XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET
974 /* Enable the Interrupt if it was enabled before
975 * calling this function
977 if (CurrentIER & Mask) {
978 XIntc_Enable(InstancePtr, Id);
983 /*****************************************************************************/
986 * Initializes Slave controllers in Cascade mode. The initialization entails:
987 * - Initial vector table with stub function calls
988 * - All interrupt sources are disabled for last controller.
989 * - All interrupt sources are disabled except sources to 31 pin of
990 * primary and secondary controllers
991 * - Interrupt outputs are disabled
993 * @param InstancePtr is a pointer to the XIntc instance to be worked on.
999 ******************************************************************************/
1000 static void XIntc_InitializeSlaves(XIntc * InstancePtr)
1004 XIntc_Config *CfgPtr;
1007 Mask = XIntc_BitPosMask[31]; /* Convert from integer id to bit mask */
1009 /* Enable interrupt id with 31 for Master
1010 * interrupt controller
1012 XIntc_Out32(InstancePtr->CfgPtr->BaseAddress + XIN_IER_OFFSET, Mask);
1014 for (Index = 1; Index <= XPAR_XINTC_NUM_INSTANCES - 1; Index++) {
1015 CfgPtr = XIntc_LookupConfig(Index);
1017 XIntc_Out32(CfgPtr->BaseAddress + XIN_IAR_OFFSET,
1019 if (CfgPtr->IntcType != XIN_INTC_LAST) {
1021 /* Enable interrupt ids with 31 for secondary
1022 * interrupt controllers
1024 XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET,
1027 XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, 0x0);
1030 /* Disable Interrupt output */
1031 XIntc_Out32(CfgPtr->BaseAddress + XIN_MER_OFFSET, 0);
1033 /* Set all interrupts as normal mode if Fast Interrupts
1036 if(CfgPtr->FastIntr == TRUE) {
1037 XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0);
1039 #ifdef XPAR_MICROBLAZE_BASE_VECTORS
1040 for (Id = 0; Id < 32 ; Id++)
1042 XIntc_Out32(CfgPtr->BaseAddress +
1043 XIN_IVAR_OFFSET + (Id * 4),
1044 XPAR_MICROBLAZE_BASE_VECTORS + 0x10);
1047 for (Id = 0; Id < 32 ; Id++)
1049 XIntc_Out32(CfgPtr->BaseAddress +
1050 XIN_IVAR_OFFSET + (Id * 4), 0x10);
1056 * Initialize all the data needed to perform interrupt
1057 * processing for each interrupt ID up to the maximum used
1059 for (Id = 0; Id < CfgPtr->NumberofIntrs; Id++) {
1062 * Initalize the handler to point to a stub to handle an
1063 * interrupt which has not been connected to a handler.
1064 * Only initialize it if the handler is 0 or
1065 * XNullHandler, which means it was not initialized
1066 * statically by the tools/user.Set the callback
1067 * reference to this instance so that unhandled
1068 * interrupts can be tracked.
1070 if ((CfgPtr->HandlerTable[Id].Handler == 0) ||
1071 (CfgPtr->HandlerTable[Id].Handler ==
1073 CfgPtr->HandlerTable[Id].Handler = StubHandler;
1075 CfgPtr->HandlerTable[Id].CallBackRef = InstancePtr;