11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
27315b7b4SJens Wiklander /*
3e9f46c74SJens Wiklander * Copyright (c) 2016-2019, Linaro Limited
47315b7b4SJens Wiklander */
57315b7b4SJens Wiklander
667729d8dSLudovic Barre #include <kernel/dt.h>
77315b7b4SJens Wiklander #include <kernel/interrupt.h>
8e9f46c74SJens Wiklander #include <kernel/panic.h>
967729d8dSLudovic Barre #include <libfdt.h>
10f932e355SEtienne Carriere #include <mm/core_memprot.h>
11acc5dd21SLudovic Barre #include <stdlib.h>
127315b7b4SJens Wiklander #include <trace.h>
131c832d7cSdavidwang #include <assert.h>
147315b7b4SJens Wiklander
157315b7b4SJens Wiklander /*
167315b7b4SJens Wiklander * NOTE!
177315b7b4SJens Wiklander *
187315b7b4SJens Wiklander * We're assuming that there's no concurrent use of this interface, except
197315b7b4SJens Wiklander * delivery of interrupts in parallel. Synchronization will be needed when
207315b7b4SJens Wiklander * we begin to modify settings after boot initialization.
217315b7b4SJens Wiklander */
227315b7b4SJens Wiklander
233475549bSEtienne Carriere static struct itr_chip *itr_main_chip __nex_bss;
247315b7b4SJens Wiklander
itr_chip_is_valid(struct itr_chip * chip)25df7874b5SEtienne Carriere static bool itr_chip_is_valid(struct itr_chip *chip)
26df7874b5SEtienne Carriere {
27df7874b5SEtienne Carriere return chip && is_unpaged(chip) && chip->ops &&
28df7874b5SEtienne Carriere is_unpaged((void *)chip->ops) &&
29df7874b5SEtienne Carriere chip->ops->mask && is_unpaged(chip->ops->mask) &&
30df7874b5SEtienne Carriere chip->ops->unmask && is_unpaged(chip->ops->unmask) &&
31df7874b5SEtienne Carriere chip->ops->enable && chip->ops->disable;
32df7874b5SEtienne Carriere }
33df7874b5SEtienne Carriere
__itr_chip_init(struct itr_chip * chip)34df7874b5SEtienne Carriere static void __itr_chip_init(struct itr_chip *chip)
35df7874b5SEtienne Carriere {
36df7874b5SEtienne Carriere SLIST_INIT(&chip->handlers);
37df7874b5SEtienne Carriere }
38df7874b5SEtienne Carriere
itr_chip_init(struct itr_chip * chip)39f932e355SEtienne Carriere TEE_Result itr_chip_init(struct itr_chip *chip)
40f932e355SEtienne Carriere {
41df7874b5SEtienne Carriere /*
42df7874b5SEtienne Carriere * Interrupt chips not using only the DT to configure
43df7874b5SEtienne Carriere * consumers interrupts require configure handler.
44df7874b5SEtienne Carriere */
45df7874b5SEtienne Carriere if (!itr_chip_is_valid(chip) || !chip->ops->configure)
46df7874b5SEtienne Carriere return TEE_ERROR_BAD_PARAMETERS;
47df7874b5SEtienne Carriere
48df7874b5SEtienne Carriere __itr_chip_init(chip);
49df7874b5SEtienne Carriere
50df7874b5SEtienne Carriere return TEE_SUCCESS;
51df7874b5SEtienne Carriere }
52df7874b5SEtienne Carriere
itr_chip_dt_only_init(struct itr_chip * chip)53df7874b5SEtienne Carriere TEE_Result itr_chip_dt_only_init(struct itr_chip *chip)
54df7874b5SEtienne Carriere {
55f932e355SEtienne Carriere if (!itr_chip_is_valid(chip))
56f932e355SEtienne Carriere return TEE_ERROR_BAD_PARAMETERS;
57f932e355SEtienne Carriere
58df7874b5SEtienne Carriere __itr_chip_init(chip);
59f932e355SEtienne Carriere
60f932e355SEtienne Carriere return TEE_SUCCESS;
61f932e355SEtienne Carriere }
62f932e355SEtienne Carriere
interrupt_main_init(struct itr_chip * chip)6301980f3fSEtienne Carriere void interrupt_main_init(struct itr_chip *chip)
647315b7b4SJens Wiklander {
655f21fda6SEtienne Carriere if (itr_chip_init(chip))
665f21fda6SEtienne Carriere panic();
675f21fda6SEtienne Carriere
683475549bSEtienne Carriere itr_main_chip = chip;
697315b7b4SJens Wiklander }
707315b7b4SJens Wiklander
interrupt_get_main_chip(void)71e050e0a7SEtienne Carriere struct itr_chip *interrupt_get_main_chip(void)
72e050e0a7SEtienne Carriere {
733475549bSEtienne Carriere assert(itr_main_chip);
743475549bSEtienne Carriere return itr_main_chip;
75e050e0a7SEtienne Carriere }
76e050e0a7SEtienne Carriere
interrupt_get_main_chip_may_fail(void)77245a552cSJens Wiklander struct itr_chip *interrupt_get_main_chip_may_fail(void)
78245a552cSJens Wiklander {
79245a552cSJens Wiklander return itr_main_chip;
80245a552cSJens Wiklander }
81245a552cSJens Wiklander
8267729d8dSLudovic Barre #ifdef CFG_DT
dt_get_irq_type_prio(const void * fdt,int node,uint32_t * type,uint32_t * prio)83702fe5a7SClément Léger int dt_get_irq_type_prio(const void *fdt, int node, uint32_t *type,
84702fe5a7SClément Léger uint32_t *prio)
8567729d8dSLudovic Barre {
8667729d8dSLudovic Barre const uint32_t *prop = NULL;
87888bb63dSClément Léger int count = 0;
8867729d8dSLudovic Barre int it_num = DT_INFO_INVALID_INTERRUPT;
8967729d8dSLudovic Barre
903475549bSEtienne Carriere if (!itr_main_chip || !itr_main_chip->dt_get_irq)
9167729d8dSLudovic Barre return it_num;
9267729d8dSLudovic Barre
93888bb63dSClément Léger prop = fdt_getprop(fdt, node, "interrupts", &count);
9467729d8dSLudovic Barre if (!prop)
9567729d8dSLudovic Barre return it_num;
9667729d8dSLudovic Barre
9763873401SEtienne Carriere return itr_main_chip->dt_get_irq(prop, count / sizeof(uint32_t), type,
9863873401SEtienne Carriere prio);
9967729d8dSLudovic Barre }
10067729d8dSLudovic Barre #endif
10167729d8dSLudovic Barre
102e9f46c74SJens Wiklander /* This function is supposed to be overridden in platform specific code */
interrupt_main_handler(void)103358bf47cSEtienne Carriere void __weak __noreturn interrupt_main_handler(void)
104e9f46c74SJens Wiklander {
105e9f46c74SJens Wiklander panic("Secure interrupt handler not defined");
106e9f46c74SJens Wiklander }
107f932e355SEtienne Carriere
108f932e355SEtienne Carriere /*
109f932e355SEtienne Carriere * Interrupt controller chip support
110f932e355SEtienne Carriere */
interrupt_call_handlers(struct itr_chip * chip,size_t itr_num)111f932e355SEtienne Carriere void interrupt_call_handlers(struct itr_chip *chip, size_t itr_num)
112f932e355SEtienne Carriere {
113f932e355SEtienne Carriere struct itr_handler *h = NULL;
114f932e355SEtienne Carriere bool was_handled = false;
115f932e355SEtienne Carriere
116f932e355SEtienne Carriere assert(chip);
117f932e355SEtienne Carriere
118f932e355SEtienne Carriere SLIST_FOREACH(h, &chip->handlers, link) {
119f932e355SEtienne Carriere if (h->it == itr_num) {
120f932e355SEtienne Carriere if (h->handler(h) == ITRR_HANDLED)
121f932e355SEtienne Carriere was_handled = true;
122f932e355SEtienne Carriere else if (!(h->flags & ITRF_SHARED))
123f932e355SEtienne Carriere break;
124f932e355SEtienne Carriere }
125f932e355SEtienne Carriere }
126f932e355SEtienne Carriere
127f932e355SEtienne Carriere if (!was_handled) {
128f932e355SEtienne Carriere EMSG("Mask unhandled interrupt %s:%zu", chip->name, itr_num);
129f932e355SEtienne Carriere interrupt_mask(chip, itr_num);
130f932e355SEtienne Carriere }
131f932e355SEtienne Carriere }
132f932e355SEtienne Carriere
interrupt_configure(struct itr_chip * chip,size_t itr_num,uint32_t type,uint32_t prio)133f932e355SEtienne Carriere TEE_Result interrupt_configure(struct itr_chip *chip, size_t itr_num,
134f932e355SEtienne Carriere uint32_t type, uint32_t prio)
135f932e355SEtienne Carriere {
136df7874b5SEtienne Carriere if (!chip->ops->configure) {
137df7874b5SEtienne Carriere EMSG("No configure handler in itr_chip %s", chip->name);
138df7874b5SEtienne Carriere return TEE_ERROR_NOT_IMPLEMENTED;
139df7874b5SEtienne Carriere }
140df7874b5SEtienne Carriere
1412a50ce7dSEtienne Carriere chip->ops->configure(chip, itr_num, type, prio);
142f932e355SEtienne Carriere
143f932e355SEtienne Carriere return TEE_SUCCESS;
144f932e355SEtienne Carriere }
145f932e355SEtienne Carriere
add_configure_handler(struct itr_handler * hdl,uint32_t type,uint32_t prio,bool configure)146e9376d02SEtienne Carriere static TEE_Result add_configure_handler(struct itr_handler *hdl,
147e9376d02SEtienne Carriere uint32_t type, uint32_t prio,
148e9376d02SEtienne Carriere bool configure)
149f932e355SEtienne Carriere {
150df7874b5SEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC;
151f932e355SEtienne Carriere struct itr_handler *h = NULL;
152f932e355SEtienne Carriere
153f932e355SEtienne Carriere assert(hdl && hdl->chip->ops && is_unpaged(hdl) &&
154f932e355SEtienne Carriere hdl->handler && is_unpaged(hdl->handler));
155f932e355SEtienne Carriere
156f932e355SEtienne Carriere SLIST_FOREACH(h, &hdl->chip->handlers, link) {
157f932e355SEtienne Carriere if (h->it == hdl->it &&
158f932e355SEtienne Carriere (!(hdl->flags & ITRF_SHARED) ||
159f932e355SEtienne Carriere !(h->flags & ITRF_SHARED))) {
160f932e355SEtienne Carriere EMSG("Shared and non-shared flags on interrupt %s#%zu",
161f932e355SEtienne Carriere hdl->chip->name, hdl->it);
162f932e355SEtienne Carriere return TEE_ERROR_GENERIC;
163f932e355SEtienne Carriere }
164f932e355SEtienne Carriere }
165f932e355SEtienne Carriere
166df7874b5SEtienne Carriere if (configure) {
167df7874b5SEtienne Carriere res = interrupt_configure(hdl->chip, hdl->it, type, prio);
168df7874b5SEtienne Carriere if (res)
169df7874b5SEtienne Carriere return res;
170df7874b5SEtienne Carriere }
171f932e355SEtienne Carriere
172f932e355SEtienne Carriere SLIST_INSERT_HEAD(&hdl->chip->handlers, hdl, link);
173f932e355SEtienne Carriere
174f932e355SEtienne Carriere return TEE_SUCCESS;
175f932e355SEtienne Carriere }
176f932e355SEtienne Carriere
interrupt_add_configure_handler(struct itr_handler * hdl,uint32_t type,uint32_t prio)177e9376d02SEtienne Carriere TEE_Result interrupt_add_configure_handler(struct itr_handler *hdl,
178e9376d02SEtienne Carriere uint32_t type, uint32_t prio)
179e9376d02SEtienne Carriere {
180e9376d02SEtienne Carriere return add_configure_handler(hdl, type, prio, true /* configure */);
181e9376d02SEtienne Carriere }
182e9376d02SEtienne Carriere
interrupt_create_handler(struct itr_chip * itr_chip,size_t itr_num,itr_handler_t callback,void * priv,uint32_t flags,struct itr_handler ** out_hdl)183e9376d02SEtienne Carriere TEE_Result interrupt_create_handler(struct itr_chip *itr_chip, size_t itr_num,
184e9376d02SEtienne Carriere itr_handler_t callback, void *priv,
185e9376d02SEtienne Carriere uint32_t flags,
186e9376d02SEtienne Carriere struct itr_handler **out_hdl)
187e9376d02SEtienne Carriere {
188e9376d02SEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC;
189e9376d02SEtienne Carriere struct itr_handler *itr_hdl = NULL;
190e9376d02SEtienne Carriere
191e9376d02SEtienne Carriere itr_hdl = calloc(1, sizeof(*itr_hdl));
192e9376d02SEtienne Carriere if (!itr_hdl)
193e9376d02SEtienne Carriere return TEE_ERROR_OUT_OF_MEMORY;
194e9376d02SEtienne Carriere
195e9376d02SEtienne Carriere *itr_hdl = (struct itr_handler){
196e9376d02SEtienne Carriere .chip = itr_chip,
197e9376d02SEtienne Carriere .it = itr_num,
198e9376d02SEtienne Carriere .flags = flags,
199e9376d02SEtienne Carriere .handler = callback,
200e9376d02SEtienne Carriere .data = priv,
201e9376d02SEtienne Carriere };
202e9376d02SEtienne Carriere
203*2f4d5a0dSEtienne Carriere res = add_configure_handler(itr_hdl, 0, 0, false /* !configure */);
204e9376d02SEtienne Carriere if (res) {
205e9376d02SEtienne Carriere free(itr_hdl);
206e9376d02SEtienne Carriere return res;
207e9376d02SEtienne Carriere }
208e9376d02SEtienne Carriere
209e9376d02SEtienne Carriere if (out_hdl)
210e9376d02SEtienne Carriere *out_hdl = itr_hdl;
211e9376d02SEtienne Carriere
212e9376d02SEtienne Carriere return TEE_SUCCESS;
213e9376d02SEtienne Carriere }
214e9376d02SEtienne Carriere
interrupt_remove_handler(struct itr_handler * hdl)215f932e355SEtienne Carriere void interrupt_remove_handler(struct itr_handler *hdl)
216f932e355SEtienne Carriere {
217f932e355SEtienne Carriere struct itr_handler *h = NULL;
218f932e355SEtienne Carriere bool disable_itr = true;
219f932e355SEtienne Carriere
220f932e355SEtienne Carriere if (!hdl)
221f932e355SEtienne Carriere return;
222f932e355SEtienne Carriere
223f932e355SEtienne Carriere SLIST_FOREACH(h, &hdl->chip->handlers, link)
224f932e355SEtienne Carriere if (h == hdl)
225f932e355SEtienne Carriere break;
226f932e355SEtienne Carriere if (!h) {
227f932e355SEtienne Carriere DMSG("Invalid %s:%zu", hdl->chip->name, hdl->it);
228f932e355SEtienne Carriere assert(false);
229f932e355SEtienne Carriere return;
230f932e355SEtienne Carriere }
231f932e355SEtienne Carriere
232f932e355SEtienne Carriere if (hdl->flags & ITRF_SHARED) {
233f932e355SEtienne Carriere SLIST_FOREACH(h, &hdl->chip->handlers, link) {
234f932e355SEtienne Carriere if (h != hdl && h->it == hdl->it) {
235f932e355SEtienne Carriere disable_itr = false;
236f932e355SEtienne Carriere break;
237f932e355SEtienne Carriere }
238f932e355SEtienne Carriere }
239f932e355SEtienne Carriere }
240f932e355SEtienne Carriere
241f932e355SEtienne Carriere if (disable_itr)
242f932e355SEtienne Carriere interrupt_disable(hdl->chip, hdl->it);
243f932e355SEtienne Carriere
244f932e355SEtienne Carriere SLIST_REMOVE(&hdl->chip->handlers, hdl, itr_handler, link);
245f932e355SEtienne Carriere }
246f932e355SEtienne Carriere
interrupt_alloc_add_conf_handler(struct itr_chip * chip,size_t itr_num,itr_handler_t handler,uint32_t flags,void * data,uint32_t type,uint32_t prio,struct itr_handler ** out_hdl)2471b5c7ca4SEtienne Carriere TEE_Result interrupt_alloc_add_conf_handler(struct itr_chip *chip,
2481b5c7ca4SEtienne Carriere size_t itr_num,
2491b5c7ca4SEtienne Carriere itr_handler_t handler,
2501b5c7ca4SEtienne Carriere uint32_t flags, void *data,
2511b5c7ca4SEtienne Carriere uint32_t type, uint32_t prio,
2521b5c7ca4SEtienne Carriere struct itr_handler **out_hdl)
253f932e355SEtienne Carriere {
254f932e355SEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC;
255f932e355SEtienne Carriere struct itr_handler *hdl = NULL;
256f932e355SEtienne Carriere
257f932e355SEtienne Carriere hdl = calloc(1, sizeof(*hdl));
258f932e355SEtienne Carriere if (!hdl)
259f932e355SEtienne Carriere return TEE_ERROR_OUT_OF_MEMORY;
260f932e355SEtienne Carriere
261f932e355SEtienne Carriere *hdl = ITR_HANDLER(chip, itr_num, flags, handler, data);
262f932e355SEtienne Carriere
2631b5c7ca4SEtienne Carriere res = interrupt_add_configure_handler(hdl, type, prio);
264f932e355SEtienne Carriere if (res) {
265f932e355SEtienne Carriere free(hdl);
266f932e355SEtienne Carriere return res;
267f932e355SEtienne Carriere }
268f932e355SEtienne Carriere
269f932e355SEtienne Carriere if (out_hdl)
270f932e355SEtienne Carriere *out_hdl = hdl;
271f932e355SEtienne Carriere
272f932e355SEtienne Carriere return TEE_SUCCESS;
273f932e355SEtienne Carriere }
274f932e355SEtienne Carriere
interrupt_remove_free_handler(struct itr_handler * hdl)275f932e355SEtienne Carriere void interrupt_remove_free_handler(struct itr_handler *hdl)
276f932e355SEtienne Carriere {
277f932e355SEtienne Carriere if (hdl) {
278f932e355SEtienne Carriere interrupt_remove_handler(hdl);
279f932e355SEtienne Carriere free(hdl);
280f932e355SEtienne Carriere }
281f932e355SEtienne Carriere }
28233a0c835SEtienne Carriere
28333a0c835SEtienne Carriere #ifdef CFG_DT
interrupt_register_provider(const void * fdt,int node,itr_dt_get_func dt_get_itr,void * data)28433a0c835SEtienne Carriere TEE_Result interrupt_register_provider(const void *fdt, int node,
28533a0c835SEtienne Carriere itr_dt_get_func dt_get_itr, void *data)
28633a0c835SEtienne Carriere {
28733a0c835SEtienne Carriere return dt_driver_register_provider(fdt, node,
28833a0c835SEtienne Carriere (get_of_device_func)dt_get_itr,
28933a0c835SEtienne Carriere data, DT_DRIVER_INTERRUPT);
29033a0c835SEtienne Carriere }
29133a0c835SEtienne Carriere
29233a0c835SEtienne Carriere /*
29333a0c835SEtienne Carriere * Fills an itr_desc reference based on "interrupts" property bindings.
29433a0c835SEtienne Carriere * May return TEE_ERROR_DEFER_DRIVER_INIT if parent controller is found but
29533a0c835SEtienne Carriere * not yet initialized.
29633a0c835SEtienne Carriere */
get_legacy_interrupt_by_index(const void * fdt,int node,unsigned int index,struct itr_desc * itr_desc)29733a0c835SEtienne Carriere static TEE_Result get_legacy_interrupt_by_index(const void *fdt, int node,
29833a0c835SEtienne Carriere unsigned int index,
29933a0c835SEtienne Carriere struct itr_desc *itr_desc)
30033a0c835SEtienne Carriere {
30133a0c835SEtienne Carriere const uint32_t *prop = NULL;
30233a0c835SEtienne Carriere uint32_t phandle = 0;
30333a0c835SEtienne Carriere int pnode = 0;
30433a0c835SEtienne Carriere int len = 0;
30533a0c835SEtienne Carriere
30633a0c835SEtienne Carriere prop = fdt_getprop(fdt, node, "interrupts", &len);
30733a0c835SEtienne Carriere if (!prop)
30833a0c835SEtienne Carriere return TEE_ERROR_ITEM_NOT_FOUND;
30933a0c835SEtienne Carriere
31033a0c835SEtienne Carriere /* Find "interrupt-parent" in node or its parents */
31133a0c835SEtienne Carriere pnode = node;
31233a0c835SEtienne Carriere prop = fdt_getprop(fdt, pnode, "interrupt-parent", &len);
31333a0c835SEtienne Carriere
31433a0c835SEtienne Carriere while (!prop) {
31533a0c835SEtienne Carriere pnode = fdt_parent_offset(fdt, pnode);
31633a0c835SEtienne Carriere if (pnode < 0)
31733a0c835SEtienne Carriere break;
31833a0c835SEtienne Carriere
31933a0c835SEtienne Carriere prop = fdt_getprop(fdt, pnode, "interrupt-parent", &len);
32033a0c835SEtienne Carriere if (!prop && len != -FDT_ERR_NOTFOUND)
32133a0c835SEtienne Carriere break;
32233a0c835SEtienne Carriere }
32333a0c835SEtienne Carriere if (!prop) {
32433a0c835SEtienne Carriere DMSG("No interrupt parent for node %s",
32533a0c835SEtienne Carriere fdt_get_name(fdt, node, NULL));
32633a0c835SEtienne Carriere return TEE_ERROR_GENERIC;
32733a0c835SEtienne Carriere }
32833a0c835SEtienne Carriere
32933a0c835SEtienne Carriere /* "interrupt-parent" provides interrupt controller phandle */
33033a0c835SEtienne Carriere phandle = fdt32_to_cpu(prop[0]);
33133a0c835SEtienne Carriere
33233a0c835SEtienne Carriere /* Get interrupt chip/number from phandle and "interrupts" property */
33333a0c835SEtienne Carriere return dt_driver_device_from_node_idx_prop_phandle("interrupts", fdt,
33433a0c835SEtienne Carriere node, index,
33533a0c835SEtienne Carriere DT_DRIVER_INTERRUPT,
33633a0c835SEtienne Carriere phandle,
33733a0c835SEtienne Carriere itr_desc);
33833a0c835SEtienne Carriere }
33933a0c835SEtienne Carriere
34033a0c835SEtienne Carriere /*
34133a0c835SEtienne Carriere * Fills an itr_desc based on "interrupts-extended" property bindings.
34233a0c835SEtienne Carriere * May return TEE_ERROR_DEFER_DRIVER_INIT if parent controller is found
34333a0c835SEtienne Carriere * but not yet initialized.
34433a0c835SEtienne Carriere */
get_extended_interrupt_by_index(const void * fdt,int node,unsigned int index,struct itr_desc * itr_desc)34533a0c835SEtienne Carriere static TEE_Result get_extended_interrupt_by_index(const void *fdt, int node,
34633a0c835SEtienne Carriere unsigned int index,
34733a0c835SEtienne Carriere struct itr_desc *itr_desc)
34833a0c835SEtienne Carriere {
34933a0c835SEtienne Carriere return dt_driver_device_from_node_idx_prop("interrupts-extended",
35033a0c835SEtienne Carriere fdt, node, index,
35133a0c835SEtienne Carriere DT_DRIVER_INTERRUPT,
35233a0c835SEtienne Carriere itr_desc);
35333a0c835SEtienne Carriere }
35433a0c835SEtienne Carriere
interrupt_dt_get_by_index(const void * fdt,int node,unsigned int index,struct itr_chip ** chip,size_t * itr_num)35533a0c835SEtienne Carriere TEE_Result interrupt_dt_get_by_index(const void *fdt, int node,
35633a0c835SEtienne Carriere unsigned int index, struct itr_chip **chip,
35733a0c835SEtienne Carriere size_t *itr_num)
35833a0c835SEtienne Carriere {
35933a0c835SEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC;
36033a0c835SEtienne Carriere struct itr_desc desc = { };
36133a0c835SEtienne Carriere
36233a0c835SEtienne Carriere assert(chip && itr_num);
36333a0c835SEtienne Carriere
36433a0c835SEtienne Carriere /* "interrupts-extended" takes precedence over "interrupts" */
36533a0c835SEtienne Carriere if (fdt_getprop(fdt, node, "interrupts-extended", NULL))
36633a0c835SEtienne Carriere res = get_extended_interrupt_by_index(fdt, node, index, &desc);
36733a0c835SEtienne Carriere else
36833a0c835SEtienne Carriere res = get_legacy_interrupt_by_index(fdt, node, index, &desc);
36933a0c835SEtienne Carriere
37033a0c835SEtienne Carriere if (!res) {
371941de178SEtienne Carriere assert(itr_chip_is_valid(desc.chip));
37233a0c835SEtienne Carriere *chip = desc.chip;
37333a0c835SEtienne Carriere *itr_num = desc.itr_num;
37433a0c835SEtienne Carriere }
37533a0c835SEtienne Carriere
37633a0c835SEtienne Carriere return res;
37733a0c835SEtienne Carriere }
37833a0c835SEtienne Carriere
interrupt_dt_get_by_name(const void * fdt,int node,const char * name,struct itr_chip ** chip,size_t * itr_num)37933a0c835SEtienne Carriere TEE_Result interrupt_dt_get_by_name(const void *fdt, int node, const char *name,
38033a0c835SEtienne Carriere struct itr_chip **chip, size_t *itr_num)
38133a0c835SEtienne Carriere {
38233a0c835SEtienne Carriere int idx = 0;
38333a0c835SEtienne Carriere
38433a0c835SEtienne Carriere idx = fdt_stringlist_search(fdt, node, "interrupt-names", name);
38533a0c835SEtienne Carriere if (idx < 0)
38633a0c835SEtienne Carriere return TEE_ERROR_GENERIC;
38733a0c835SEtienne Carriere
38833a0c835SEtienne Carriere return interrupt_dt_get_by_index(fdt, node, idx, chip, itr_num);
38933a0c835SEtienne Carriere }
39033a0c835SEtienne Carriere #endif /*CFG_DT*/
391