1 /*
2  * Copyright (c) 2016 - 2017, Xilinx Inc. and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /*
8  * @file	generic/xlnx/irq.c
9  * @brief	generic libmetal Xilinx irq controller definitions.
10  */
11 
12 #include <metal/errno.h>
13 #include <metal/irq_controller.h>
14 #include <metal/log.h>
15 #include <metal/mutex.h>
16 #include <metal/list.h>
17 #include <metal/alloc.h>
18 #include <metal/sys.h>
19 #include <metal/system/generic/xlnx/sys.h>
20 
21 #ifdef __MICROBLAZE__
22 #define MAX_IRQS 32
23 #else
24 #define MAX_IRQS XLNX_MAXIRQS
25 #endif
26 
27 static struct metal_irq irqs[MAX_IRQS]; /**< Linux IRQs array */
28 
metal_xlnx_irq_set_enable(struct metal_irq_controller * irq_cntr,int irq,unsigned int state)29 static void metal_xlnx_irq_set_enable(struct metal_irq_controller *irq_cntr,
30 				      int irq, unsigned int state)
31 {
32 	if (irq < irq_cntr->irq_base ||
33 	    irq >= irq_cntr->irq_base + irq_cntr->irq_num) {
34 		metal_log(METAL_LOG_ERROR, "%s: invalid irq %d\n",
35 			  __func__, irq);
36 		return;
37 	} else if (state == METAL_IRQ_ENABLE) {
38 		sys_irq_enable((unsigned int)irq);
39 	} else {
40 		sys_irq_disable((unsigned int)irq);
41 	}
42 }
43 
44 /**< Xilinx common platform IRQ controller */
45 static METAL_IRQ_CONTROLLER_DECLARE(xlnx_irq_cntr,
46 				    0, MAX_IRQS,
47 				    NULL,
48 				    metal_xlnx_irq_set_enable, NULL,
49 				    irqs);
50 
51 /**
52  * @brief default handler
53  */
metal_xlnx_irq_isr(void * arg)54 void metal_xlnx_irq_isr(void *arg)
55 {
56 	unsigned int vector;
57 
58 	vector = (uintptr_t)arg;
59 	if (vector >= MAX_IRQS) {
60 		return;
61 	}
62 	(void)metal_irq_handle(&irqs[vector], (int)vector);
63 }
64 
metal_xlnx_irq_init(void)65 int metal_xlnx_irq_init(void)
66 {
67 	int ret;
68 
69 	ret =  metal_irq_register_controller(&xlnx_irq_cntr);
70 	if (ret < 0) {
71 		metal_log(METAL_LOG_ERROR, "%s: register irq controller failed.\n",
72 			  __func__);
73 		return ret;
74 	}
75 	return 0;
76 }
77