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