11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 27315b7b4SJens Wiklander /* 3e9f46c74SJens Wiklander * Copyright (c) 2016-2019, Linaro Limited 47315b7b4SJens Wiklander */ 57315b7b4SJens Wiklander 67315b7b4SJens Wiklander #include <kernel/interrupt.h> 7e9f46c74SJens Wiklander #include <kernel/panic.h> 87315b7b4SJens Wiklander #include <trace.h> 9*1c832d7cSdavidwang #include <assert.h> 107315b7b4SJens Wiklander 117315b7b4SJens Wiklander /* 127315b7b4SJens Wiklander * NOTE! 137315b7b4SJens Wiklander * 147315b7b4SJens Wiklander * We're assuming that there's no concurrent use of this interface, except 157315b7b4SJens Wiklander * delivery of interrupts in parallel. Synchronization will be needed when 167315b7b4SJens Wiklander * we begin to modify settings after boot initialization. 177315b7b4SJens Wiklander */ 187315b7b4SJens Wiklander 197315b7b4SJens Wiklander static struct itr_chip *itr_chip; 207315b7b4SJens Wiklander static SLIST_HEAD(, itr_handler) handlers = SLIST_HEAD_INITIALIZER(handlers); 217315b7b4SJens Wiklander 227315b7b4SJens Wiklander void itr_init(struct itr_chip *chip) 237315b7b4SJens Wiklander { 247315b7b4SJens Wiklander itr_chip = chip; 257315b7b4SJens Wiklander } 267315b7b4SJens Wiklander 277315b7b4SJens Wiklander void itr_handle(size_t it) 287315b7b4SJens Wiklander { 29*1c832d7cSdavidwang struct itr_handler *h = NULL; 30*1c832d7cSdavidwang bool was_handled = false; 317315b7b4SJens Wiklander 32*1c832d7cSdavidwang SLIST_FOREACH(h, &handlers, link) { 33*1c832d7cSdavidwang if (h->it == it) { 34*1c832d7cSdavidwang if (h->handler(h) == ITRR_HANDLED) 35*1c832d7cSdavidwang was_handled = true; 36*1c832d7cSdavidwang else if (!(h->flags & ITRF_SHARED)) 37*1c832d7cSdavidwang break; 38*1c832d7cSdavidwang } 397315b7b4SJens Wiklander } 407315b7b4SJens Wiklander 41*1c832d7cSdavidwang if (!was_handled) { 42*1c832d7cSdavidwang EMSG("Disabling unhandled interrupt %zu", it); 437315b7b4SJens Wiklander itr_chip->ops->disable(itr_chip, it); 447315b7b4SJens Wiklander } 457315b7b4SJens Wiklander } 467315b7b4SJens Wiklander 477315b7b4SJens Wiklander void itr_add(struct itr_handler *h) 487315b7b4SJens Wiklander { 49*1c832d7cSdavidwang struct itr_handler __maybe_unused *hdl = NULL; 50*1c832d7cSdavidwang 51*1c832d7cSdavidwang SLIST_FOREACH(hdl, &handlers, link) 52*1c832d7cSdavidwang if (hdl->it == h->it) 53*1c832d7cSdavidwang assert((hdl->flags & ITRF_SHARED) && 54*1c832d7cSdavidwang (h->flags & ITRF_SHARED)); 55*1c832d7cSdavidwang 567315b7b4SJens Wiklander itr_chip->ops->add(itr_chip, h->it, h->flags); 577315b7b4SJens Wiklander SLIST_INSERT_HEAD(&handlers, h, link); 587315b7b4SJens Wiklander } 597315b7b4SJens Wiklander 6026ed70ecSGuanchao Liang void itr_enable(size_t it) 617315b7b4SJens Wiklander { 6226ed70ecSGuanchao Liang itr_chip->ops->enable(itr_chip, it); 637315b7b4SJens Wiklander } 647315b7b4SJens Wiklander 6526ed70ecSGuanchao Liang void itr_disable(size_t it) 667315b7b4SJens Wiklander { 6726ed70ecSGuanchao Liang itr_chip->ops->disable(itr_chip, it); 6826ed70ecSGuanchao Liang } 6926ed70ecSGuanchao Liang 7026ed70ecSGuanchao Liang void itr_raise_pi(size_t it) 7126ed70ecSGuanchao Liang { 7226ed70ecSGuanchao Liang itr_chip->ops->raise_pi(itr_chip, it); 7326ed70ecSGuanchao Liang } 7426ed70ecSGuanchao Liang 7526ed70ecSGuanchao Liang void itr_raise_sgi(size_t it, uint8_t cpu_mask) 7626ed70ecSGuanchao Liang { 7726ed70ecSGuanchao Liang itr_chip->ops->raise_sgi(itr_chip, it, cpu_mask); 7826ed70ecSGuanchao Liang } 7926ed70ecSGuanchao Liang 8026ed70ecSGuanchao Liang void itr_set_affinity(size_t it, uint8_t cpu_mask) 8126ed70ecSGuanchao Liang { 8226ed70ecSGuanchao Liang itr_chip->ops->set_affinity(itr_chip, it, cpu_mask); 837315b7b4SJens Wiklander } 84e9f46c74SJens Wiklander 85e9f46c74SJens Wiklander /* This function is supposed to be overridden in platform specific code */ 86e9f46c74SJens Wiklander void __weak __noreturn itr_core_handler(void) 87e9f46c74SJens Wiklander { 88e9f46c74SJens Wiklander panic("Secure interrupt handler not defined"); 89e9f46c74SJens Wiklander } 90