1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2022, Linaro Limited 4 */ 5 6 #include <assert.h> 7 #include <compiler.h> 8 #include <config.h> 9 #include <drivers/hfic.h> 10 #include <hafnium.h> 11 #include <kernel/interrupt.h> 12 #include <kernel/panic.h> 13 #include <kernel/thread.h> 14 15 struct hfic_data { 16 struct itr_chip chip; 17 }; 18 19 static struct hfic_data hfic_data __nex_bss; 20 21 static void hfic_op_add(struct itr_chip *chip __unused, size_t it __unused, 22 uint32_t type __unused, uint32_t prio __unused) 23 { 24 } 25 26 static void hfic_op_enable(struct itr_chip *chip __unused, size_t it) 27 { 28 uint32_t res __maybe_unused = 0; 29 30 res = thread_hvc(HF_INTERRUPT_ENABLE, it, HF_ENABLE, 31 HF_INTERRUPT_TYPE_IRQ); 32 assert(!res); 33 } 34 35 static void hfic_op_disable(struct itr_chip *chip __unused, size_t it) 36 { 37 uint32_t res __maybe_unused = 0; 38 39 res = thread_hvc(HF_INTERRUPT_ENABLE, it, HF_DISABLE, 40 HF_INTERRUPT_TYPE_IRQ); 41 assert(!res); 42 } 43 44 static void hfic_op_raise_pi(struct itr_chip *chip __unused, size_t it __unused) 45 { 46 panic(); 47 } 48 49 static void hfic_op_raise_sgi(struct itr_chip *chip __unused, 50 size_t it __unused, uint8_t cpu_mask __unused) 51 { 52 panic(); 53 } 54 55 static void hfic_op_set_affinity(struct itr_chip *chip __unused, 56 size_t it __unused, uint8_t cpu_mask __unused) 57 { 58 panic(); 59 } 60 61 static const struct itr_ops hfic_ops = { 62 .add = hfic_op_add, 63 .mask = hfic_op_disable, 64 .unmask = hfic_op_enable, 65 .enable = hfic_op_enable, 66 .disable = hfic_op_disable, 67 .raise_pi = hfic_op_raise_pi, 68 .raise_sgi = hfic_op_raise_sgi, 69 .set_affinity = hfic_op_set_affinity, 70 }; 71 72 void hfic_init(void) 73 { 74 hfic_data.chip.ops = &hfic_ops; 75 interrupt_main_init(&hfic_data.chip); 76 } 77 78 /* Override interrupt_main_handler() with driver implementation */ 79 void interrupt_main_handler(void) 80 { 81 uint32_t id = 0; 82 uint32_t res __maybe_unused = 0; 83 84 id = thread_hvc(HF_INTERRUPT_GET, 0, 0, 0); 85 if (id == HF_INVALID_INTID) { 86 DMSG("ignoring invalid interrupt %#"PRIx32, id); 87 return; 88 } 89 90 itr_handle(id); 91 res = thread_hvc(HF_INTERRUPT_DEACTIVATE, id, id, 0); 92 assert(!res); 93 } 94