Kernel/aarch64: Retrieve Pi 5 EMMC2 clock frequency from the devicetree

This commit is contained in:
Sönke Holz authored and Sönke Holz committed 2026-09-27 18:17:45 +02:00
1 parent b37efc6925
commit e1fd729c8b
2 files changed
+48 -5

No files matched your search

+39 -4
View File
@@ -14,13 +14,40 @@
namespace Kernel::RPi {
SDHostController::SDHostController(Memory::TypedMapping<SD::HostControlRegisterMap volatile> registers)
: m_registers(move(registers))
SDHostController::SDHostController(Model model, DeviceTree::Device const& device, Memory::TypedMapping<SD::HostControlRegisterMap volatile> registers)
: m_model(model)
, m_device(device)
, m_registers(move(registers))
{
}
ErrorOr<u32> SDHostController::retrieve_sd_clock_frequency()
{
if (m_model == Model::BCM2712_SDHCI) {
// On the Pi 5, the "Get clock rate" mailbox message doesn't appear to work if the firmware didn't initialize the SD host controller.
// In its devicetree, the EMMC2 clock is represented by a "fixed-clock" node, so get the frequency from there.
// FIXME: Add a proper abstraction for devicetree clock hierarchies.
auto maybe_clocks = m_device.node().get_property("clocks"sv);
if (!maybe_clocks.has_value() || maybe_clocks->size() != sizeof(u32))
return ENOTSUP;
auto clock_phandle = maybe_clocks->as<u32>();
auto const* clock = DeviceTree::get().phandle(clock_phandle);
if (clock == nullptr)
return EINVAL;
if (!clock->is_compatible_with("fixed-clock"sv))
return ENOTSUP;
auto maybe_clock_frequency = clock->get_property("clock-frequency"sv);
if (!maybe_clock_frequency.has_value() || maybe_clock_frequency->size() != sizeof(u32))
return EINVAL;
return maybe_clock_frequency->as<u32>();
}
return Timer::get_clock_rate(Timer::ClockID::EMMC);
}
@@ -32,12 +59,20 @@ static constinit Array const compatibles_array = {
DEVICETREE_DRIVER(BCM2835SDHCIController, compatibles_array);
// https://www.kernel.org/doc/Documentation/devicetree/bindings/mmc/brcm,iproc-sdhci.yaml
ErrorOr<void> BCM2835SDHCIController::probe(DeviceTree::Device const& device, StringView) const
ErrorOr<void> BCM2835SDHCIController::probe(DeviceTree::Device const& device, StringView compatible) const
{
SDHostController::Model model;
if (compatible == "brcm,bcm2712-sdhci"sv)
model = SDHostController::Model::BCM2712_SDHCI;
else if (compatible == "brcm,bcm2835-sdhci"sv)
model = SDHostController::Model::BCM2835_SDHCI;
else
VERIFY_NOT_REACHED();
auto physical_address = TRY(device.get_resource(0)).paddr;
auto registers = TRY(Memory::map_typed_writable<SD::HostControlRegisterMap volatile>(physical_address));
auto sdhc = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) SDHostController(move(registers))));
auto sdhc = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) SDHostController(model, device, move(registers))));
TRY(sdhc->initialize());
TRY(StorageManagement::the().add_controller(*sdhc));
+9 -1
View File
@@ -8,13 +8,19 @@
#include <Kernel/Devices/Storage/SD/Registers.h>
#include <Kernel/Devices/Storage/SD/SDHostController.h>
#include <Kernel/Firmware/DeviceTree/Device.h>
#include <Kernel/Memory/TypedMapping.h>
namespace Kernel::RPi {
class SDHostController : public ::SDHostController {
public:
SDHostController(Memory::TypedMapping<SD::HostControlRegisterMap volatile>);
enum class Model {
BCM2712_SDHCI,
BCM2835_SDHCI,
};
SDHostController(Model, DeviceTree::Device const&, Memory::TypedMapping<SD::HostControlRegisterMap volatile>);
virtual ~SDHostController() override = default;
protected:
@@ -23,6 +29,8 @@ protected:
virtual ErrorOr<u32> retrieve_sd_clock_frequency() override;
private:
Model m_model { Model::BCM2835_SDHCI };
DeviceTree::Device const& m_device;
Memory::TypedMapping<SD::HostControlRegisterMap volatile> m_registers;
};