1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-06-15 12:52:10 +00:00
serenity/Kernel/Arch/aarch64/GPIO.cpp
Jakub V. Flasar 6d2c298b66 Kernel: Move aarch64 Prekernel into Kernel
As there is no need for a Prekernel on aarch64, the Prekernel code was
moved into Kernel itself. The functionality remains the same.

SERENITY_KERNEL_AND_INITRD in run.sh specifies a kernel and an inital
ramdisk to be used by the emulator. This is needed because aarch64
does not need a Prekernel and the other ones do.
2022-03-12 14:54:12 -08:00

98 lines
3.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2021, Nico Weber <thakis@chromium.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <Kernel/Arch/aarch64/GPIO.h>
#include <Kernel/Arch/aarch64/MMIO.h>
extern "C" void wait_cycles(int n);
namespace Prekernel {
// See BCM2835-ARM-Peripherals.pdf section "6 General Purpose I/O" or bcm2711-peripherals.pdf "Chapter 5. General Purpose I/O".
// "6.1 Register View" / "5.2 Register View"
struct PinData {
u32 bits[2];
u32 reserved;
};
struct GPIOControlRegisters {
u32 function_select[6]; // Every u32 stores a 3-bit function code for 10 pins.
u32 reserved;
PinData output_set;
PinData output_clear;
PinData level;
PinData event_detect_status;
PinData rising_edge_detect_enable;
PinData falling_edge_detect_enable;
PinData high_detect_enable;
PinData low_detect_enable;
PinData async_rising_edge_detect_enable;
PinData async_falling_edge_detect_enable;
u32 pull_up_down_enable;
PinData pull_up_down_enable_clock;
u32 test;
};
GPIO::GPIO()
: m_registers(MMIO::the().peripheral<GPIOControlRegisters>(0x20'0000))
{
}
GPIO& GPIO::the()
{
static GPIO instance;
return instance;
}
void GPIO::set_pin_function(unsigned pin_number, PinFunction function)
{
// pin_number must be <= 53. We can't VERIFY() that since this function runs too early to print assertion failures.
unsigned function_select_index = pin_number / 10;
unsigned function_select_bits_start = (pin_number % 10) * 3;
u32 function_bits = m_registers->function_select[function_select_index];
function_bits = (function_bits & ~(0b111 << function_select_bits_start)) | (static_cast<u32>(function) << function_select_bits_start);
m_registers->function_select[function_select_index] = function_bits;
}
void GPIO::internal_enable_pins(u32 enable[2], PullUpDownState state)
{
// Section "GPIO Pull-up/down Clock Registers (GPPUDCLKn)":
// The GPIO Pull-up/down Clock Registers control the actuation of internal pull-downs on
// the respective GPIO pins. These registers must be used in conjunction with the GPPUD
// register to effect GPIO Pull-up/down changes. The following sequence of events is
// required:
// 1. Write to GPPUD to set the required control signal (i.e. Pull-up or Pull-Down or neither
// to remove the current Pull-up/down)
m_registers->pull_up_down_enable = static_cast<u32>(state);
// 2. Wait 150 cycles this provides the required set-up time for the control signal
wait_cycles(150);
// 3. Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to
// modify NOTE only the pads which receive a clock will be modified, all others will
// retain their previous state.
m_registers->pull_up_down_enable_clock.bits[0] = enable[0];
m_registers->pull_up_down_enable_clock.bits[1] = enable[1];
// 4. Wait 150 cycles this provides the required hold time for the control signal
wait_cycles(150);
// 5. Write to GPPUD to remove the control signal
m_registers->pull_up_down_enable = 0;
// 6. Write to GPPUDCLK0/1 to remove the clock
m_registers->pull_up_down_enable_clock.bits[0] = 0;
m_registers->pull_up_down_enable_clock.bits[1] = 0;
// bcm2711-peripherals.pdf documents GPIO_PUP_PDN_CNTRL_REG[4] registers that store 2 bits state per register, similar to function_select.
// I don't know if the RPi3 has that already, so this uses the old BCM2835 approach for now.
}
}