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> 91c832d7cSdavidwang #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 19*0c1be93bSVolodymyr Babchuk static struct itr_chip *itr_chip __nex_bss; 20*0c1be93bSVolodymyr Babchuk static SLIST_HEAD(, itr_handler) handlers __nex_data = 21*0c1be93bSVolodymyr Babchuk SLIST_HEAD_INITIALIZER(handlers); 227315b7b4SJens Wiklander 237315b7b4SJens Wiklander void itr_init(struct itr_chip *chip) 247315b7b4SJens Wiklander { 257315b7b4SJens Wiklander itr_chip = chip; 267315b7b4SJens Wiklander } 277315b7b4SJens Wiklander 287315b7b4SJens Wiklander void itr_handle(size_t it) 297315b7b4SJens Wiklander { 301c832d7cSdavidwang struct itr_handler *h = NULL; 311c832d7cSdavidwang bool was_handled = false; 327315b7b4SJens Wiklander 331c832d7cSdavidwang SLIST_FOREACH(h, &handlers, link) { 341c832d7cSdavidwang if (h->it == it) { 351c832d7cSdavidwang if (h->handler(h) == ITRR_HANDLED) 361c832d7cSdavidwang was_handled = true; 371c832d7cSdavidwang else if (!(h->flags & ITRF_SHARED)) 381c832d7cSdavidwang break; 391c832d7cSdavidwang } 407315b7b4SJens Wiklander } 417315b7b4SJens Wiklander 421c832d7cSdavidwang if (!was_handled) { 431c832d7cSdavidwang EMSG("Disabling unhandled interrupt %zu", it); 447315b7b4SJens Wiklander itr_chip->ops->disable(itr_chip, it); 457315b7b4SJens Wiklander } 467315b7b4SJens Wiklander } 477315b7b4SJens Wiklander 487315b7b4SJens Wiklander void itr_add(struct itr_handler *h) 497315b7b4SJens Wiklander { 501c832d7cSdavidwang struct itr_handler __maybe_unused *hdl = NULL; 511c832d7cSdavidwang 521c832d7cSdavidwang SLIST_FOREACH(hdl, &handlers, link) 531c832d7cSdavidwang if (hdl->it == h->it) 541c832d7cSdavidwang assert((hdl->flags & ITRF_SHARED) && 551c832d7cSdavidwang (h->flags & ITRF_SHARED)); 561c832d7cSdavidwang 577315b7b4SJens Wiklander itr_chip->ops->add(itr_chip, h->it, h->flags); 587315b7b4SJens Wiklander SLIST_INSERT_HEAD(&handlers, h, link); 597315b7b4SJens Wiklander } 607315b7b4SJens Wiklander 6126ed70ecSGuanchao Liang void itr_enable(size_t it) 627315b7b4SJens Wiklander { 6326ed70ecSGuanchao Liang itr_chip->ops->enable(itr_chip, it); 647315b7b4SJens Wiklander } 657315b7b4SJens Wiklander 6626ed70ecSGuanchao Liang void itr_disable(size_t it) 677315b7b4SJens Wiklander { 6826ed70ecSGuanchao Liang itr_chip->ops->disable(itr_chip, it); 6926ed70ecSGuanchao Liang } 7026ed70ecSGuanchao Liang 7126ed70ecSGuanchao Liang void itr_raise_pi(size_t it) 7226ed70ecSGuanchao Liang { 7326ed70ecSGuanchao Liang itr_chip->ops->raise_pi(itr_chip, it); 7426ed70ecSGuanchao Liang } 7526ed70ecSGuanchao Liang 7626ed70ecSGuanchao Liang void itr_raise_sgi(size_t it, uint8_t cpu_mask) 7726ed70ecSGuanchao Liang { 7826ed70ecSGuanchao Liang itr_chip->ops->raise_sgi(itr_chip, it, cpu_mask); 7926ed70ecSGuanchao Liang } 8026ed70ecSGuanchao Liang 8126ed70ecSGuanchao Liang void itr_set_affinity(size_t it, uint8_t cpu_mask) 8226ed70ecSGuanchao Liang { 8326ed70ecSGuanchao Liang itr_chip->ops->set_affinity(itr_chip, it, cpu_mask); 847315b7b4SJens Wiklander } 85e9f46c74SJens Wiklander 86e9f46c74SJens Wiklander /* This function is supposed to be overridden in platform specific code */ 87e9f46c74SJens Wiklander void __weak __noreturn itr_core_handler(void) 88e9f46c74SJens Wiklander { 89e9f46c74SJens Wiklander panic("Secure interrupt handler not defined"); 90e9f46c74SJens Wiklander } 91