]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/BSP/microblaze_0/libsrc/intc_v3_2/src/xintc.c
a6d1b7872987b7add382dbb86b4be5e8b025f7be
[freertos] / FreeRTOS / Demo / MicroBlaze_Kintex7_EthernetLite / BSP / microblaze_0 / libsrc / intc_v3_2 / src / xintc.c
1 /******************************************************************************
2 *
3 * Copyright (C) 2002 - 2014 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 xintc.c
36 *
37 * Contains required functions for the XIntc driver for the Xilinx Interrupt
38 * Controller. See xintc.h for a detailed description of the driver.
39 *
40 * <pre>
41 * MODIFICATION HISTORY:
42 *
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
59 *                     interrupt mode.
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
71 *                     CR#765931
72 *
73 * </pre>
74 *
75 ******************************************************************************/
76
77 /***************************** Include Files *********************************/
78
79 #include "xil_types.h"
80 #include "xil_assert.h"
81 #include "xintc.h"
82 #include "xintc_l.h"
83 #include "xintc_i.h"
84
85 /************************** Constant Definitions *****************************/
86
87
88 /**************************** Type Definitions *******************************/
89
90
91 /***************** Macros (Inline Functions) Definitions *********************/
92
93
94 /************************** Variable Definitions *****************************/
95
96 /*
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
101  */
102 u32 XIntc_BitPosMask[XIN_CONTROLLER_MAX_INTRS];
103
104 /************************** Function Prototypes ******************************/
105
106 static void StubHandler(void *CallBackRef);
107 static void XIntc_InitializeSlaves(XIntc * InstancePtr);
108
109 /*****************************************************************************/
110 /**
111 *
112 * Initialize a specific interrupt controller instance/driver. The
113 * initialization entails:
114 *
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
119 *
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.
125 *
126 * @return
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.
131 *
132 * @note         In Cascade mode this function calls XIntc_InitializeSlaves to
133 *               initialiaze Slave Interrupt controllers.
134 *
135 ******************************************************************************/
136 int XIntc_Initialize(XIntc * InstancePtr, u16 DeviceId)
137 {
138         u8 Id;
139         XIntc_Config *CfgPtr;
140         u32 NextBitMask = 1;
141
142         Xil_AssertNonvoid(InstancePtr != NULL);
143
144         /*
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
148          */
149         if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) {
150                 return XST_DEVICE_IS_STARTED;
151         }
152
153         /*
154          * Lookup the device configuration in the CROM table. Use this
155          * configuration info down below when initializing this component.
156          */
157         CfgPtr = XIntc_LookupConfig(DeviceId);
158         if (CfgPtr == NULL) {
159                 return XST_DEVICE_NOT_FOUND;
160         }
161
162         /*
163          * Set some default values
164          */
165         InstancePtr->IsReady = 0;
166         InstancePtr->IsStarted = 0;     /* not started */
167         InstancePtr->CfgPtr = CfgPtr;
168
169         InstancePtr->CfgPtr->Options = XIN_SVC_SGL_ISR_OPTION;
170         InstancePtr->CfgPtr->IntcType = CfgPtr->IntcType;
171
172         /*
173          * Save the base address pointer such that the registers of the
174          * interrupt can be accessed
175          */
176 #if (XPAR_XINTC_USE_DCR_BRIDGE != 0)
177         InstancePtr->BaseAddress = ((CfgPtr->BaseAddress >> 2)) & 0xFFF;
178 #else
179         InstancePtr->BaseAddress = CfgPtr->BaseAddress;
180 #endif
181
182         /*
183          * Initialize all the data needed to perform interrupt processing for
184          * each interrupt ID up to the maximum used
185          */
186         for (Id = 0; Id < CfgPtr->NumberofIntrs; Id++) {
187
188                 /*
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.
195                  */
196                 if ((InstancePtr->CfgPtr->HandlerTable[Id].Handler == 0) ||
197                     (InstancePtr->CfgPtr->HandlerTable[Id].Handler ==
198                      XNullHandler)) {
199                         InstancePtr->CfgPtr->HandlerTable[Id].Handler =
200                                 StubHandler;
201                 }
202                 InstancePtr->CfgPtr->HandlerTable[Id].CallBackRef = InstancePtr;
203
204                 /*
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, ... })
209                  */
210                 XIntc_BitPosMask[Id] = NextBitMask;
211                 NextBitMask *= 2;
212         }
213
214         /*
215          * Disable IRQ output signal
216          * Disable all interrupt sources
217          * Acknowledge all sources
218          */
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);
222
223         /*
224          * If the fast Interrupt mode is enabled then set all the
225          * interrupts as normal mode.
226          */
227         if(InstancePtr->CfgPtr->FastIntr == TRUE) {
228                 XIntc_Out32(InstancePtr->BaseAddress + XIN_IMR_OFFSET, 0);
229
230 #ifdef XPAR_MICROBLAZE_BASE_VECTORS
231                 for (Id = 0; Id < 32 ; Id++)
232                 {
233                         XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET
234                                 + (Id * 4), XPAR_MICROBLAZE_BASE_VECTORS
235                                 + 0x10);
236                 }
237 #else
238                 for (Id = 0; Id < 32 ; Id++)
239                 {
240                         XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET
241                                                         + (Id * 4), 0x10);
242                 }
243 #endif
244         }
245
246         /* Initialize slaves in Cascade mode*/
247         if (InstancePtr->CfgPtr->IntcType != XIN_INTC_NOCASCADE) {
248                 XIntc_InitializeSlaves(InstancePtr);
249         }
250
251         /*
252          * Indicate the instance is now ready to use, successfully initialized
253          */
254         InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
255
256         return XST_SUCCESS;
257 }
258
259 /*****************************************************************************/
260 /**
261 *
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.
265 *
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.
269 *
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.
276 *
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
280 *
281 * @return
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.
285 *
286 * @note         Must be called after XIntc initialization is completed.
287 *
288 ******************************************************************************/
289 int XIntc_Start(XIntc * InstancePtr, u8 Mode)
290 {
291         u32 MasterEnable = XIN_INT_MASTER_ENABLE_MASK;
292         XIntc_Config *CfgPtr;
293         int Index;
294
295         /*
296          * Assert the arguments
297          */
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);
302
303         /*
304          * Check for simulation mode
305          */
306         if (Mode == XIN_SIMULATION_MODE) {
307                 if (MasterEnable & XIN_INT_HARDWARE_ENABLE_MASK) {
308                         return XST_FAILURE;
309                 }
310         }
311         else {
312                 MasterEnable |= XIN_INT_HARDWARE_ENABLE_MASK;
313         }
314
315         /*
316          * Indicate the instance is ready to be used and is started before we
317          * enable the device.
318          */
319         InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED;
320
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++)
324                 {
325                         CfgPtr = XIntc_LookupConfig(Index);
326                         XIntc_Out32(CfgPtr->BaseAddress + XIN_MER_OFFSET,
327                                         MasterEnable);
328                 }
329         }
330
331         /* Start the master */
332         XIntc_Out32(InstancePtr->BaseAddress + XIN_MER_OFFSET, MasterEnable);
333
334         return XST_SUCCESS;
335 }
336
337 /*****************************************************************************/
338 /**
339 *
340 * Stops the interrupt controller by disabling the output from the controller
341 * so that no interrupts will be caused by the interrupt controller.
342 *
343 * @param        InstancePtr is a pointer to the XIntc instance to be worked on.
344 *
345 * @return       None.
346 *
347 * @note         None.
348 *
349 ******************************************************************************/
350 void XIntc_Stop(XIntc * InstancePtr)
351 {
352         /*
353          * Assert the arguments
354          */
355         Xil_AssertVoid(InstancePtr != NULL);
356         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
357
358         /*
359          * Stop all interrupts from occurring thru the interrupt controller by
360          * disabling all interrupts in the MER register
361          */
362         XIntc_Out32(InstancePtr->BaseAddress + XIN_MER_OFFSET, 0);
363
364         InstancePtr->IsStarted = 0;
365 }
366
367 /*****************************************************************************/
368 /**
369 *
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.
375 *
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.
383 *
384 * @return
385 *
386 *               - XST_SUCCESS if the handler was connected correctly.
387 *
388 * @note
389 *
390 * WARNING: The handler provided as an argument will overwrite any handler
391 * that was previously connected.
392 *
393 ****************************************************************************/
394 int XIntc_Connect(XIntc * InstancePtr, u8 Id,
395                   XInterruptHandler Handler, void *CallBackRef)
396 {
397         XIntc_Config *CfgPtr;
398         /*
399          * Assert the arguments
400          */
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);
405
406         /* Connect Handlers for Slave controllers in Cascade Mode */
407         if (Id > 31) {
408
409                 CfgPtr = XIntc_LookupConfig(Id/32);
410
411                 CfgPtr->HandlerTable[Id%32].Handler = Handler;
412                 CfgPtr->HandlerTable[Id%32].CallBackRef = CallBackRef;
413         }
414         /* Connect Handlers for Master/primary controller */
415         else {
416                 /*
417                  * The Id is used as an index into the table to select the
418                  * proper handler
419                  */
420                 InstancePtr->CfgPtr->HandlerTable[Id].Handler = Handler;
421                 InstancePtr->CfgPtr->HandlerTable[Id].CallBackRef =
422                                                                 CallBackRef;
423         }
424
425         return XST_SUCCESS;
426 }
427
428 /*****************************************************************************/
429 /**
430 *
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
435 * interrupt Id.
436 *
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.
441 *
442 * @return       None.
443 *
444 * @note         None.
445 *
446 ****************************************************************************/
447 void XIntc_Disconnect(XIntc * InstancePtr, u8 Id)
448 {
449         u32 CurrentIER;
450         u32 Mask;
451         XIntc_Config *CfgPtr;
452
453         /*
454          * Assert the arguments
455          */
456         Xil_AssertVoid(InstancePtr != NULL);
457         Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS);
458         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
459
460         /*
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
464          */
465
466         /* Disconnect Handlers for Slave controllers in Cascade Mode */
467         if (Id > 31) {
468
469                 CfgPtr = XIntc_LookupConfig(Id/32);
470
471                 CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET);
472
473                 /* Convert from integer id to bit mask */
474                 Mask = XIntc_BitPosMask[(Id%32)];
475
476                 XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET,
477                                         (CurrentIER & ~Mask));
478                 /*
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
482                  */
483                 CfgPtr->HandlerTable[Id%32].Handler = StubHandler;
484                 CfgPtr->HandlerTable[Id%32].CallBackRef = InstancePtr;
485         }
486         /* Disconnect Handlers for Master/primary controller */
487         else {
488                 CurrentIER = XIntc_In32(InstancePtr->BaseAddress +
489                                                         XIN_IER_OFFSET);
490
491                 /* Convert from integer id to bit mask */
492                 Mask = XIntc_BitPosMask[Id];
493
494                 XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET,
495                                         (CurrentIER & ~Mask));
496                 InstancePtr->CfgPtr->HandlerTable[Id%32].Handler =
497                                                                 StubHandler;
498                 InstancePtr->CfgPtr->HandlerTable[Id%32].CallBackRef =
499                                                                 InstancePtr;
500         }
501
502 }
503
504 /*****************************************************************************/
505 /**
506 *
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.
511 *
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.
516 *
517 * @return       None.
518 *
519 * @note         None.
520 *
521 ****************************************************************************/
522 void XIntc_Enable(XIntc * InstancePtr, u8 Id)
523 {
524         u32 CurrentIER;
525         u32 Mask;
526         XIntc_Config *CfgPtr;
527
528         /*
529          * Assert the arguments
530          */
531         Xil_AssertVoid(InstancePtr != NULL);
532         Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS);
533         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
534
535         if (Id > 31) {
536
537                 /* Enable user required Id in Slave controller */
538                 CfgPtr = XIntc_LookupConfig(Id/32);
539
540                 CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET);
541
542                 /* Convert from integer id to bit mask */
543                 Mask = XIntc_BitPosMask[(Id%32)];
544
545                 XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET,
546                                                 (CurrentIER | Mask));
547         }
548         else {
549                 /*
550                  * The Id is used to create the appropriate mask for the
551                  * desired bit position.
552                  */
553                 Mask = XIntc_BitPosMask[Id];
554
555                 /*
556                  * Enable the selected interrupt source by reading the
557                  * interrupt enable register and then modifying only the
558                  * specified interrupt id enable
559                  */
560                 CurrentIER = XIntc_In32(InstancePtr->BaseAddress +
561                                                         XIN_IER_OFFSET);
562                 XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET,
563                     (CurrentIER | Mask));
564         }
565 }
566
567 /*****************************************************************************/
568 /**
569 *
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.
575 *
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.
580 *
581 * @return       None.
582 *
583 * @note         None.
584 *
585 ****************************************************************************/
586 void XIntc_Disable(XIntc * InstancePtr, u8 Id)
587 {
588         u32 CurrentIER;
589         u32 Mask;
590         XIntc_Config *CfgPtr;
591
592         /*
593          * Assert the arguments
594          */
595         Xil_AssertVoid(InstancePtr != NULL);
596         Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS);
597         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
598
599         if (Id > 31) {
600                 /* Enable user required Id in Slave controller */
601                 CfgPtr = XIntc_LookupConfig(Id/32);
602
603                 CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET);
604
605                 /* Convert from integer id to bit mask */
606                 Mask = XIntc_BitPosMask[(Id%32)];
607
608                 XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET,
609                                                         (CurrentIER & ~Mask));
610         } else {
611                 /*
612                  * The Id is used to create the appropriate mask for the
613                  * desired bit position. Id currently limited to 0 - 31
614                  */
615                 Mask = XIntc_BitPosMask[Id];
616
617                 /*
618                  * Disable the selected interrupt source by reading the
619                  * interrupt enable register and then modifying only the
620                  * specified interrupt id
621                  */
622                 CurrentIER = XIntc_In32(InstancePtr->BaseAddress +
623                                                         XIN_IER_OFFSET);
624                 XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET,
625                                                         (CurrentIER & ~Mask));
626         }
627 }
628
629 /*****************************************************************************/
630 /**
631 *
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.
636 *
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.
641 *
642 * @return       None.
643 *
644 * @note         None.
645 *
646 ****************************************************************************/
647 void XIntc_Acknowledge(XIntc * InstancePtr, u8 Id)
648 {
649         u32 Mask;
650         XIntc_Config *CfgPtr;
651
652         /*
653          * Assert the arguments
654          */
655         Xil_AssertVoid(InstancePtr != NULL);
656         Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS);
657         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
658
659         if (Id > 31) {
660                 /* Enable user required Id in Slave controller */
661                 CfgPtr = XIntc_LookupConfig(Id/32);
662
663                 /* Convert from integer id to bit mask */
664                 Mask = XIntc_BitPosMask[(Id%32)];
665
666                 XIntc_Out32(CfgPtr->BaseAddress + XIN_IAR_OFFSET, Mask);
667         } else {
668                 /*
669                  * The Id is used to create the appropriate mask for the
670                  * desired bit position.
671                  */
672                 Mask = XIntc_BitPosMask[Id];
673
674                 /*
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
678                  */
679                 XIntc_Out32(InstancePtr->BaseAddress + XIN_IAR_OFFSET, Mask);
680         }
681 }
682
683 /*****************************************************************************/
684 /**
685 *
686 * A stub for the asynchronous callback. The stub is here in case the upper
687 * layers forget to set the handler.
688 *
689 * @param        CallBackRef is a pointer to the upper layer callback reference
690 *
691 * @return       None.
692 *
693 * @note         None.
694 *
695 ******************************************************************************/
696 static void StubHandler(void *CallBackRef)
697 {
698         /*
699          * Verify that the inputs are valid
700          */
701         Xil_AssertVoid(CallBackRef != NULL);
702
703         /*
704          * Indicate another unhandled interrupt for stats
705          */
706         ((XIntc *) CallBackRef)->UnhandledInterrupts++;
707 }
708
709 /*****************************************************************************/
710 /**
711 *
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.
714 *
715 * @param        DeviceId is the unique identifier for a device.
716 *
717 * @return       A pointer to the XIntc configuration structure for the specified
718 *               device, or NULL if the device was not found.
719 *
720 * @note         None.
721 *
722 ******************************************************************************/
723 XIntc_Config *XIntc_LookupConfig(u16 DeviceId)
724 {
725         XIntc_Config *CfgPtr = NULL;
726         int Index;
727
728         for (Index = 0; Index < XPAR_XINTC_NUM_INSTANCES; Index++) {
729                 if (XIntc_ConfigTable[Index].DeviceId == DeviceId) {
730                         CfgPtr = &XIntc_ConfigTable[Index];
731                         break;
732                 }
733         }
734
735         return CfgPtr;
736 }
737
738 /*****************************************************************************/
739 /**
740 *
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
745 * fast interrupts.
746 *
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.
752 *
753 * @return
754 *               - XST_SUCCESS
755 *
756 * @note
757 *               Slave controllers in Cascade Mode should have all as Fast
758 *               interrupts or Normal interrupts, mixed interrupts are not
759 *               supported
760 *
761 * WARNING: The handler provided as an argument will overwrite any handler
762 * that was previously connected.
763 *
764 ****************************************************************************/
765 int XIntc_ConnectFastHandler(XIntc *InstancePtr, u8 Id,
766                                 XFastInterruptHandler Handler)
767 {
768         u32 Imr;
769         u32 CurrentIER;
770         u32 Mask;
771         XIntc_Config *CfgPtr;
772
773         /*
774          * Assert the arguments
775          */
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);
781
782
783         if (Id > 31) {
784                 /* Enable user required Id in Slave controller */
785                 CfgPtr = XIntc_LookupConfig(Id/32);
786
787                 if (CfgPtr->FastIntr != TRUE) {
788                         /*Fast interrupts of slave controller are not enabled*/
789                         return XST_FAILURE;
790                 }
791
792                 /* Get the Enabled Interrupts */
793                 CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET);
794
795                 /* Convert from integer id to bit mask */
796                 Mask = XIntc_BitPosMask[(Id%32)];
797
798                 /* Disable the Interrupt if it was enabled before calling
799                  * this function
800                  */
801                 if (CurrentIER & Mask) {
802                         XIntc_Disable(InstancePtr, Id);
803                 }
804
805                 XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET +
806                                 ((Id%32) * 4), (u32) Handler);
807
808                 /* Slave controllers in Cascade Mode should have all as Fast
809                  * interrupts or Normal interrupts, mixed interrupts are not
810                  * supported
811                  */
812                 XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0xFFFFFFFF);
813
814                 /* Enable the Interrupt if it was enabled before calling this
815                  * function
816                  */
817                 if (CurrentIER & Mask) {
818                         XIntc_Enable(InstancePtr, Id);
819                 }
820         }
821         else {
822                 /* Get the Enabled Interrupts */
823                 CurrentIER = XIntc_In32(InstancePtr->BaseAddress +
824                                                          XIN_IER_OFFSET);
825                 /* Convert from integer id to bit mask */
826                 Mask = XIntc_BitPosMask[Id];
827
828                 /* Disable the Interrupt if it was enabled before calling
829                  * this function
830                  */
831                 if (CurrentIER & Mask) {
832                         XIntc_Disable(InstancePtr, Id);
833                 }
834
835                 XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET +
836                                          (Id * 4), (u32) Handler);
837
838                 Imr = XIntc_In32(InstancePtr->BaseAddress + XIN_IMR_OFFSET);
839                 XIntc_Out32(InstancePtr->BaseAddress + XIN_IMR_OFFSET,
840                                                         Imr | Mask);
841
842                 /* Enable the Interrupt if it was enabled before
843                  * calling this function
844                  */
845                 if (CurrentIER & Mask) {
846                         XIntc_Enable(InstancePtr, Id);
847                 }
848
849         }
850
851         return XST_SUCCESS;
852 }
853
854
855 /*****************************************************************************/
856 /**
857 *
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.
862 *
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.
867 *
868 * @return       None.
869 *
870 * @note
871 *               Slave controllers in Cascade Mode should have all as Fast
872 *               interrupts or Normal interrupts, mixed interrupts are not
873 *               supported
874 *
875 ****************************************************************************/
876 void XIntc_SetNormalIntrMode(XIntc *InstancePtr, u8 Id)
877 {
878         u32 Imr;
879         u32 CurrentIER;
880         u32 Mask;
881         XIntc_Config *CfgPtr;
882
883         /*
884          * Assert the arguments
885          */
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);
890
891         if (Id > 31) {
892                 /* Enable user required Id in Slave controller */
893                 CfgPtr = XIntc_LookupConfig(Id/32);
894
895                 /* Get the Enabled Interrupts */
896                 CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET);
897
898                 /* Convert from integer id to bit mask */
899                 Mask = XIntc_BitPosMask[(Id%32)];
900
901                 /* Disable the Interrupt if it was enabled before calling
902                  * this function
903                  */
904                 if (CurrentIER & Mask) {
905                         XIntc_Disable(InstancePtr, Id);
906                 }
907
908                 /* Slave controllers in Cascade Mode should have all as Fast
909                  * interrupts or Normal interrupts, mixed interrupts are not
910                  * supported
911                  */
912                 XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0x0);
913
914 #ifdef XPAR_MICROBLAZE_BASE_VECTORS
915                 for (Id = 0; Id < 32 ; Id++)
916                 {
917                         XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET
918                                 + (Id * 4), XPAR_MICROBLAZE_BASE_VECTORS
919                                 + 0x10);
920                 }
921 #else
922                 for (Id = 0; Id < 32 ; Id++)
923                 {
924                         XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET
925                                                         + (Id * 4), 0x10);
926                 }
927 #endif
928
929                 /* Enable the Interrupt if it was enabled before calling this
930                  * function
931                  */
932                 if (CurrentIER & Mask) {
933                         XIntc_Enable(InstancePtr, Id);
934                 }
935
936         }
937         else {
938
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 */
942
943
944                 /* Disable the Interrupt if it was enabled before
945                  * calling this function
946                  */
947                 if (CurrentIER & Mask) {
948                         XIntc_Disable(InstancePtr, Id);
949                 }
950
951                 /*
952                  * Disable the selected interrupt as Fast Interrupt by reading the
953                  * interrupt mode register and then modifying only the
954                  * specified interrupt id
955                  */
956                 Imr = XIntc_In32(InstancePtr->BaseAddress + XIN_IMR_OFFSET);
957                 XIntc_Out32(InstancePtr->BaseAddress + XIN_IMR_OFFSET,
958                                                     Imr & ~Mask);
959
960 #ifdef XPAR_MICROBLAZE_BASE_VECTORS
961                 for (Id = 0; Id < 32 ; Id++)
962                 {
963                         XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET
964                                 + (Id * 4), XPAR_MICROBLAZE_BASE_VECTORS
965                                 + 0x10);
966                 }
967 #else
968                 for (Id = 0; Id < 32 ; Id++)
969                 {
970                         XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET
971                                                         + (Id * 4), 0x10);
972                 }
973 #endif
974                 /* Enable the Interrupt if it was enabled before
975                  * calling this function
976                  */
977                 if (CurrentIER & Mask) {
978                         XIntc_Enable(InstancePtr, Id);
979                 }
980         }
981 }
982
983 /*****************************************************************************/
984 /**
985 *
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
992 *
993 * @param        InstancePtr is a pointer to the XIntc instance to be worked on.
994 *
995 * @return       None
996 *
997 * @note         None.
998 *
999 ******************************************************************************/
1000 static void XIntc_InitializeSlaves(XIntc * InstancePtr)
1001 {
1002         int Index;
1003         u32 Mask;
1004         XIntc_Config *CfgPtr;
1005         int Id;
1006
1007         Mask = XIntc_BitPosMask[31]; /* Convert from integer id to bit mask */
1008
1009         /* Enable interrupt id with 31 for Master
1010          * interrupt controller
1011          */
1012         XIntc_Out32(InstancePtr->CfgPtr->BaseAddress + XIN_IER_OFFSET, Mask);
1013
1014         for (Index = 1; Index <= XPAR_XINTC_NUM_INSTANCES - 1; Index++) {
1015                 CfgPtr = XIntc_LookupConfig(Index);
1016
1017                 XIntc_Out32(CfgPtr->BaseAddress + XIN_IAR_OFFSET,
1018                                                         0xFFFFFFFF);
1019                 if (CfgPtr->IntcType != XIN_INTC_LAST) {
1020
1021                         /* Enable interrupt ids with 31 for secondary
1022                          * interrupt controllers
1023                          */
1024                         XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET,
1025                                                                         Mask);
1026                 } else {
1027                         XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, 0x0);
1028                 }
1029
1030                 /* Disable Interrupt output */
1031                 XIntc_Out32(CfgPtr->BaseAddress + XIN_MER_OFFSET, 0);
1032
1033                 /* Set all interrupts as normal mode if Fast Interrupts
1034                  * are enabled
1035                  */
1036                 if(CfgPtr->FastIntr == TRUE) {
1037                         XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0);
1038
1039 #ifdef XPAR_MICROBLAZE_BASE_VECTORS
1040                         for (Id = 0; Id < 32 ; Id++)
1041                         {
1042                                 XIntc_Out32(CfgPtr->BaseAddress +
1043                                         XIN_IVAR_OFFSET + (Id * 4),
1044                                         XPAR_MICROBLAZE_BASE_VECTORS + 0x10);
1045                         }
1046 #else
1047                         for (Id = 0; Id < 32 ; Id++)
1048                         {
1049                                 XIntc_Out32(CfgPtr->BaseAddress +
1050                                         XIN_IVAR_OFFSET + (Id * 4), 0x10);
1051                         }
1052 #endif
1053                 }
1054
1055                 /*
1056                  * Initialize all the data needed to perform interrupt
1057                  * processing for each interrupt ID up to the maximum used
1058                  */
1059                 for (Id = 0; Id < CfgPtr->NumberofIntrs; Id++) {
1060
1061                         /*
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.
1069                          */
1070                         if ((CfgPtr->HandlerTable[Id].Handler == 0) ||
1071                                     (CfgPtr->HandlerTable[Id].Handler ==
1072                                      XNullHandler)) {
1073                                 CfgPtr->HandlerTable[Id].Handler = StubHandler;
1074                         }
1075                         CfgPtr->HandlerTable[Id].CallBackRef = InstancePtr;
1076                 }
1077         }
1078 }