From 5eac2b9f3383413a2050e37a2281bd0ea6096081 Mon Sep 17 00:00:00 2001 From: Timon Kruiper Date: Mon, 30 May 2022 09:30:11 +0200 Subject: [PATCH] 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. --- Kernel/Arch/aarch64/IRQController.h | 2 + .../Arch/aarch64/RPi/InterruptController.cpp | 69 +++++++++++++++++++ Kernel/Arch/aarch64/RPi/InterruptController.h | 39 +++++++++++ Kernel/CMakeLists.txt | 1 + 4 files changed, 111 insertions(+) create mode 100644 Kernel/Arch/aarch64/RPi/InterruptController.cpp create mode 100644 Kernel/Arch/aarch64/RPi/InterruptController.h 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 + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +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(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 + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +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; +}; + +} diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 5daf2ca395..a5a7c79b50 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -401,6 +401,7 @@ else() set(RPI_SOURCES Arch/aarch64/RPi/Framebuffer.cpp Arch/aarch64/RPi/GPIO.cpp + Arch/aarch64/RPi/InterruptController.cpp Arch/aarch64/RPi/Mailbox.cpp Arch/aarch64/RPi/MMIO.cpp Arch/aarch64/RPi/Timer.cpp