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
25*38376d36SJens Wiklander #define HF_MAILBOX_READABLE_INTID 1
26*38376d36SJens Wiklander #define HF_MAILBOX_WRITABLE_INTID 2
27*38376d36SJens Wiklander #define HF_VIRTUAL_TIMER_INTID 3
28e37b526dSJens Wiklander #define HF_MANAGED_EXIT_INTID 4
29*38376d36SJens Wiklander #define HF_NOTIFICATION_PENDING_INTID 5
30*38376d36SJens Wiklander #define HF_IPI_INTID 9
31e37b526dSJens Wiklander
32e37b526dSJens Wiklander #define HF_INTERRUPT_TYPE_IRQ 0
33e37b526dSJens Wiklander #define HF_INTERRUPT_TYPE_FIQ 1
34e37b526dSJens Wiklander #define HF_ENABLE 1
35e37b526dSJens Wiklander #define HF_DISABLE 0
36e37b526dSJens Wiklander
3749655078SJens Wiklander #define HF_INT_RECONFIGURE_STATUS 2
3849655078SJens Wiklander
3967e55c51SEtienne Carriere struct hfic_data {
4067e55c51SEtienne Carriere struct itr_chip chip;
4167e55c51SEtienne Carriere };
4267e55c51SEtienne Carriere
4367e55c51SEtienne Carriere static struct hfic_data hfic_data __nex_bss;
4467e55c51SEtienne Carriere
hfic_static_it(size_t it)45*38376d36SJens Wiklander static bool __maybe_unused hfic_static_it(size_t it)
46*38376d36SJens Wiklander {
47*38376d36SJens Wiklander switch (it) {
48*38376d36SJens Wiklander case HF_MAILBOX_READABLE_INTID:
49*38376d36SJens Wiklander case HF_MAILBOX_WRITABLE_INTID:
50*38376d36SJens Wiklander case HF_VIRTUAL_TIMER_INTID:
51*38376d36SJens Wiklander case HF_MANAGED_EXIT_INTID:
52*38376d36SJens Wiklander case HF_NOTIFICATION_PENDING_INTID:
53*38376d36SJens Wiklander case HF_IPI_INTID:
54*38376d36SJens Wiklander return true;
55*38376d36SJens Wiklander default:
56*38376d36SJens Wiklander return false;
57*38376d36SJens Wiklander }
58*38376d36SJens Wiklander }
59*38376d36SJens Wiklander
hfic_op_configure(struct itr_chip * chip __unused,size_t it,uint32_t type __unused,uint32_t prio __unused)602a50ce7dSEtienne Carriere static void hfic_op_configure(struct itr_chip *chip __unused, size_t it,
61a0602052SJens Wiklander uint32_t type __unused, uint32_t prio __unused)
62a0602052SJens Wiklander {
63a0602052SJens Wiklander uint32_t res __maybe_unused = 0;
64a0602052SJens Wiklander
65a0602052SJens Wiklander res = thread_hvc(HF_INTERRUPT_ENABLE, it, HF_ENABLE,
66a0602052SJens Wiklander HF_INTERRUPT_TYPE_IRQ);
67*38376d36SJens Wiklander assert(!res || hfic_static_it(it));
68a0602052SJens Wiklander }
69a0602052SJens Wiklander
hfic_op_enable(struct itr_chip * chip __unused,size_t it)7049655078SJens Wiklander static void hfic_op_enable(struct itr_chip *chip __unused, size_t it)
7149655078SJens Wiklander {
7249655078SJens Wiklander uint32_t res __maybe_unused = 0;
7349655078SJens Wiklander
7449655078SJens Wiklander res = thread_hvc(HF_INTERRUPT_RECONFIGURE, it,
7549655078SJens Wiklander HF_INT_RECONFIGURE_STATUS, HF_ENABLE);
76*38376d36SJens Wiklander assert(!res || hfic_static_it(it));
7749655078SJens Wiklander }
7849655078SJens Wiklander
hfic_op_disable(struct itr_chip * chip __unused,size_t it)79a0602052SJens Wiklander static void hfic_op_disable(struct itr_chip *chip __unused, size_t it)
80a0602052SJens Wiklander {
81a0602052SJens Wiklander uint32_t res __maybe_unused = 0;
82a0602052SJens Wiklander
8349655078SJens Wiklander res = thread_hvc(HF_INTERRUPT_RECONFIGURE, it,
8449655078SJens Wiklander HF_INT_RECONFIGURE_STATUS, HF_DISABLE);
85*38376d36SJens Wiklander assert(!res || hfic_static_it(it));
86a0602052SJens Wiklander }
87a0602052SJens Wiklander
88a0602052SJens Wiklander static const struct itr_ops hfic_ops = {
892a50ce7dSEtienne Carriere .configure = hfic_op_configure,
9059feef28SEtienne Carriere .mask = hfic_op_disable,
9159feef28SEtienne Carriere .unmask = hfic_op_enable,
92a0602052SJens Wiklander .enable = hfic_op_enable,
93a0602052SJens Wiklander .disable = hfic_op_disable,
94a0602052SJens Wiklander };
95a0602052SJens Wiklander
hfic_init(void)9667e55c51SEtienne Carriere void hfic_init(void)
97a0602052SJens Wiklander {
9867e55c51SEtienne Carriere hfic_data.chip.ops = &hfic_ops;
9901980f3fSEtienne Carriere interrupt_main_init(&hfic_data.chip);
100a0602052SJens Wiklander }
101a0602052SJens Wiklander
102358bf47cSEtienne Carriere /* Override interrupt_main_handler() with driver implementation */
interrupt_main_handler(void)103358bf47cSEtienne Carriere void interrupt_main_handler(void)
104a0602052SJens Wiklander {
105a0602052SJens Wiklander uint32_t id = 0;
106a0602052SJens Wiklander uint32_t res __maybe_unused = 0;
107a0602052SJens Wiklander
108a0602052SJens Wiklander id = thread_hvc(HF_INTERRUPT_GET, 0, 0, 0);
109a0602052SJens Wiklander if (id == HF_INVALID_INTID) {
110a0602052SJens Wiklander DMSG("ignoring invalid interrupt %#"PRIx32, id);
111a0602052SJens Wiklander return;
112a0602052SJens Wiklander }
113a0602052SJens Wiklander
11499e2612cSEtienne Carriere interrupt_call_handlers(&hfic_data.chip, id);
11599e2612cSEtienne Carriere
116a0602052SJens Wiklander res = thread_hvc(HF_INTERRUPT_DEACTIVATE, id, id, 0);
117a0602052SJens Wiklander assert(!res);
118a0602052SJens Wiklander }
119