1 /*
2 * Copyright (c) 2018, Pinecone Inc. and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /*
8 * @file nuttx/irq.c
9 * @brief NuttX libmetal irq definitions.
10 */
11
12 #include <metal/errno.h>
13 #include <metal/irq_controller.h>
14 #include <metal/alloc.h>
15 #include <nuttx/arch.h>
16 #include <nuttx/irq.h>
17
metal_irq_save_disable(void)18 unsigned int metal_irq_save_disable(void)
19 {
20 return up_irq_save();
21 }
22
metal_irq_restore_enable(unsigned int flags)23 void metal_irq_restore_enable(unsigned int flags)
24 {
25 up_irq_restore(flags);
26 }
27
28 /* Implement the default irq controller */
metal_cntr_irq_set_enable(struct metal_irq_controller * cntr,int irq,unsigned int enable)29 static void metal_cntr_irq_set_enable(struct metal_irq_controller *cntr,
30 int irq, unsigned int enable)
31 {
32 #ifndef CONFIG_ARCH_NOINTC
33 if (irq >= 0 && irq < cntr->irq_num) {
34 if (enable == METAL_IRQ_ENABLE)
35 up_enable_irq(irq);
36 else
37 up_disable_irq(irq);
38 }
39 #endif
40 }
41
metal_cntr_irq_handler(int irq,void * context,void * data)42 static int metal_cntr_irq_handler(int irq, void *context, void *data)
43 {
44 if (context != NULL)
45 return metal_irq_handle(data, irq);
46
47 /* context == NULL mean unregister */
48 irqchain_detach(irq, metal_cntr_irq_handler, data);
49 metal_free_memory(data);
50 return 0;
51 }
52
metal_cntr_irq_attach(struct metal_irq_controller * cntr,int irq,metal_irq_handler hd,void * arg)53 static int metal_cntr_irq_attach(struct metal_irq_controller *cntr,
54 int irq, metal_irq_handler hd, void *arg)
55 {
56 if (irq < 0 || irq >= cntr->irq_num)
57 return -EINVAL;
58
59 if (hd) {
60 struct metal_irq *data;
61
62 data = metal_allocate_memory(sizeof(*data));
63 if (data == NULL)
64 return -ENOMEM;
65
66 data->hd = hd;
67 data->arg = arg;
68
69 irq_attach(irq, metal_cntr_irq_handler, data);
70 } else {
71 unsigned int flags;
72
73 flags = metal_irq_save_disable();
74 irq_dispatch(irq, NULL); /* fake a irq request */
75 metal_irq_restore_enable(flags);
76 }
77
78 return 0;
79 }
80
metal_cntr_irq_init(void)81 int metal_cntr_irq_init(void)
82 {
83 static METAL_IRQ_CONTROLLER_DECLARE(metal_cntr_irq,
84 0,
85 NR_IRQS ? NR_IRQS : 1,
86 NULL,
87 metal_cntr_irq_set_enable,
88 metal_cntr_irq_attach,
89 NULL);
90 return metal_irq_register_controller(&metal_cntr_irq);
91 }
92