Skip to content

Commit 2b67405

Browse files
committed
drivers: shared_irq: add devicetree helper macros
This commit adds helper macros to reduce boilerplate code in drivers that (conditionally) use the shared irq driver. Signed-off-by: Thomas Stranger <[email protected]>
1 parent 3656ba5 commit 2b67405

File tree

1 file changed

+363
-0
lines changed

1 file changed

+363
-0
lines changed

include/shared_irq.h

Lines changed: 363 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
/*
44
* Copyright (c) 2015 Intel corporation
5+
* Copyright (c) 2021 Thomas Stranger
56
*
67
* SPDX-License-Identifier: Apache-2.0
78
*/
@@ -15,6 +16,368 @@
1516
extern "C" {
1617
#endif
1718

19+
/**
20+
* @brief Get a node identifier for a shared-irqs specifier at the index
21+
*
22+
* @param node_id Node identifier of a device that has a shared-irqs
23+
* phandle-array property.
24+
* @param irq_idx logical index into the shared-irqs phandle-array
25+
* @return node identifier for the shared-irq node at that index
26+
*/
27+
#define SHARED_IRQ_BY_IDX(node_id, irq_idx) \
28+
DT_PHANDLE_BY_IDX(node_id, shared_irqs, irq_idx); \
29+
30+
/**
31+
* @brief Get a node identifier within a shared-irqs specifier by name
32+
*
33+
* This can be used to get an individual shared-irq when a device generates more
34+
* than one, provided that the bindings give each shared-irq specifier a name.
35+
*
36+
* @param node_id Node identifier of a device that has a shared-irqs
37+
* phandle-array property.
38+
* @param irq_name lowercase-and-underscores shared interrupt specifier name
39+
* @return node identifier for the shared-irq identified by given by the name
40+
*/
41+
#define SHARED_IRQ_BY_NAME(node_id, irq_name) \
42+
DT_PHANDLE_BY_NAME(node_id, shared_irqs, irq_name) \
43+
44+
/**
45+
* @brief Does the node have a shared-irqs element at index?
46+
*
47+
* @param node_id Node identifier of a device which may have a shared-irqs
48+
* phandle-array element at index.
49+
* @param irq_idx logical index into the shared-irqs phandle-array
50+
* @return 1 if the shared-irqs property has an element at index, 0 otherwise
51+
*/
52+
#define SHARED_IRQ_HAS_IDX(node_id, irq_idx) \
53+
DT_PROP_HAS_IDX(node_id, shared_irqs, irq_idx) \
54+
55+
/**
56+
* @brief Does the node have a shared-irqs element with a matching name?
57+
*
58+
* @param node_id Node identifier of a device which may have a shared-irqs
59+
* phandle-array element with the given name.
60+
* @param irq_name lowercase-and-underscores name of a shared-irqs element
61+
* as defined by the node's shared-irq-names property
62+
* @return 1 if the shared-irqs property has the named element, 0 otherwise
63+
*/
64+
#define SHARED_IRQ_HAS_NAME(node_id, irq_name) \
65+
IS_ENABLED(DT_CAT(node_id, _P_shared_irqs_NAME_##irq_name##_EXISTS))
66+
67+
/**
68+
* @brief Does the node have an shared-irqs element at index with status okay?
69+
*
70+
* @param node_id Node identifier of a device which may have a shared-irqs
71+
* phandle-array element at the given index.
72+
* @param irq_idx logical index into the shared-irqs phandle-array
73+
* @return 1 if the shared-irqs element at index has status okay,
74+
* 0 otherwise
75+
*/
76+
#define SHARED_IRQ_BY_IDX_HAS_STATUS_OKAY(node_id, irq_idx) \
77+
COND_CODE_1(SHARED_IRQ_HAS_IDX(node_id, irq_idx), \
78+
(COND_CODE_1(DT_NODE_HAS_STATUS( \
79+
SHARED_IRQ_BY_IDX(node_id, irq_idx), okay), \
80+
(1), \
81+
(0)), \
82+
(0)))
83+
84+
/**
85+
* @brief Does the node have an shared-irqs element with a matching name and
86+
* status okay?
87+
*
88+
* @param node_id Node identifier of a device which may have a shared-irqs
89+
* phandle-array element with the given name.
90+
* @param irq_name lowercase-and-underscores name of a shared-irqs element
91+
* as defined by the node's shared-irq-names property
92+
* @return 1 if the shared-irqs property has the named element and status okay,
93+
* 0 otherwise
94+
*/
95+
#define SHARED_IRQ_BY_NAME_HAS_STATUS_OKAY(node_id, irq_name) \
96+
COND_CODE_1(SHARED_IRQ_HAS_NAME(node_id, irq_name), \
97+
(COND_CODE_1(DT_NODE_HAS_STATUS( \
98+
SHARED_IRQ_BY_NAME(node_id, irq_name), okay),\
99+
(1), \
100+
(0))), \
101+
(0))
102+
103+
/**
104+
* @brief Connect to a devicetree nodes shared-irq at index.
105+
*
106+
* The IRQ must be subsequently enabled before the interrupt handler
107+
* begins servicing interrupts.
108+
*
109+
* @warning
110+
* Although this routine is invoked at run-time, all of its arguments must be
111+
* computable by the compiler at build time.
112+
*
113+
* @param node_id Node identifier of a device that has a shared-irqs
114+
* phandle-array property.
115+
* @param irq_idx logical index into the shared-irqs phandle-array
116+
* @param isr_p Address of interrupt service routine.
117+
* @param isr_param_p Parameter passed to interrupt service routine. Should be a
118+
* pointer to the device that will service the interrupt.
119+
*/
120+
#define SHARED_IRQ_CONNECT_BY_IDX(node_id, irq_idx, isr_p, isr_param_p) \
121+
__ASSERT(device_is_ready( \
122+
DEVICE_DT_GET(SHARED_IRQ_BY_IDX(node_id, irq_idx))), \
123+
"shared irq ##irq_idx## not ready"); \
124+
shared_irq_isr_register( \
125+
DEVICE_DT_GET(SHARED_IRQ_BY_IDX(node_id, irq_idx)), \
126+
(isr_t)isr_p, isr_param_p); \
127+
128+
/**
129+
* @brief Connect to a devicetree nodes shared-irq by name.
130+
*
131+
* This routine connects to a shared-irqs element, provided the given name
132+
* finds a match.
133+
*
134+
* The IRQ must be subsequently enabled before the interrupt handler
135+
* begins servicing interrupts.
136+
*
137+
* @warning
138+
* Although this routine is invoked at run-time, all of its arguments must be
139+
* computable by the compiler at build time.
140+
*
141+
* @param node_id Node identifier of a device that has a shared-irqs
142+
* phandle-array property.
143+
* @param irq_name lowercase-and-underscores shared-irq specifier name
144+
* @param isr_p Address of interrupt service routine.
145+
* @param isr_param_p Parameter passed to interrupt service routine. Should be a
146+
* pointer to the device that will service the interrupt.
147+
*/
148+
#define SHARED_IRQ_CONNECT_BY_NAME(node_id, irq_name, isr_p, isr_param_p) \
149+
__ASSERT(device_is_ready( \
150+
DEVICE_DT_GET(SHARED_IRQ_BY_NAME(node_id, irq_name))), \
151+
"shared-irq ##irq_name## not ready"); \
152+
shared_irq_isr_register( \
153+
DEVICE_DT_GET(SHARED_IRQ_BY_NAME(node_id, irq_name)), \
154+
(isr_t)isr_p, isr_param_p) \
155+
156+
/**
157+
* @brief Connect to a devicetree nodes shared-irqs element at idx if it
158+
* exists, else connect to the IRQ in the interrupts array at the same idx.
159+
*
160+
* This routine registers a device isr with the shared-irq matching the given
161+
* index if a shared-irq with index idx exists.
162+
* Otherwise, it initializes an interrupt handler for the irq in the interrupts
163+
* array at the same idx.
164+
* The IRQ must be subsequently enabled before the interrupt handler
165+
* begins servicing interrupts.
166+
*
167+
* @warning
168+
* Although this routine is invoked at run-time, all of its arguments must be
169+
* computable by the compiler at build time.
170+
*
171+
* @param node_id Node identifier of a device that has either a shared-irqs
172+
* phandle-array or a interrupts property.
173+
* @param irq_idx logical index into the shared-irqs phandle-array if it exists,
174+
* index into the interrupts array otherwise.
175+
* @param isr_p Address of interrupt service routine.
176+
* @param isr_param_p Parameter passed to interrupt service routine. Should be a
177+
* pointer to the device that will service the interrupt.
178+
* @param flags_p Architecture-specific IRQ configuration flags (not used for
179+
* shared-irqs).
180+
*
181+
* @return N/A
182+
*/
183+
#define SHARED_IRQ_CONNECT_IRQ_BY_IDX_COND(node_id, irq_idx, isr_p, \
184+
isr_param_p, flags_p) \
185+
COND_CODE_1(SHARED_IRQ_BY_IDX_HAS_STATUS_OKAY(node_id, irq_idx), \
186+
(SHARED_IRQ_CONNECT_BY_IDX(node_id, irq_idx, isr_p, \
187+
isr_param_p)), \
188+
(IRQ_CONNECT(DT_IRQ_BY_IDX(node_id, irq_idx, irq), \
189+
DT_IRQ_BY_IDX(node_id, irq_idx, priority), \
190+
isr_p, isr_param_p, flags_p)))
191+
192+
/**
193+
* @brief Connect to a devicetree nodes (only) shared-irqs element if it
194+
* exists, else connect to the single irq in the interrupts array.
195+
*
196+
* The IRQ must be subsequently enabled before the interrupt handler
197+
* begins servicing interrupts.
198+
*
199+
* @warning
200+
* Although this routine is invoked at run-time, all of its arguments must be
201+
* computable by the compiler at build time.
202+
*
203+
* @param node_id Node identifier of a device that has either a shared-irqs
204+
* phandle-array or a interrupts array.
205+
* @param isr_p Address of interrupt service routine.
206+
* @param isr_param_p Parameter passed to interrupt service routine. Should be a
207+
* pointer to the device that will service the interrupt.
208+
* @param flags_p Architecture-specific IRQ configuration flags (not used for
209+
* shared-irqs).
210+
*
211+
* @return N/A
212+
*/
213+
#define SHARED_IRQ_CONNECT_IRQ_COND(node_id, isr_p, isr_param_p, flags_p) \
214+
SHARED_IRQ_CONNECT_IRQ_BY_IDX_COND(node_id, 0, isr_p, isr_param_p, \
215+
flags_p) \
216+
217+
/**
218+
* @brief Connect to a devicetree nodes shared-irqs element by name if it
219+
* exists, else connect to a IRQ using the same given name.
220+
*
221+
* This routine registers a device isr with the shared-irq matching the given
222+
* name if such a shared-irq exists.
223+
* Otherwise, it initializes an interrupt handler for an IRQ with the given name.
224+
* The IRQ must be subsequently enabled before the interrupt handler
225+
* begins servicing interrupts.
226+
*
227+
* @warning
228+
* Although this routine is invoked at run-time, all of its arguments must be
229+
* computable by the compiler at build time.
230+
*
231+
* @param node_id Node identifier of a device that has either a shared-irqs
232+
* phandle-array or a interrupts property.
233+
* @param irq_name lowercase-and-underscores device shared-irq-name if it
234+
* exists, interrupt-name otherwise.
235+
* @param isr_p Address of interrupt service routine.
236+
* @param isr_param_p Parameter passed to interrupt service routine. Should be a
237+
* pointer to the device that will service the interrupt.
238+
* @param flags_p Architecture-specific IRQ configuration flags (not used for
239+
* shared-irqs).
240+
*
241+
* @return N/A
242+
*/
243+
244+
#define SHARED_IRQ_CONNECT_IRQ_BY_NAME_COND(node_id, irq_name, isr_p, \
245+
isr_param_p, flags_p) \
246+
COND_CODE_1(SHARED_IRQ_BY_NAME_HAS_STATUS_OKAY(node_id, irq_name), \
247+
(SHARED_IRQ_CONNECT_BY_NAME(node_id, irq_name, \
248+
isr_p, isr_param_p)), \
249+
(IRQ_CONNECT(DT_IRQ_BY_NAME(node_id, irq_name, irq), \
250+
DT_IRQ_BY_NAME(node_id, irq_name, priority), \
251+
isr_p, isr_param_p, flags_p)))
252+
253+
/**
254+
* @brief Enable ISR for a devicetree node's shared interrupt at index if it
255+
* exists, or enable interrupts from irq at index otherwise.
256+
*
257+
* @warning
258+
* Although this routine is invoked at run-time, all of its arguments must be
259+
* computable by the compiler at build time.
260+
*
261+
* @param node_id Node identifier of a device which may have a shared-irqs
262+
* phandle-array property.
263+
* @param irq_idx logical index into the shared-irqs phandle-array if it exists,
264+
* index into the interrupts array otherwise.
265+
*
266+
* @return N/A
267+
*/
268+
#define SHARED_IRQ_ENABLE_BY_IDX_COND(node_id, irq_idx) \
269+
COND_CODE_1(SHARED_IRQ_BY_IDX_HAS_STATUS_OKAY(node_id, irq_idx), \
270+
(shared_irq_enable( \
271+
DEVICE_DT_GET(SHARED_IRQ_BY_IDX(node_id, irq_idx)), \
272+
DEVICE_DT_GET(node_id))), \
273+
(irq_enable(DT_IRQ_BY_IDX(node_id, irq_idx, irq)))) \
274+
275+
/**
276+
* @brief Enable ISR for a devicetree node's (only) shared-irqs interrupt if it
277+
* exists, or enable interrupts from the single IRQ otherwise.
278+
*
279+
* @warning
280+
* Although this routine is invoked at run-time, all of its arguments must be
281+
* computable by the compiler at build time.
282+
*
283+
* @param node_id Node identifier of a device which may have a shared-irqs
284+
* phandle-array property.
285+
*
286+
* @return N/A
287+
*/
288+
#define SHARED_IRQ_ENABLE_COND(node_id) \
289+
COND_CODE_1(SHARED_IRQ_BY_IDX_HAS_STATUS_OKAY(node_id, 0), \
290+
(shared_irq_enable( \
291+
DEVICE_DT_GET(SHARED_IRQ_BY_IDX(node_id, 0)), \
292+
DEVICE_DT_GET(node_id))), \
293+
(irq_enable(DT_IRQ(node_id, irq)))) \
294+
295+
/**
296+
* @brief Enable ISR for a devicetree node's shared interrupt by name if it
297+
* exists, or enable interrupts from irq by name otherwise.
298+
*
299+
* @warning
300+
* Although this routine is invoked at run-time, all of its arguments must be
301+
* computable by the compiler at build time.
302+
*
303+
* @param node_id Node identifier of a device which may have a shared-irqs
304+
* phandle-array property.
305+
* @param irq_name lowercase-and-underscores device shared-irqs name if it
306+
* exists, irq name otherwise.
307+
*
308+
* @return N/A
309+
*/
310+
#define SHARED_IRQ_ENABLE_BY_NAME_COND(node_id, irq_name) \
311+
COND_CODE_1(SHARED_IRQ_BY_NAME_HAS_STATUS_OKAY(node_id, irq_name), \
312+
(shared_irq_enable( \
313+
DEVICE_DT_GET(SHARED_IRQ_BY_NAME(node_id, irq_name)), \
314+
DEVICE_DT_GET(node_id))), \
315+
(irq_enable(DT_IRQ_BY_NAME(node_id, irq_name, irq)))) \
316+
317+
/**
318+
* @brief Disable ISR for a devicetree node's shared interrupt at index if it
319+
* exists, or disable interrupts from irq at index otherwise.
320+
*
321+
* @warning
322+
* Although this routine is invoked at run-time, all of its arguments must be
323+
* computable by the compiler at build time.
324+
*
325+
* @param node_id Node identifier of a device which may have a shared-irqs
326+
* phandle-array property.
327+
* @param irq_idx logical index into the shared-irqs phandle-array if it exists,
328+
* index into the interrupts array otherwise.
329+
*
330+
* @return N/A
331+
*/
332+
#define SHARED_IRQ_DISABLE_BY_IDX_COND(node_id, irq_idx) \
333+
COND_CODE_1(SHARED_IRQ_BY_IDX_HAS_STATUS_OKAY(node_id, irq_idx), \
334+
(shared_irq_disable( \
335+
DEVICE_DT_GET(SHARED_IRQ_BY_IDX(node_id, irq_idx)), \
336+
DEVICE_DT_GET(node_id))), \
337+
(irq_disable(DT_IRQ_BY_IDX(node_id, irq_idx, irq)))) \
338+
339+
/**
340+
* @brief Disable ISR for a devicetree node's (only) shared-irqs interrupt if it
341+
* exists, or disable interrupts from the single IRQ otherwise.
342+
*
343+
* @warning
344+
* Although this routine is invoked at run-time, all of its arguments must be
345+
* computable by the compiler at build time.
346+
*
347+
* @param node_id Node identifier of a device which may have a shared-irqs
348+
* phandle-array property.
349+
*
350+
* @return N/A
351+
*/
352+
#define SHARED_IRQ_DISABLE_COND(node_id) \
353+
COND_CODE_1(SHARED_IRQ_BY_IDX_HAS_STATUS_OKAY(node_id, 0), \
354+
(shared_irq_disable( \
355+
DEVICE_DT_GET(SHARED_IRQ_BY_IDX(node_id, 0)), \
356+
DEVICE_DT_GET(node_id))), \
357+
(irq_disable(DT_IRQ(node_id, irq)))) \
358+
359+
/**
360+
* @brief Disable ISR for a devicetree node's shared interrupt by name if it
361+
* exists, or disable interrupts from irq by name otherwise.
362+
*
363+
* @warning
364+
* Although this routine is invoked at run-time, all of its arguments must be
365+
* computable by the compiler at build time.
366+
*
367+
* @param node_id Node identifier of a device which may have a shared-irqs
368+
* phandle-array property.
369+
* @param irq_name lowercase-and-underscores device shared-irqs name if it
370+
* exists, irq name otherwise.
371+
*
372+
* @return N/A
373+
*/
374+
#define SHARED_IRQ_DISABLE_BY_NAME_COND(node_id, irq_name) \
375+
COND_CODE_1(SHARED_IRQ_BY_NAME_HAS_STATUS_OKAY(node_id, irq_name), \
376+
(shared_irq_disable( \
377+
DEVICE_DT_GET(SHARED_IRQ_BY_NAME(node_id, irq_name)), \
378+
DEVICE_DT_GET(node_id))), \
379+
(irq_disable(DT_IRQ_BY_NAME(node_id, irq_name, irq)))) \
380+
18381
typedef int (*isr_t)(const struct device *dev);
19382

20383
/* driver API definition */

0 commit comments

Comments
 (0)