diff options
author | Timon Kruiper <timonkruiper@gmail.com> | 2022-05-30 09:30:11 +0200 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-06-02 13:14:12 +0100 |
commit | 5eac2b9f3383413a2050e37a2281bd0ea6096081 (patch) | |
tree | 62e1fc59d6ae38aa5239045a72224f1cc18cc298 /Kernel/Arch | |
parent | f085903f62e07f80ba345d26a63e34fbd9f82235 (diff) | |
download | serenity-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.h | 2 | ||||
-rw-r--r-- | Kernel/Arch/aarch64/RPi/InterruptController.cpp | 69 | ||||
-rw-r--r-- | Kernel/Arch/aarch64/RPi/InterruptController.h | 39 |
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; +}; + +} |