Kernel/aarch64: Allow manually driving RP1 GPIOs from software

This currently uses the output (enable) override fields in the control
registers. There's also a dedicated Registered IO (RIO) interface
mentioned in the datasheet, which might be a better fit.
This commit is contained in:
Sönke Holz authored and Sönke Holz committed 2026-09-21 12:14:42 +02:00
1 parent ef456c3d29
commit 5962730d78
2 files changed
+50

No files matched your search

+24
View File
@@ -99,6 +99,30 @@ void RP1GPIO::set_pin_enabled(u32 pin_number, bool enabled)
m_pads_bank_registers[bank_number]->pad_control[relative_pin_number] = pad_control;
}
void RP1GPIO::set_output_enable_override(u32 pin_number, OutputEnableOverride output_enable_override)
{
auto [bank_number, relative_pin_number] = MUST(pin_number_to_bank_and_relative_pin_number(pin_number));
auto control = m_io_bank_registers[bank_number]->gpio[relative_pin_number].control;
control &= ~IOBankRegisters::CONTROL_OUTPUT_ENABLE_OVERRIDE_MASK;
control |= static_cast<u32>(output_enable_override) << IOBankRegisters::CONTROL_OUTPUT_ENABLE_OVERRIDE_OFFSET;
m_io_bank_registers[bank_number]->gpio[relative_pin_number].control = control;
}
void RP1GPIO::set_output_override(u32 pin_number, OutputOverride output_override)
{
auto [bank_number, relative_pin_number] = MUST(pin_number_to_bank_and_relative_pin_number(pin_number));
auto control = m_io_bank_registers[bank_number]->gpio[relative_pin_number].control;
control &= ~IOBankRegisters::CONTROL_OUTPUT_OVERRIDE_MASK;
control |= static_cast<u32>(output_override) << IOBankRegisters::CONTROL_OUTPUT_OVERRIDE_OFFSET;
m_io_bank_registers[bank_number]->gpio[relative_pin_number].control = control;
}
RP1GPIO::RP1GPIO(RP1& rp1, Array<Memory::TypedMapping<IOBankRegisters volatile>, 3> io_bank_registers, Array<Memory::TypedMapping<PadsBankRegisters volatile>, 3> pads_bank_registers)
: m_rp1(rp1)
, m_io_bank_registers(move(io_bank_registers))
+26
View File
@@ -24,6 +24,26 @@ public:
void set_pin_function(u32 pin_number, u8 function);
void set_pin_enabled(u32 pin_number, bool);
// FIXME: Instead of output (enable) overrides we should probably use the Registered IO interface to manually drive GPIOs.
enum class OutputEnableOverride {
UsePeripheralSignal = 0x0,
UseInvertedPeripheralSignal = 0x1,
ForceDisable = 0x2,
ForceEnable = 0x3,
};
void set_output_enable_override(u32 pin_number, OutputEnableOverride);
enum class OutputOverride {
UsePeripheralSignal = 0x0,
UseInvertedPeripheralSignal = 0x1,
ForceLow = 0x2,
ForceHigh = 0x3,
};
void set_output_override(u32 pin_number, OutputOverride);
struct IOBankRegisters;
struct PadsBankRegisters;
@@ -39,6 +59,12 @@ struct RP1GPIO::IOBankRegisters {
static constexpr size_t CONTROL_FUNCTION_SELECT_OFFSET = 0;
static constexpr size_t CONTROL_FUNCTION_SELECT_MASK = 0x1f << 0;
static constexpr size_t CONTROL_OUTPUT_ENABLE_OVERRIDE_OFFSET = 14;
static constexpr size_t CONTROL_OUTPUT_ENABLE_OVERRIDE_MASK = 0x3 << 14;
static constexpr size_t CONTROL_OUTPUT_OVERRIDE_OFFSET = 12;
static constexpr size_t CONTROL_OUTPUT_OVERRIDE_MASK = 0x3 << 12;
struct {
u32 status;
u32 control;