1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2016, Linaro Limited 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <kernel/interrupt.h> 30 #include <trace.h> 31 32 /* 33 * NOTE! 34 * 35 * We're assuming that there's no concurrent use of this interface, except 36 * delivery of interrupts in parallel. Synchronization will be needed when 37 * we begin to modify settings after boot initialization. 38 */ 39 40 static struct itr_chip *itr_chip; 41 static SLIST_HEAD(, itr_handler) handlers = SLIST_HEAD_INITIALIZER(handlers); 42 43 void itr_init(struct itr_chip *chip) 44 { 45 itr_chip = chip; 46 } 47 48 static struct itr_handler *find_handler(size_t it) 49 { 50 struct itr_handler *h; 51 52 SLIST_FOREACH(h, &handlers, link) 53 if (h->it == it) 54 return h; 55 return NULL; 56 } 57 58 void itr_handle(size_t it) 59 { 60 struct itr_handler *h = find_handler(it); 61 62 if (!h) { 63 EMSG("Disabling unhandled interrupt %zu", it); 64 itr_chip->ops->disable(itr_chip, it); 65 return; 66 } 67 68 if (h->handler(h) != ITRR_HANDLED) { 69 EMSG("Disabling interrupt %zu not handled by handler", it); 70 itr_chip->ops->disable(itr_chip, it); 71 } 72 } 73 74 void itr_add(struct itr_handler *h) 75 { 76 itr_chip->ops->add(itr_chip, h->it, h->flags); 77 SLIST_INSERT_HEAD(&handlers, h, link); 78 } 79 80 void itr_enable(size_t it) 81 { 82 itr_chip->ops->enable(itr_chip, it); 83 } 84 85 void itr_disable(size_t it) 86 { 87 itr_chip->ops->disable(itr_chip, it); 88 } 89 90 void itr_raise_pi(size_t it) 91 { 92 itr_chip->ops->raise_pi(itr_chip, it); 93 } 94 95 void itr_raise_sgi(size_t it, uint8_t cpu_mask) 96 { 97 itr_chip->ops->raise_sgi(itr_chip, it, cpu_mask); 98 } 99 100 void itr_set_affinity(size_t it, uint8_t cpu_mask) 101 { 102 itr_chip->ops->set_affinity(itr_chip, it, cpu_mask); 103 } 104