11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 27315b7b4SJens Wiklander /* 3*e9f46c74SJens Wiklander * Copyright (c) 2016-2019, Linaro Limited 47315b7b4SJens Wiklander */ 57315b7b4SJens Wiklander 67315b7b4SJens Wiklander #include <kernel/interrupt.h> 7*e9f46c74SJens Wiklander #include <kernel/panic.h> 87315b7b4SJens Wiklander #include <trace.h> 97315b7b4SJens Wiklander 107315b7b4SJens Wiklander /* 117315b7b4SJens Wiklander * NOTE! 127315b7b4SJens Wiklander * 137315b7b4SJens Wiklander * We're assuming that there's no concurrent use of this interface, except 147315b7b4SJens Wiklander * delivery of interrupts in parallel. Synchronization will be needed when 157315b7b4SJens Wiklander * we begin to modify settings after boot initialization. 167315b7b4SJens Wiklander */ 177315b7b4SJens Wiklander 187315b7b4SJens Wiklander static struct itr_chip *itr_chip; 197315b7b4SJens Wiklander static SLIST_HEAD(, itr_handler) handlers = SLIST_HEAD_INITIALIZER(handlers); 207315b7b4SJens Wiklander 217315b7b4SJens Wiklander void itr_init(struct itr_chip *chip) 227315b7b4SJens Wiklander { 237315b7b4SJens Wiklander itr_chip = chip; 247315b7b4SJens Wiklander } 257315b7b4SJens Wiklander 267315b7b4SJens Wiklander static struct itr_handler *find_handler(size_t it) 277315b7b4SJens Wiklander { 287315b7b4SJens Wiklander struct itr_handler *h; 297315b7b4SJens Wiklander 307315b7b4SJens Wiklander SLIST_FOREACH(h, &handlers, link) 317315b7b4SJens Wiklander if (h->it == it) 327315b7b4SJens Wiklander return h; 337315b7b4SJens Wiklander return NULL; 347315b7b4SJens Wiklander } 357315b7b4SJens Wiklander 367315b7b4SJens Wiklander void itr_handle(size_t it) 377315b7b4SJens Wiklander { 387315b7b4SJens Wiklander struct itr_handler *h = find_handler(it); 397315b7b4SJens Wiklander 407315b7b4SJens Wiklander if (!h) { 417315b7b4SJens Wiklander EMSG("Disabling unhandled interrupt %zu", it); 427315b7b4SJens Wiklander itr_chip->ops->disable(itr_chip, it); 437315b7b4SJens Wiklander return; 447315b7b4SJens Wiklander } 457315b7b4SJens Wiklander 467315b7b4SJens Wiklander if (h->handler(h) != ITRR_HANDLED) { 477315b7b4SJens Wiklander EMSG("Disabling interrupt %zu not handled by handler", it); 487315b7b4SJens Wiklander itr_chip->ops->disable(itr_chip, it); 497315b7b4SJens Wiklander } 507315b7b4SJens Wiklander } 517315b7b4SJens Wiklander 527315b7b4SJens Wiklander void itr_add(struct itr_handler *h) 537315b7b4SJens Wiklander { 547315b7b4SJens Wiklander itr_chip->ops->add(itr_chip, h->it, h->flags); 557315b7b4SJens Wiklander SLIST_INSERT_HEAD(&handlers, h, link); 567315b7b4SJens Wiklander } 577315b7b4SJens Wiklander 5826ed70ecSGuanchao Liang void itr_enable(size_t it) 597315b7b4SJens Wiklander { 6026ed70ecSGuanchao Liang itr_chip->ops->enable(itr_chip, it); 617315b7b4SJens Wiklander } 627315b7b4SJens Wiklander 6326ed70ecSGuanchao Liang void itr_disable(size_t it) 647315b7b4SJens Wiklander { 6526ed70ecSGuanchao Liang itr_chip->ops->disable(itr_chip, it); 6626ed70ecSGuanchao Liang } 6726ed70ecSGuanchao Liang 6826ed70ecSGuanchao Liang void itr_raise_pi(size_t it) 6926ed70ecSGuanchao Liang { 7026ed70ecSGuanchao Liang itr_chip->ops->raise_pi(itr_chip, it); 7126ed70ecSGuanchao Liang } 7226ed70ecSGuanchao Liang 7326ed70ecSGuanchao Liang void itr_raise_sgi(size_t it, uint8_t cpu_mask) 7426ed70ecSGuanchao Liang { 7526ed70ecSGuanchao Liang itr_chip->ops->raise_sgi(itr_chip, it, cpu_mask); 7626ed70ecSGuanchao Liang } 7726ed70ecSGuanchao Liang 7826ed70ecSGuanchao Liang void itr_set_affinity(size_t it, uint8_t cpu_mask) 7926ed70ecSGuanchao Liang { 8026ed70ecSGuanchao Liang itr_chip->ops->set_affinity(itr_chip, it, cpu_mask); 817315b7b4SJens Wiklander } 82*e9f46c74SJens Wiklander 83*e9f46c74SJens Wiklander /* This function is supposed to be overridden in platform specific code */ 84*e9f46c74SJens Wiklander void __weak __noreturn itr_core_handler(void) 85*e9f46c74SJens Wiklander { 86*e9f46c74SJens Wiklander panic("Secure interrupt handler not defined"); 87*e9f46c74SJens Wiklander } 88