1a0602052SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause 2a0602052SJens Wiklander /* 3a0602052SJens Wiklander * Copyright (c) 2022, Linaro Limited 4a0602052SJens Wiklander */ 5a0602052SJens Wiklander 6a0602052SJens Wiklander #include <assert.h> 767e55c51SEtienne Carriere #include <compiler.h> 8a0602052SJens Wiklander #include <config.h> 9a0602052SJens Wiklander #include <drivers/hfic.h> 10a0602052SJens Wiklander #include <kernel/interrupt.h> 11a0602052SJens Wiklander #include <kernel/panic.h> 12a0602052SJens Wiklander #include <kernel/thread.h> 13a0602052SJens Wiklander 14e37b526dSJens Wiklander /* 15e37b526dSJens Wiklander * For documentation of the paravirtualized interface see: 16e37b526dSJens Wiklander * https://hafnium.readthedocs.io/en/latest/design/secure-partition-manager.html#paravirtualized-interfaces 17e37b526dSJens Wiklander */ 18e37b526dSJens Wiklander 19e37b526dSJens Wiklander #define HF_INTERRUPT_ENABLE 0xff03 20e37b526dSJens Wiklander #define HF_INTERRUPT_GET 0xff04 21e37b526dSJens Wiklander #define HF_INTERRUPT_DEACTIVATE 0xff08 2249655078SJens Wiklander #define HF_INTERRUPT_RECONFIGURE 0xff09 23e37b526dSJens Wiklander 24e37b526dSJens Wiklander #define HF_INVALID_INTID 0xffffffff 25e37b526dSJens Wiklander #define HF_MANAGED_EXIT_INTID 4 26e37b526dSJens Wiklander 27e37b526dSJens Wiklander #define HF_INTERRUPT_TYPE_IRQ 0 28e37b526dSJens Wiklander #define HF_INTERRUPT_TYPE_FIQ 1 29e37b526dSJens Wiklander #define HF_ENABLE 1 30e37b526dSJens Wiklander #define HF_DISABLE 0 31e37b526dSJens Wiklander 3249655078SJens Wiklander #define HF_INT_RECONFIGURE_STATUS 2 3349655078SJens Wiklander 3467e55c51SEtienne Carriere struct hfic_data { 3567e55c51SEtienne Carriere struct itr_chip chip; 3667e55c51SEtienne Carriere }; 3767e55c51SEtienne Carriere 3867e55c51SEtienne Carriere static struct hfic_data hfic_data __nex_bss; 3967e55c51SEtienne Carriere 40*2a50ce7dSEtienne Carriere static void hfic_op_configure(struct itr_chip *chip __unused, size_t it, 41a0602052SJens Wiklander uint32_t type __unused, uint32_t prio __unused) 42a0602052SJens Wiklander { 43a0602052SJens Wiklander uint32_t res __maybe_unused = 0; 44a0602052SJens Wiklander 45a0602052SJens Wiklander res = thread_hvc(HF_INTERRUPT_ENABLE, it, HF_ENABLE, 46a0602052SJens Wiklander HF_INTERRUPT_TYPE_IRQ); 47a0602052SJens Wiklander assert(!res); 48a0602052SJens Wiklander } 49a0602052SJens Wiklander 5049655078SJens Wiklander static void hfic_op_enable(struct itr_chip *chip __unused, size_t it) 5149655078SJens Wiklander { 5249655078SJens Wiklander uint32_t res __maybe_unused = 0; 5349655078SJens Wiklander 5449655078SJens Wiklander res = thread_hvc(HF_INTERRUPT_RECONFIGURE, it, 5549655078SJens Wiklander HF_INT_RECONFIGURE_STATUS, HF_ENABLE); 5649655078SJens Wiklander assert(!res); 5749655078SJens Wiklander } 5849655078SJens Wiklander 59a0602052SJens Wiklander static void hfic_op_disable(struct itr_chip *chip __unused, size_t it) 60a0602052SJens Wiklander { 61a0602052SJens Wiklander uint32_t res __maybe_unused = 0; 62a0602052SJens Wiklander 6349655078SJens Wiklander res = thread_hvc(HF_INTERRUPT_RECONFIGURE, it, 6449655078SJens Wiklander HF_INT_RECONFIGURE_STATUS, HF_DISABLE); 65a0602052SJens Wiklander assert(!res); 66a0602052SJens Wiklander } 67a0602052SJens Wiklander 68a0602052SJens Wiklander static const struct itr_ops hfic_ops = { 69*2a50ce7dSEtienne Carriere .configure = hfic_op_configure, 7059feef28SEtienne Carriere .mask = hfic_op_disable, 7159feef28SEtienne Carriere .unmask = hfic_op_enable, 72a0602052SJens Wiklander .enable = hfic_op_enable, 73a0602052SJens Wiklander .disable = hfic_op_disable, 74a0602052SJens Wiklander }; 75a0602052SJens Wiklander 7667e55c51SEtienne Carriere void hfic_init(void) 77a0602052SJens Wiklander { 7867e55c51SEtienne Carriere hfic_data.chip.ops = &hfic_ops; 7901980f3fSEtienne Carriere interrupt_main_init(&hfic_data.chip); 80a0602052SJens Wiklander } 81a0602052SJens Wiklander 82358bf47cSEtienne Carriere /* Override interrupt_main_handler() with driver implementation */ 83358bf47cSEtienne Carriere void interrupt_main_handler(void) 84a0602052SJens Wiklander { 85a0602052SJens Wiklander uint32_t id = 0; 86a0602052SJens Wiklander uint32_t res __maybe_unused = 0; 87a0602052SJens Wiklander 88a0602052SJens Wiklander id = thread_hvc(HF_INTERRUPT_GET, 0, 0, 0); 89a0602052SJens Wiklander if (id == HF_INVALID_INTID) { 90a0602052SJens Wiklander DMSG("ignoring invalid interrupt %#"PRIx32, id); 91a0602052SJens Wiklander return; 92a0602052SJens Wiklander } 93a0602052SJens Wiklander 9499e2612cSEtienne Carriere interrupt_call_handlers(&hfic_data.chip, id); 9599e2612cSEtienne Carriere 96a0602052SJens Wiklander res = thread_hvc(HF_INTERRUPT_DEACTIVATE, id, id, 0); 97a0602052SJens Wiklander assert(!res); 98a0602052SJens Wiklander } 99