summaryrefslogtreecommitdiffstats
path: root/bsps/include/grlib/genirq.h
blob: 3c99b5a7044288db89829c8ff7b7cb22cb54fa46 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/* SPDX-License-Identifier: BSD-2-Clause */

/* General Shared Interrupt handling function interface 
 *
 * The functions does not manipulate the IRQ controller or the 
 * interrupt level of the CPU. It simply helps the caller with
 * managing shared interrupts where multiple interrupt routines
 * share on interrupt vector/number.
 *
 * COPYRIGHT (c) 2008.
 * Cobham Gaisler AB.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __GENIRQ_H__
#define __GENIRQ_H__

#ifdef __cplusplus
extern "C" {
#endif

typedef void (*genirq_handler)(void *arg);
typedef void* genirq_t;

struct genirq_stats {
	unsigned int	irq_cnt;
};

/* Initialize the genirq interface. Must be the first function
 * called.
 *
 * Returns zero on success, otherwise failure.
 */
extern genirq_t genirq_init(int number_of_irqs);

/* Free the dynamically allocated memory that the genirq interface has 
 * allocated. Also the handlers will be freed.
 *
 * Returns zero on success, otherwise failure.
 */
extern void genirq_destroy(genirq_t d);

/* Check IRQ number validity 
 * 
 * Returns zero for valid IRQ numbers, -1 of invalid IRQ numbers.
 */
extern int genirq_check(genirq_t d, int irq);

/* Allocate one ISR handler and initialize it. Input to genirq_register().
 *
 * \param isr    The interrupt service routine called upon IRQ
 * \param arg    The argument given to isr() when called.
 *
 * Returns a pointer on success, on failure NULL is returned.
 */
extern void *genirq_alloc_handler(genirq_handler isr, void *arg);

/* Free handler memory */
#define genirq_free_handler(handler) free(handler)

/* Register shared interrupt handler previously initialized with
 * genirq_alloc_handler().
 *
 * NOTE: internal list structures are accessed and needs to be protected by
 *       spin-locks/IRQ disable by the user to guarantee a correct behaviour.
 *
 * \param irq    The interrupt number to register ISR on
 * \param handler Install the pre- allocated and initialized handler.
 *
 * Return Values
 * -1  = Failed
 * 0   = Handler registered Successfully, first handler on this IRQ
 * 1   = Handler registered Successfully, _not_ first handler on this IRQ
 */
extern int genirq_register(genirq_t d, int irq, void *handler);

/* Unregister an previous registered interrupt handler. It is the user's
 * responsibility to free the handler returned by genirq_unregister().
 *
 * NOTE: internal list structures are accessed and needs to be protected by
 *       spin-locks/IRQ disable by the user to guarantee a correct behaviour.
 *
 * Return Values
 * NULL    = ISR not registered before or unable to unregister enabled ISR
 * Pointer = ISR sucessfully unregistered. Returned is the handler pointer
 *           previously allocated with genirq_alloc_handler().
 */
extern void *genirq_unregister(genirq_t d, int irq,
				genirq_handler isr, void *arg);

/* Enables IRQ only for this isr[arg] combination. Records if this 
 * is the first interrupt enable, only then must interrupts be enabled
 * on the interrupt controller.
 *
 * NOTE: internal list structures are accessed and needs to be protected by
 *       spin-locks/IRQ disable by the user to guarantee a correct behaviour.
 *
 * Return values
 *  -1 = Failure, for example isr[arg] not registered on this irq
 *  0  = IRQ must be enabled, it is the first IRQ handler to be enabled
 *  1  = IRQ has already been enabled, either by isr[arg] or by another handler
 */
extern int genirq_enable(genirq_t d, int irq, genirq_handler isr, void *arg);

/* Disables IRQ only for this isr[arg] combination. Records if this 
 * is the only interrupt handler that is enabled on this IRQ, only then
 * must interrupts be disabled on the interrupt controller.
 *
 * NOTE: internal list structures are accessed and needs to be protected by
 *       spin-locks/IRQ disable by the user to guarantee a correct behaviour.
 *
 * Return values
 *  -1 = Failure, for example isr[arg] not registered on this irq
 *  0  = IRQ must be disabled, no ISR are enabled for this IRQ
 *  1  = ISR has already been disabled, or other ISRs are still enabled
 */
extern int genirq_disable(genirq_t d, int irq, genirq_handler isr, void *arg);

/* Must be called by user when an IRQ has fired, the argument 'irq' 
 * is the IRQ number of the IRQ which was fired.
 *
 * NOTE: internal list structures are accessed and needs to be protected by
 *       spin-locks/IRQ disable by the user to guarantee a correct behaviour.
 */
extern void genirq_doirq(genirq_t d, int irq);

#ifdef __cplusplus
}
#endif

#endif