summaryrefslogtreecommitdiff
path: root/Kernel/Arch
diff options
context:
space:
mode:
authorTimon Kruiper <timonkruiper@gmail.com>2022-05-30 09:30:11 +0200
committerLinus Groh <mail@linusgroh.de>2022-06-02 13:14:12 +0100
commit5eac2b9f3383413a2050e37a2281bd0ea6096081 (patch)
tree62e1fc59d6ae38aa5239045a72224f1cc18cc298 /Kernel/Arch
parentf085903f62e07f80ba345d26a63e34fbd9f82235 (diff)
downloadserenity-5eac2b9f3383413a2050e37a2281bd0ea6096081.zip
Kernel: Add driver for interrupt controller on the Raspberry Pi
This implements the simpler IRQController class and adds a pending_interrupts() function to the class.
Diffstat (limited to 'Kernel/Arch')
-rw-r--r--Kernel/Arch/aarch64/IRQController.h2
-rw-r--r--Kernel/Arch/aarch64/RPi/InterruptController.cpp69
-rw-r--r--Kernel/Arch/aarch64/RPi/InterruptController.h39
3 files changed, 110 insertions, 0 deletions
diff --git a/Kernel/Arch/aarch64/IRQController.h b/Kernel/Arch/aarch64/IRQController.h
index 35882a6ffc..20e6b6b712 100644
--- a/Kernel/Arch/aarch64/IRQController.h
+++ b/Kernel/Arch/aarch64/IRQController.h
@@ -22,6 +22,8 @@ public:
virtual void eoi(GenericInterruptHandler const&) const = 0;
+ virtual u64 pending_interrupts() const = 0;
+
virtual StringView model() const = 0;
protected:
diff --git a/Kernel/Arch/aarch64/RPi/InterruptController.cpp b/Kernel/Arch/aarch64/RPi/InterruptController.cpp
new file mode 100644
index 0000000000..5f44fc11b3
--- /dev/null
+++ b/Kernel/Arch/aarch64/RPi/InterruptController.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2022, Timon Kruiper <timonkruiper@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <AK/Format.h>
+#include <Kernel/Arch/aarch64/RPi/InterruptController.h>
+#include <Kernel/Arch/aarch64/RPi/MMIO.h>
+#include <Kernel/Interrupts/GenericInterruptHandler.h>
+
+namespace Kernel::RPi {
+
+// "7.5 Interrupts Registers"
+// https://github.com/raspberrypi/documentation/files/1888662/BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf
+struct InterruptControllerRegisters {
+ u32 irq_basic_pending;
+ u32 irq_pending_1;
+ u32 irq_pending_2;
+ u32 fiq_control;
+
+ u32 enable_irqs_1;
+ u32 enable_irqs_2;
+ u32 enable_basic_irqs;
+
+ u32 disable_irqs_1;
+ u32 disable_irqs_2;
+ u32 disable_basic_irqs;
+};
+
+InterruptController::InterruptController()
+ : m_registers(MMIO::the().peripheral<InterruptControllerRegisters>(0xB200))
+{
+}
+
+void InterruptController::enable(GenericInterruptHandler const& handler)
+{
+ u8 interrupt_number = handler.interrupt_number();
+ VERIFY(interrupt_number < 64);
+
+ if (interrupt_number < 32)
+ m_registers->enable_irqs_1 = m_registers->enable_irqs_1 | (1 << interrupt_number);
+ else
+ m_registers->enable_irqs_2 = m_registers->enable_irqs_2 | (1 << (interrupt_number - 32));
+}
+
+void InterruptController::disable(GenericInterruptHandler const& handler)
+{
+ u8 interrupt_number = handler.interrupt_number();
+ VERIFY(interrupt_number < 64);
+
+ if (interrupt_number < 32)
+ m_registers->disable_irqs_1 = m_registers->disable_irqs_1 | (1 << interrupt_number);
+ else
+ m_registers->disable_irqs_2 = m_registers->disable_irqs_2 | (1 << (interrupt_number - 32));
+}
+
+void InterruptController::eoi(GenericInterruptHandler const&) const
+{
+ // NOTE: The interrupt controller cannot clear the interrupt, since it is basically just a big multiplexer.
+ // The interrupt should be cleared by the corresponding device driver, such as a timer or uart.
+}
+
+u64 InterruptController::pending_interrupts() const
+{
+ return ((u64)m_registers->irq_pending_2 << 32) | (u64)m_registers->irq_pending_1;
+}
+
+}
diff --git a/Kernel/Arch/aarch64/RPi/InterruptController.h b/Kernel/Arch/aarch64/RPi/InterruptController.h
new file mode 100644
index 0000000000..6633a553fe
--- /dev/null
+++ b/Kernel/Arch/aarch64/RPi/InterruptController.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2022, Timon Kruiper <timonkruiper@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/Types.h>
+#include <Kernel/Arch/aarch64/IRQController.h>
+
+namespace Kernel::RPi {
+
+struct InterruptControllerRegisters;
+
+// This class implements the simple Interrupt Controller found in the BCM2837. (RPi3)
+// A description of this device can be found at chapter 7 (Interrupts) of the manual:
+// https://github.com/raspberrypi/documentation/files/1888662/BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf (RPi3)
+class InterruptController : public IRQController {
+public:
+ InterruptController();
+
+private:
+ virtual void enable(GenericInterruptHandler const&) override;
+ virtual void disable(GenericInterruptHandler const&) override;
+
+ virtual void eoi(GenericInterruptHandler const&) const override;
+
+ virtual u64 pending_interrupts() const override;
+
+ virtual StringView model() const override
+ {
+ return "Raspberry Pi Interrupt Controller";
+ }
+
+ InterruptControllerRegisters volatile* m_registers;
+};
+
+}