Skip to content

Commit 183c065

Browse files
committed
Kernel/aarch64: Add support for the Pi 5 xHCs in the RP1
This driver doesn't get the base addresses and interrupt numbers from the devicetree, since the devicetree seems to expect that the RP1 BAR1 is set to 0. Our BAR allocator chooses a different address.
1 parent 3582672 commit 183c065

File tree

6 files changed

+119
-0
lines changed

6 files changed

+119
-0
lines changed

Kernel/Arch/aarch64/RPi/RP1.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright (c) 2025, Sönke Holz <[email protected]>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#include <Kernel/Arch/aarch64/RPi/RP1.h>
8+
#include <Kernel/Bus/PCI/BarMapping.h>
9+
#include <Kernel/Bus/USB/USBManagement.h>
10+
#include <Kernel/Bus/USB/xHCI/xHCIController.h>
11+
#include <Kernel/Interrupts/IRQHandler.h>
12+
13+
namespace Kernel::RPi {
14+
15+
class RP1xHCIController final : public USB::xHCIController {
16+
public:
17+
static ErrorOr<NonnullLockRefPtr<RP1xHCIController>> try_to_initialize(PhysicalAddress, size_t index, size_t interrupt_number);
18+
19+
private:
20+
RP1xHCIController(Memory::TypedMapping<u8> registers_mapping, size_t index, size_t interrupt_number);
21+
22+
// ^xHCIController
23+
virtual bool using_message_signalled_interrupts() const override { return m_using_message_signalled_interrupts; }
24+
virtual ErrorOr<OwnPtr<GenericInterruptHandler>> create_interrupter(u16 interrupter_id) override;
25+
virtual ErrorOr<void> write_dmesgln_prefix(StringBuilder& builder) const override
26+
{
27+
TRY(builder.try_appendff("xHCI: RP1 USBHOST{}: "sv, m_index));
28+
return {};
29+
}
30+
31+
size_t m_index { 0 };
32+
size_t m_interrupt_number { 0 };
33+
bool m_using_message_signalled_interrupts { false };
34+
};
35+
36+
ErrorOr<NonnullLockRefPtr<RP1xHCIController>> RP1xHCIController::try_to_initialize(PhysicalAddress paddr, size_t index, size_t interrupt_number)
37+
{
38+
auto registers_mapping = TRY(Memory::map_typed_writable<u8>(paddr));
39+
40+
auto controller = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) RP1xHCIController(move(registers_mapping), index, interrupt_number)));
41+
TRY(controller->initialize());
42+
return controller;
43+
}
44+
45+
UNMAP_AFTER_INIT RP1xHCIController::RP1xHCIController(Memory::TypedMapping<u8> registers_mapping, size_t index, size_t interrupt_number)
46+
: xHCIController(move(registers_mapping))
47+
, m_index(index)
48+
, m_interrupt_number(interrupt_number)
49+
{
50+
}
51+
52+
ErrorOr<OwnPtr<GenericInterruptHandler>> RP1xHCIController::create_interrupter(u16)
53+
{
54+
// FIXME: Add interrupt support. This requires adding support for the BCM2712 MSI-X interrupt controller.
55+
return nullptr;
56+
}
57+
58+
ErrorOr<void> RP1::try_to_initialize_xhci_controllers(PCI::DeviceIdentifier const& pci_identifier)
59+
{
60+
PCI::enable_memory_space(pci_identifier);
61+
PCI::enable_bus_mastering(pci_identifier);
62+
63+
auto bar1_address = TRY(get_bar_address(pci_identifier, PCI::HeaderType0BaseRegister::BAR1));
64+
65+
// Chapter 5. USB, https://datasheets.raspberrypi.com/rp1/rp1-peripherals.pdf
66+
// The interrupt numbers are taken from the devicetree.
67+
auto usbhost0 = TRY(RP1xHCIController::try_to_initialize(bar1_address.offset(0x20'0000), 0, 31));
68+
auto usbhost1 = TRY(RP1xHCIController::try_to_initialize(bar1_address.offset(0x30'0000), 1, 36));
69+
70+
USB::USBManagement::the().add_controller(usbhost0);
71+
USB::USBManagement::the().add_controller(usbhost1);
72+
73+
return {};
74+
}
75+
76+
}

Kernel/Arch/aarch64/RPi/RP1.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright (c) 2025, Sönke Holz <[email protected]>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#pragma once
8+
9+
#include <AK/Forward.h>
10+
#include <Kernel/Bus/PCI/Definitions.h>
11+
12+
namespace Kernel::RPi {
13+
14+
class RP1 {
15+
public:
16+
static ErrorOr<void> try_to_initialize_xhci_controllers(PCI::DeviceIdentifier const&);
17+
};
18+
19+
}

Kernel/Bus/PCI/IDs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ enum VendorID {
1818
VirtualBox = 0x80ee,
1919
VMWare = 0x15ad,
2020
Tdfx = 0x121a,
21+
RaspberryPi = 0x1de4,
2122
};
2223

2324
enum DeviceID {
@@ -27,6 +28,8 @@ enum DeviceID {
2728
VirtIOEntropy = 0x1005,
2829
VirtIOGPU = 0x1050,
2930
VirtIOInput = 0x1052,
31+
32+
RaspberryPiRP1 = 0x0001,
3033
};
3134

3235
}

Kernel/Bus/USB/USBManagement.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <Kernel/Bus/PCI/API.h>
1212
#include <Kernel/Bus/PCI/Access.h>
1313
#include <Kernel/Bus/PCI/Definitions.h>
14+
#include <Kernel/Bus/PCI/IDs.h>
1415
#include <Kernel/Bus/USB/EHCI/EHCIController.h>
1516
#include <Kernel/Bus/USB/UHCI/UHCIController.h>
1617
#include <Kernel/Bus/USB/USBManagement.h>
@@ -19,6 +20,10 @@
1920
#include <Kernel/Firmware/DeviceTree/DeviceTree.h>
2021
#include <Kernel/Sections.h>
2122

23+
#if ARCH(AARCH64)
24+
# include <Kernel/Arch/aarch64/RPi/RP1.h>
25+
#endif
26+
2227
namespace Kernel::USB {
2328

2429
static NeverDestroyed<Vector<NonnullLockRefPtr<Driver>>> s_available_drivers;
@@ -48,6 +53,14 @@ UNMAP_AFTER_INIT void USBManagement::enumerate_controllers()
4853
return;
4954

5055
MUST(PCI::enumerate([this](PCI::DeviceIdentifier const& device_identifier) {
56+
#if ARCH(AARCH64)
57+
if (device_identifier.hardware_id().vendor_id == PCI::VendorID::RaspberryPi && device_identifier.hardware_id().device_id == PCI::DeviceID::RaspberryPiRP1) {
58+
if (auto result = RPi::RP1::try_to_initialize_xhci_controllers(device_identifier); result.is_error()) {
59+
dmesgln("USBManagement: Failed to initialize RP1 xHCI controllers: {}", result.release_error());
60+
}
61+
}
62+
#endif
63+
5164
if (device_identifier.class_code() != PCI::ClassID::SerialBus
5265
|| device_identifier.subclass_code() != PCI::SerialBus::SubclassID::USB)
5366
return;
@@ -131,6 +144,11 @@ USBManagement& USBManagement::the()
131144
return *s_the;
132145
}
133146

147+
void USBManagement::add_controller(NonnullLockRefPtr<USBController> controller)
148+
{
149+
m_controllers.append(controller);
150+
}
151+
134152
void USBManagement::add_recipe(DeviceTree::DeviceRecipe<NonnullLockRefPtr<USBController>> recipe)
135153
{
136154
s_recipes->append(move(recipe));

Kernel/Bus/USB/USBManagement.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ class USBManagement {
2525
static LockRefPtr<Driver> get_driver_by_name(StringView name);
2626
static void unregister_driver(NonnullLockRefPtr<Driver> driver);
2727

28+
void add_controller(NonnullLockRefPtr<USBController>);
29+
2830
static void add_recipe(DeviceTree::DeviceRecipe<NonnullLockRefPtr<USBController>>);
2931

3032
static Vector<NonnullLockRefPtr<Driver>>& available_drivers();

Kernel/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@ elseif("${SERENITY_ARCH}" STREQUAL "aarch64")
482482
Arch/aarch64/RPi/InterruptController.cpp
483483
Arch/aarch64/RPi/Mailbox.cpp
484484
Arch/aarch64/RPi/MiniUART.cpp
485+
Arch/aarch64/RPi/RP1.cpp
485486
Arch/aarch64/RPi/SDHostController.cpp
486487
Arch/aarch64/RPi/Timer.cpp
487488
Arch/aarch64/RPi/Watchdog.cpp

0 commit comments

Comments
 (0)