diff --git a/bootloader/soc/irq.c b/bootloader/soc/irq.c
new file mode 100644
index 0000000..627976d
--- /dev/null
+++ b/bootloader/soc/irq.c
@@ -0,0 +1,263 @@
+/*
+ * BPMP-Lite IRQ driver for Tegra X1
+ *
+ * Copyright (c) 2019 CTCaer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+
+#include "irq.h"
+#include "t210.h"
+#include "../gfx/gfx.h"
+#include "../mem/heap.h"
+
+//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
+#define DPRINTF(...)
+
+extern void irq_disable();
+extern void irq_enable_cpu_irq_exceptions();
+extern void irq_disable_cpu_irq_exceptions();
+
+typedef struct _irq_ctxt_t
+{
+ u32 irq;
+ int (*handler)(u32 irq, void *data);
+ void *data;
+ u32 flags;
+} irq_ctxt_t;
+
+bool irq_init_done = false;
+irq_ctxt_t irqs[IRQ_MAX_HANDLERS];
+
+static void _irq_enable_source(u32 irq)
+{
+ u32 ctrl_idx = irq >> 5;
+ u32 bit = irq % 32;
+
+ // Set as normal IRQ.
+ ICTLR(ctrl_idx, PRI_ICTLR_COP_IEP_CLASS) &= ~(1 << bit);
+
+ // Enable IRQ source.
+ ICTLR(ctrl_idx, PRI_ICTLR_COP_IER_SET) = 1 << bit;
+}
+
+static void _irq_disable_source(u32 irq)
+{
+ u32 ctrl_idx = irq >> 5;
+ u32 bit = irq % 32;
+
+ // Disable IRQ source.
+ ICTLR(ctrl_idx, PRI_ICTLR_COP_IER_CLR) = 1 << bit;
+}
+
+static void _irq_disable_and_ack_all()
+{
+ // Disable and ack all IRQ sources.
+ for (u32 ctrl_idx = 0; ctrl_idx < 6; ctrl_idx++)
+ {
+ u32 enabled_irqs = ICTLR(ctrl_idx, PRI_ICTLR_COP_IER);
+ ICTLR(ctrl_idx, PRI_ICTLR_COP_IER_CLR) = enabled_irqs;
+ ICTLR(ctrl_idx, PRI_ICTLR_FIR_CLR) = enabled_irqs;
+ }
+}
+
+static void _irq_ack_source(u32 irq)
+{
+ u32 ctrl_idx = irq >> 5;
+ u32 bit = irq % 32;
+
+ // Force stop the interrupt as it's serviced here.
+ ICTLR(ctrl_idx, PRI_ICTLR_FIR_CLR) = 1 << bit;
+}
+
+void irq_free(u32 irq)
+{
+ for (u32 idx = 0; idx < IRQ_MAX_HANDLERS; idx++)
+ {
+ if (irqs[idx].irq == irq && irqs[idx].handler)
+ {
+ irqs[idx].irq = 0;
+ irqs[idx].handler = NULL;
+ irqs[idx].data = NULL;
+ irqs[idx].flags = 0;
+
+ _irq_disable_source(irq);
+ }
+ }
+}
+
+static void _irq_free_all()
+{
+ for (u32 idx = 0; idx < IRQ_MAX_HANDLERS; idx++)
+ {
+ if (irqs[idx].handler)
+ {
+ _irq_disable_source(irqs[idx].irq);
+
+ irqs[idx].irq = 0;
+ irqs[idx].handler = NULL;
+ irqs[idx].data = NULL;
+ irqs[idx].flags = 0;
+ }
+ }
+}
+
+static irq_status_t _irq_handle_source(u32 irq)
+{
+ int status = IRQ_NONE;
+
+ _irq_disable_source(irq);
+ _irq_ack_source(irq);
+
+ u32 idx;
+ for (idx = 0; idx < IRQ_MAX_HANDLERS; idx++)
+ {
+ if (irqs[idx].irq == irq)
+ {
+ status = irqs[idx].handler(irqs[idx].irq, irqs[idx].data);
+
+ if (status == IRQ_HANDLED)
+ break;
+ }
+ }
+
+ if (irqs[idx].flags & IRQ_FLAG_ONE_OFF)
+ irq_free(irq);
+ else
+ _irq_enable_source(irq);
+
+ return status;
+}
+
+void irq_handler()
+{
+ // Get IRQ source.
+ u32 irq = EXCP_VEC(EVP_COP_IRQ_STS) & 0xFF;
+
+ if (!irq_init_done)
+ {
+ _irq_ack_source(irq);
+ return;
+ }
+
+ DPRINTF("IRQ: %d\n", irq);
+
+ int err = _irq_handle_source(irq);
+
+ //TODO: disable if unhandhled.
+ if (err == IRQ_NONE)
+ gfx_printf("Unhandled IRQ: %d\n", irq);
+}
+
+static void _irq_init()
+{
+ _irq_disable_and_ack_all();
+ memset(irqs, 0, sizeof(irq_ctxt_t) * IRQ_MAX_HANDLERS);
+ irq_init_done = true;
+}
+
+void irq_end()
+{
+ _irq_free_all();
+ irq_disable_cpu_irq_exceptions();
+ irq_init_done = false;
+}
+
+void irq_wait_event(u32 irq)
+{
+ irq_disable_cpu_irq_exceptions();
+
+ _irq_enable_source(irq);
+
+ // Halt BPMP and wait for the IRQ. No need to use WAIT_EVENT + LIC_IRQ when BPMP serves the IRQ.
+ FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_COP_STOP_UNTIL_IRQ;
+
+ _irq_disable_source(irq);
+ _irq_ack_source(irq);
+
+ irq_enable_cpu_irq_exceptions();
+}
+
+void irq_disable_wait_event()
+{
+ irq_enable_cpu_irq_exceptions();
+}
+
+irq_status_t irq_request(u32 irq, irq_handler_t handler, void *data, irq_flags_t flags)
+{
+ if (!irq_init_done)
+ _irq_init();
+
+ for (u32 idx = 0; idx < IRQ_MAX_HANDLERS; idx++)
+ {
+ if (irqs[idx].handler == NULL ||
+ (irqs[idx].irq == irq && irqs[idx].flags & IRQ_FLAG_REPLACEABLE))
+ {
+ DPRINTF("Registered handler, IRQ: %d, Slot: %d\n", irq, idx);
+ DPRINTF("Handler: %08p, Flags: %x\n", (u32)handler, flags);
+
+ irqs[idx].irq = irq;
+ irqs[idx].handler = handler;
+ irqs[idx].data = data;
+ irqs[idx].flags = flags;
+
+ _irq_enable_source(irq);
+
+ return IRQ_ENABLED;
+ }
+ else if (irqs[idx].irq == irq)
+ return IRQ_ALREADY_REGISTERED;
+ }
+
+ return IRQ_NO_SLOTS_AVAILABLE;
+}
+
+void __attribute__ ((target("arm"))) fiq_setup()
+{
+/*
+ asm volatile("mrs r12, cpsr\n\t"
+ "bic r12, r12, #0x1F\n\t"
+ "orr r12, r12, #0x11\n\t"
+ "msr cpsr_c, r12\n\t");
+
+ register volatile char *text asm ("r8");
+ register volatile char *uart_tx asm ("r9");
+ register int len asm ("r10");
+
+ len = 5;
+ uart_tx = (char *)0x70006040;
+ memcpy((char *)text, "FIQ\r\n", len);
+ *uart_tx = 0;
+
+ asm volatile("mrs r12, cpsr\n"
+ "orr r12, r12, #0x1F\n"
+ "msr cpsr_c, r12");
+*/
+}
+
+void __attribute__ ((target("arm"), interrupt ("FIQ"))) fiq_handler()
+{
+/*
+ register volatile char *text asm ("r8");
+ register volatile char *uart_tx asm ("r9");
+ register int len asm ("r10");
+
+ while (len)
+ {
+ *uart_tx = *text++;
+ len--;
+ }
+*/
+}
diff --git a/bootloader/soc/irq.h b/bootloader/soc/irq.h
new file mode 100644
index 0000000..c77d980
--- /dev/null
+++ b/bootloader/soc/irq.h
@@ -0,0 +1,222 @@
+/*
+ * BPMP-Lite IRQ driver for Tegra X1
+ *
+ * Copyright (c) 2019 CTCaer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef IRQ_H
+#define IRQ_H
+
+#include "../utils/types.h"
+
+#define IRQ_MAX_HANDLERS 16
+
+/* Primary interrupt controller ids */
+#define IRQ_TMR1 0
+#define IRQ_TMR2 1
+#define IRQ_RTC 2
+#define IRQ_CEC 3
+#define IRQ_SHR_SEM_INBOX_FULL 4
+#define IRQ_SHR_SEM_INBOX_EMPTY 5
+#define IRQ_SHR_SEM_OUTBOX_FULL 6
+#define IRQ_SHR_SEM_OUTBOX_EMPTY 7
+#define IRQ_NVJPEG 8
+#define IRQ_NVDEC 9
+#define IRQ_QUAD_SPI 10
+#define IRQ_DPAUX_INT1 11
+#define IRQ_SATA_RX_STAT 13
+#define IRQ_SDMMC1 14
+#define IRQ_SDMMC2 15
+#define IRQ_VGPIO_INT 16
+#define IRQ_VII2C_INT 17
+#define IRQ_SDMMC3 19
+#define IRQ_USB 20
+#define IRQ_USB2 21
+#define IRQ_SATA_CTL 23
+#define IRQ_PMC_INT 24
+#define IRQ_FC_INT 25
+#define IRQ_APB_DMA_CPU 26
+#define IRQ_ARB_SEM_GNT_COP 28
+#define IRQ_ARB_SEM_GNT_CPU 29
+#define IRQ_SDMMC4 31
+
+/* Secondary interrupt controller ids */
+#define IRQ_GPIO1 32
+#define IRQ_GPIO2 33
+#define IRQ_GPIO3 34
+#define IRQ_GPIO4 35
+#define IRQ_UARTA 36
+#define IRQ_UARTB 37
+#define IRQ_I2C 38
+#define IRQ_USB3_HOST_INT 39
+#define IRQ_USB3_HOST_SMI 40
+#define IRQ_TMR3 41
+#define IRQ_TMR4 42
+#define IRQ_USB3_HOST_PME 43
+#define IRQ_USB3_DEV_HOST 44
+#define IRQ_ACTMON 45
+#define IRQ_UARTC 46
+#define IRQ_THERMAL 48
+#define IRQ_XUSB_PADCTL 49
+#define IRQ_TSEC 50
+#define IRQ_EDP 51
+#define IRQ_I2C5 53
+#define IRQ_GPIO5 55
+#define IRQ_USB3_DEV_SMI 56
+#define IRQ_USB3_DEV_PME 57
+#define IRQ_SE 58
+#define IRQ_SPI1 59
+#define IRQ_APB_DMA_COP 60
+#define IRQ_CLDVFS 62
+#define IRQ_I2C6 63
+
+/* Tertiary interrupt controller ids */
+#define IRQ_HOST1X_SYNCPT_COP 64
+#define IRQ_HOST1X_SYNCPT_CPU 65
+#define IRQ_HOST1X_GEN_COP 66
+#define IRQ_HOST1X_GEN_CPU 67
+#define IRQ_NVENC 68
+#define IRQ_VI 69
+#define IRQ_ISPB 70
+#define IRQ_ISP 71
+#define IRQ_VIC 72
+#define IRQ_DISPLAY 73
+#define IRQ_DISPLAYB 74
+#define IRQ_SOR1 75
+#define IRQ_SOR 76
+#define IRQ_MC 77
+#define IRQ_EMC 78
+#define IRQ_TSECB 80
+#define IRQ_HDA 81
+#define IRQ_SPI2 82
+#define IRQ_SPI3 83
+#define IRQ_I2C2 84
+#define IRQ_PMU_EXT 86
+#define IRQ_GPIO6 87
+#define IRQ_GPIO7 89
+#define IRQ_UARTD 90
+#define IRQ_I2C3 92
+#define IRQ_SPI4 93
+
+/* Quaternary interrupt controller ids */
+#define IRQ_DTV 96
+#define IRQ_PCIE_INT 98
+#define IRQ_PCIE_MSI 99
+#define IRQ_AVP_CACHE 101
+#define IRQ_APE_INT1 102
+#define IRQ_APE_INT0 103
+#define IRQ_APB_DMA_CH0 104
+#define IRQ_APB_DMA_CH1 105
+#define IRQ_APB_DMA_CH2 106
+#define IRQ_APB_DMA_CH3 107
+#define IRQ_APB_DMA_CH4 108
+#define IRQ_APB_DMA_CH5 109
+#define IRQ_APB_DMA_CH6 110
+#define IRQ_APB_DMA_CH7 111
+#define IRQ_APB_DMA_CH8 112
+#define IRQ_APB_DMA_CH9 113
+#define IRQ_APB_DMA_CH10 114
+#define IRQ_APB_DMA_CH11 115
+#define IRQ_APB_DMA_CH12 116
+#define IRQ_APB_DMA_CH13 117
+#define IRQ_APB_DMA_CH14 118
+#define IRQ_APB_DMA_CH15 119
+#define IRQ_I2C4 120
+#define IRQ_TMR5 121
+#define IRQ_WDT_CPU 123
+#define IRQ_WDT_AVP 124
+#define IRQ_GPIO8 125
+#define IRQ_CAR 126
+
+/* Quinary interrupt controller ids */
+#define IRQ_APB_DMA_CH16 128
+#define IRQ_APB_DMA_CH17 129
+#define IRQ_APB_DMA_CH18 130
+#define IRQ_APB_DMA_CH19 131
+#define IRQ_APB_DMA_CH20 132
+#define IRQ_APB_DMA_CH21 133
+#define IRQ_APB_DMA_CH22 134
+#define IRQ_APB_DMA_CH23 135
+#define IRQ_APB_DMA_CH24 136
+#define IRQ_APB_DMA_CH25 137
+#define IRQ_APB_DMA_CH26 138
+#define IRQ_APB_DMA_CH27 139
+#define IRQ_APB_DMA_CH28 140
+#define IRQ_APB_DMA_CH29 141
+#define IRQ_APB_DMA_CH30 142
+#define IRQ_APB_DMA_CH31 143
+#define IRQ_CPU0_PMU_INTR 144
+#define IRQ_CPU1_PMU_INTR 145
+#define IRQ_CPU2_PMU_INTR 146
+#define IRQ_CPU3_PMU_INTR 147
+#define IRQ_SDMMC1_SYS 148
+#define IRQ_SDMMC2_SYS 149
+#define IRQ_SDMMC3_SYS 150
+#define IRQ_SDMMC4_SYS 151
+#define IRQ_TMR6 152
+#define IRQ_TMR7 153
+#define IRQ_TMR8 154
+#define IRQ_TMR9 155
+#define IRQ_TMR0 156
+#define IRQ_GPU_STALL 157
+#define IRQ_GPU_NONSTALL 158
+#define IRQ_DPAUX 159
+
+/* Senary interrupt controller ids */
+#define IRQ_MPCORE_AXIERRIRQ 160
+#define IRQ_MPCORE_INTERRIRQ 161
+#define IRQ_EVENT_GPIO_A 162
+#define IRQ_EVENT_GPIO_B 163
+#define IRQ_EVENT_GPIO_C 164
+#define IRQ_FLOW_RSM_CPU 168
+#define IRQ_FLOW_RSM_COP 169
+#define IRQ_TMR_SHARED 170
+#define IRQ_MPCORE_CTIIRQ0 171
+#define IRQ_MPCORE_CTIIRQ1 172
+#define IRQ_MPCORE_CTIIRQ2 173
+#define IRQ_MPCORE_CTIIRQ3 174
+#define IRQ_MSELECT_ERROR 175
+#define IRQ_TMR10 176
+#define IRQ_TMR11 177
+#define IRQ_TMR12 178
+#define IRQ_TMR13 179
+
+typedef int (*irq_handler_t)(u32 irq, void *data);
+
+typedef enum _irq_status_t
+{
+ IRQ_NONE = 0,
+ IRQ_HANDLED = 1,
+ IRQ_ERROR = 2,
+
+ IRQ_ENABLED = 0,
+ IRQ_NO_SLOTS_AVAILABLE = 1,
+ IRQ_ALREADY_REGISTERED = 2
+} irq_status_t;
+
+typedef enum _irq_flags_t
+{
+ IRQ_FLAG_NONE = 0,
+ IRQ_FLAG_ONE_OFF = (1 << 0),
+ IRQ_FLAG_REPLACEABLE = (1 << 1)
+} irq_flags_t;
+
+void irq_end();
+void irq_free(u32 irq);
+void irq_wait_event();
+void irq_disable_wait_event();
+irq_status_t irq_request(u32 irq, irq_handler_t handler, void *data, irq_flags_t flags);
+
+#endif
\ No newline at end of file
diff --git a/nyx/nyx_gui/soc/irq.c b/nyx/nyx_gui/soc/irq.c
new file mode 100644
index 0000000..627976d
--- /dev/null
+++ b/nyx/nyx_gui/soc/irq.c
@@ -0,0 +1,263 @@
+/*
+ * BPMP-Lite IRQ driver for Tegra X1
+ *
+ * Copyright (c) 2019 CTCaer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+
+#include "irq.h"
+#include "t210.h"
+#include "../gfx/gfx.h"
+#include "../mem/heap.h"
+
+//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
+#define DPRINTF(...)
+
+extern void irq_disable();
+extern void irq_enable_cpu_irq_exceptions();
+extern void irq_disable_cpu_irq_exceptions();
+
+typedef struct _irq_ctxt_t
+{
+ u32 irq;
+ int (*handler)(u32 irq, void *data);
+ void *data;
+ u32 flags;
+} irq_ctxt_t;
+
+bool irq_init_done = false;
+irq_ctxt_t irqs[IRQ_MAX_HANDLERS];
+
+static void _irq_enable_source(u32 irq)
+{
+ u32 ctrl_idx = irq >> 5;
+ u32 bit = irq % 32;
+
+ // Set as normal IRQ.
+ ICTLR(ctrl_idx, PRI_ICTLR_COP_IEP_CLASS) &= ~(1 << bit);
+
+ // Enable IRQ source.
+ ICTLR(ctrl_idx, PRI_ICTLR_COP_IER_SET) = 1 << bit;
+}
+
+static void _irq_disable_source(u32 irq)
+{
+ u32 ctrl_idx = irq >> 5;
+ u32 bit = irq % 32;
+
+ // Disable IRQ source.
+ ICTLR(ctrl_idx, PRI_ICTLR_COP_IER_CLR) = 1 << bit;
+}
+
+static void _irq_disable_and_ack_all()
+{
+ // Disable and ack all IRQ sources.
+ for (u32 ctrl_idx = 0; ctrl_idx < 6; ctrl_idx++)
+ {
+ u32 enabled_irqs = ICTLR(ctrl_idx, PRI_ICTLR_COP_IER);
+ ICTLR(ctrl_idx, PRI_ICTLR_COP_IER_CLR) = enabled_irqs;
+ ICTLR(ctrl_idx, PRI_ICTLR_FIR_CLR) = enabled_irqs;
+ }
+}
+
+static void _irq_ack_source(u32 irq)
+{
+ u32 ctrl_idx = irq >> 5;
+ u32 bit = irq % 32;
+
+ // Force stop the interrupt as it's serviced here.
+ ICTLR(ctrl_idx, PRI_ICTLR_FIR_CLR) = 1 << bit;
+}
+
+void irq_free(u32 irq)
+{
+ for (u32 idx = 0; idx < IRQ_MAX_HANDLERS; idx++)
+ {
+ if (irqs[idx].irq == irq && irqs[idx].handler)
+ {
+ irqs[idx].irq = 0;
+ irqs[idx].handler = NULL;
+ irqs[idx].data = NULL;
+ irqs[idx].flags = 0;
+
+ _irq_disable_source(irq);
+ }
+ }
+}
+
+static void _irq_free_all()
+{
+ for (u32 idx = 0; idx < IRQ_MAX_HANDLERS; idx++)
+ {
+ if (irqs[idx].handler)
+ {
+ _irq_disable_source(irqs[idx].irq);
+
+ irqs[idx].irq = 0;
+ irqs[idx].handler = NULL;
+ irqs[idx].data = NULL;
+ irqs[idx].flags = 0;
+ }
+ }
+}
+
+static irq_status_t _irq_handle_source(u32 irq)
+{
+ int status = IRQ_NONE;
+
+ _irq_disable_source(irq);
+ _irq_ack_source(irq);
+
+ u32 idx;
+ for (idx = 0; idx < IRQ_MAX_HANDLERS; idx++)
+ {
+ if (irqs[idx].irq == irq)
+ {
+ status = irqs[idx].handler(irqs[idx].irq, irqs[idx].data);
+
+ if (status == IRQ_HANDLED)
+ break;
+ }
+ }
+
+ if (irqs[idx].flags & IRQ_FLAG_ONE_OFF)
+ irq_free(irq);
+ else
+ _irq_enable_source(irq);
+
+ return status;
+}
+
+void irq_handler()
+{
+ // Get IRQ source.
+ u32 irq = EXCP_VEC(EVP_COP_IRQ_STS) & 0xFF;
+
+ if (!irq_init_done)
+ {
+ _irq_ack_source(irq);
+ return;
+ }
+
+ DPRINTF("IRQ: %d\n", irq);
+
+ int err = _irq_handle_source(irq);
+
+ //TODO: disable if unhandhled.
+ if (err == IRQ_NONE)
+ gfx_printf("Unhandled IRQ: %d\n", irq);
+}
+
+static void _irq_init()
+{
+ _irq_disable_and_ack_all();
+ memset(irqs, 0, sizeof(irq_ctxt_t) * IRQ_MAX_HANDLERS);
+ irq_init_done = true;
+}
+
+void irq_end()
+{
+ _irq_free_all();
+ irq_disable_cpu_irq_exceptions();
+ irq_init_done = false;
+}
+
+void irq_wait_event(u32 irq)
+{
+ irq_disable_cpu_irq_exceptions();
+
+ _irq_enable_source(irq);
+
+ // Halt BPMP and wait for the IRQ. No need to use WAIT_EVENT + LIC_IRQ when BPMP serves the IRQ.
+ FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_COP_STOP_UNTIL_IRQ;
+
+ _irq_disable_source(irq);
+ _irq_ack_source(irq);
+
+ irq_enable_cpu_irq_exceptions();
+}
+
+void irq_disable_wait_event()
+{
+ irq_enable_cpu_irq_exceptions();
+}
+
+irq_status_t irq_request(u32 irq, irq_handler_t handler, void *data, irq_flags_t flags)
+{
+ if (!irq_init_done)
+ _irq_init();
+
+ for (u32 idx = 0; idx < IRQ_MAX_HANDLERS; idx++)
+ {
+ if (irqs[idx].handler == NULL ||
+ (irqs[idx].irq == irq && irqs[idx].flags & IRQ_FLAG_REPLACEABLE))
+ {
+ DPRINTF("Registered handler, IRQ: %d, Slot: %d\n", irq, idx);
+ DPRINTF("Handler: %08p, Flags: %x\n", (u32)handler, flags);
+
+ irqs[idx].irq = irq;
+ irqs[idx].handler = handler;
+ irqs[idx].data = data;
+ irqs[idx].flags = flags;
+
+ _irq_enable_source(irq);
+
+ return IRQ_ENABLED;
+ }
+ else if (irqs[idx].irq == irq)
+ return IRQ_ALREADY_REGISTERED;
+ }
+
+ return IRQ_NO_SLOTS_AVAILABLE;
+}
+
+void __attribute__ ((target("arm"))) fiq_setup()
+{
+/*
+ asm volatile("mrs r12, cpsr\n\t"
+ "bic r12, r12, #0x1F\n\t"
+ "orr r12, r12, #0x11\n\t"
+ "msr cpsr_c, r12\n\t");
+
+ register volatile char *text asm ("r8");
+ register volatile char *uart_tx asm ("r9");
+ register int len asm ("r10");
+
+ len = 5;
+ uart_tx = (char *)0x70006040;
+ memcpy((char *)text, "FIQ\r\n", len);
+ *uart_tx = 0;
+
+ asm volatile("mrs r12, cpsr\n"
+ "orr r12, r12, #0x1F\n"
+ "msr cpsr_c, r12");
+*/
+}
+
+void __attribute__ ((target("arm"), interrupt ("FIQ"))) fiq_handler()
+{
+/*
+ register volatile char *text asm ("r8");
+ register volatile char *uart_tx asm ("r9");
+ register int len asm ("r10");
+
+ while (len)
+ {
+ *uart_tx = *text++;
+ len--;
+ }
+*/
+}
diff --git a/nyx/nyx_gui/soc/irq.h b/nyx/nyx_gui/soc/irq.h
new file mode 100644
index 0000000..c77d980
--- /dev/null
+++ b/nyx/nyx_gui/soc/irq.h
@@ -0,0 +1,222 @@
+/*
+ * BPMP-Lite IRQ driver for Tegra X1
+ *
+ * Copyright (c) 2019 CTCaer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef IRQ_H
+#define IRQ_H
+
+#include "../utils/types.h"
+
+#define IRQ_MAX_HANDLERS 16
+
+/* Primary interrupt controller ids */
+#define IRQ_TMR1 0
+#define IRQ_TMR2 1
+#define IRQ_RTC 2
+#define IRQ_CEC 3
+#define IRQ_SHR_SEM_INBOX_FULL 4
+#define IRQ_SHR_SEM_INBOX_EMPTY 5
+#define IRQ_SHR_SEM_OUTBOX_FULL 6
+#define IRQ_SHR_SEM_OUTBOX_EMPTY 7
+#define IRQ_NVJPEG 8
+#define IRQ_NVDEC 9
+#define IRQ_QUAD_SPI 10
+#define IRQ_DPAUX_INT1 11
+#define IRQ_SATA_RX_STAT 13
+#define IRQ_SDMMC1 14
+#define IRQ_SDMMC2 15
+#define IRQ_VGPIO_INT 16
+#define IRQ_VII2C_INT 17
+#define IRQ_SDMMC3 19
+#define IRQ_USB 20
+#define IRQ_USB2 21
+#define IRQ_SATA_CTL 23
+#define IRQ_PMC_INT 24
+#define IRQ_FC_INT 25
+#define IRQ_APB_DMA_CPU 26
+#define IRQ_ARB_SEM_GNT_COP 28
+#define IRQ_ARB_SEM_GNT_CPU 29
+#define IRQ_SDMMC4 31
+
+/* Secondary interrupt controller ids */
+#define IRQ_GPIO1 32
+#define IRQ_GPIO2 33
+#define IRQ_GPIO3 34
+#define IRQ_GPIO4 35
+#define IRQ_UARTA 36
+#define IRQ_UARTB 37
+#define IRQ_I2C 38
+#define IRQ_USB3_HOST_INT 39
+#define IRQ_USB3_HOST_SMI 40
+#define IRQ_TMR3 41
+#define IRQ_TMR4 42
+#define IRQ_USB3_HOST_PME 43
+#define IRQ_USB3_DEV_HOST 44
+#define IRQ_ACTMON 45
+#define IRQ_UARTC 46
+#define IRQ_THERMAL 48
+#define IRQ_XUSB_PADCTL 49
+#define IRQ_TSEC 50
+#define IRQ_EDP 51
+#define IRQ_I2C5 53
+#define IRQ_GPIO5 55
+#define IRQ_USB3_DEV_SMI 56
+#define IRQ_USB3_DEV_PME 57
+#define IRQ_SE 58
+#define IRQ_SPI1 59
+#define IRQ_APB_DMA_COP 60
+#define IRQ_CLDVFS 62
+#define IRQ_I2C6 63
+
+/* Tertiary interrupt controller ids */
+#define IRQ_HOST1X_SYNCPT_COP 64
+#define IRQ_HOST1X_SYNCPT_CPU 65
+#define IRQ_HOST1X_GEN_COP 66
+#define IRQ_HOST1X_GEN_CPU 67
+#define IRQ_NVENC 68
+#define IRQ_VI 69
+#define IRQ_ISPB 70
+#define IRQ_ISP 71
+#define IRQ_VIC 72
+#define IRQ_DISPLAY 73
+#define IRQ_DISPLAYB 74
+#define IRQ_SOR1 75
+#define IRQ_SOR 76
+#define IRQ_MC 77
+#define IRQ_EMC 78
+#define IRQ_TSECB 80
+#define IRQ_HDA 81
+#define IRQ_SPI2 82
+#define IRQ_SPI3 83
+#define IRQ_I2C2 84
+#define IRQ_PMU_EXT 86
+#define IRQ_GPIO6 87
+#define IRQ_GPIO7 89
+#define IRQ_UARTD 90
+#define IRQ_I2C3 92
+#define IRQ_SPI4 93
+
+/* Quaternary interrupt controller ids */
+#define IRQ_DTV 96
+#define IRQ_PCIE_INT 98
+#define IRQ_PCIE_MSI 99
+#define IRQ_AVP_CACHE 101
+#define IRQ_APE_INT1 102
+#define IRQ_APE_INT0 103
+#define IRQ_APB_DMA_CH0 104
+#define IRQ_APB_DMA_CH1 105
+#define IRQ_APB_DMA_CH2 106
+#define IRQ_APB_DMA_CH3 107
+#define IRQ_APB_DMA_CH4 108
+#define IRQ_APB_DMA_CH5 109
+#define IRQ_APB_DMA_CH6 110
+#define IRQ_APB_DMA_CH7 111
+#define IRQ_APB_DMA_CH8 112
+#define IRQ_APB_DMA_CH9 113
+#define IRQ_APB_DMA_CH10 114
+#define IRQ_APB_DMA_CH11 115
+#define IRQ_APB_DMA_CH12 116
+#define IRQ_APB_DMA_CH13 117
+#define IRQ_APB_DMA_CH14 118
+#define IRQ_APB_DMA_CH15 119
+#define IRQ_I2C4 120
+#define IRQ_TMR5 121
+#define IRQ_WDT_CPU 123
+#define IRQ_WDT_AVP 124
+#define IRQ_GPIO8 125
+#define IRQ_CAR 126
+
+/* Quinary interrupt controller ids */
+#define IRQ_APB_DMA_CH16 128
+#define IRQ_APB_DMA_CH17 129
+#define IRQ_APB_DMA_CH18 130
+#define IRQ_APB_DMA_CH19 131
+#define IRQ_APB_DMA_CH20 132
+#define IRQ_APB_DMA_CH21 133
+#define IRQ_APB_DMA_CH22 134
+#define IRQ_APB_DMA_CH23 135
+#define IRQ_APB_DMA_CH24 136
+#define IRQ_APB_DMA_CH25 137
+#define IRQ_APB_DMA_CH26 138
+#define IRQ_APB_DMA_CH27 139
+#define IRQ_APB_DMA_CH28 140
+#define IRQ_APB_DMA_CH29 141
+#define IRQ_APB_DMA_CH30 142
+#define IRQ_APB_DMA_CH31 143
+#define IRQ_CPU0_PMU_INTR 144
+#define IRQ_CPU1_PMU_INTR 145
+#define IRQ_CPU2_PMU_INTR 146
+#define IRQ_CPU3_PMU_INTR 147
+#define IRQ_SDMMC1_SYS 148
+#define IRQ_SDMMC2_SYS 149
+#define IRQ_SDMMC3_SYS 150
+#define IRQ_SDMMC4_SYS 151
+#define IRQ_TMR6 152
+#define IRQ_TMR7 153
+#define IRQ_TMR8 154
+#define IRQ_TMR9 155
+#define IRQ_TMR0 156
+#define IRQ_GPU_STALL 157
+#define IRQ_GPU_NONSTALL 158
+#define IRQ_DPAUX 159
+
+/* Senary interrupt controller ids */
+#define IRQ_MPCORE_AXIERRIRQ 160
+#define IRQ_MPCORE_INTERRIRQ 161
+#define IRQ_EVENT_GPIO_A 162
+#define IRQ_EVENT_GPIO_B 163
+#define IRQ_EVENT_GPIO_C 164
+#define IRQ_FLOW_RSM_CPU 168
+#define IRQ_FLOW_RSM_COP 169
+#define IRQ_TMR_SHARED 170
+#define IRQ_MPCORE_CTIIRQ0 171
+#define IRQ_MPCORE_CTIIRQ1 172
+#define IRQ_MPCORE_CTIIRQ2 173
+#define IRQ_MPCORE_CTIIRQ3 174
+#define IRQ_MSELECT_ERROR 175
+#define IRQ_TMR10 176
+#define IRQ_TMR11 177
+#define IRQ_TMR12 178
+#define IRQ_TMR13 179
+
+typedef int (*irq_handler_t)(u32 irq, void *data);
+
+typedef enum _irq_status_t
+{
+ IRQ_NONE = 0,
+ IRQ_HANDLED = 1,
+ IRQ_ERROR = 2,
+
+ IRQ_ENABLED = 0,
+ IRQ_NO_SLOTS_AVAILABLE = 1,
+ IRQ_ALREADY_REGISTERED = 2
+} irq_status_t;
+
+typedef enum _irq_flags_t
+{
+ IRQ_FLAG_NONE = 0,
+ IRQ_FLAG_ONE_OFF = (1 << 0),
+ IRQ_FLAG_REPLACEABLE = (1 << 1)
+} irq_flags_t;
+
+void irq_end();
+void irq_free(u32 irq);
+void irq_wait_event();
+void irq_disable_wait_event();
+irq_status_t irq_request(u32 irq, irq_handler_t handler, void *data, irq_flags_t flags);
+
+#endif
\ No newline at end of file