Drivers: Added Sunxi pinctrl driver
Works well enough to set bank modes and turn on an LED Very not complete and needs more testing
This commit is contained in:
parent
d100b515d6
commit
259d929c13
6 changed files with 141 additions and 0 deletions
|
@ -0,0 +1,38 @@
|
|||
#include <stdint.h>
|
||||
|
||||
namespace drivers {
|
||||
namespace sunxi_d1_pinctrl {
|
||||
|
||||
struct [[gnu::aligned(4)]] Port {
|
||||
uint32_t config[4];
|
||||
uint32_t data;
|
||||
uint32_t drive[4];
|
||||
uint32_t pull[2];
|
||||
uint32_t _;
|
||||
};
|
||||
|
||||
struct [[gnu::aligned(4)]] PortInt {
|
||||
uint32_t config[4];
|
||||
uint32_t control;
|
||||
uint32_t status;
|
||||
uint32_t debounce;
|
||||
uint32_t _;
|
||||
};
|
||||
|
||||
struct [[gnu::aligned(4)]] PIO {
|
||||
uint32_t mode;
|
||||
uint32_t control;
|
||||
uint32_t value;
|
||||
uint32_t voltage_select;
|
||||
};
|
||||
|
||||
struct [[gnu::aligned(4)]] Registers {
|
||||
volatile Port ports[7];
|
||||
volatile uint32_t _[0x34];
|
||||
volatile PortInt interrupt[7];
|
||||
volatile uint32_t __[0x10];
|
||||
volatile PIO pio;
|
||||
};
|
||||
|
||||
} // End namespace sunxi_d1_pinctrl
|
||||
} // End namespace drivers
|
|
@ -0,0 +1,39 @@
|
|||
#pragma once
|
||||
|
||||
#include "registers.h"
|
||||
#include <stdint.h>
|
||||
|
||||
namespace drivers {
|
||||
namespace sunxi_d1_pinctrl {
|
||||
|
||||
enum Bank {
|
||||
PA,
|
||||
PB,
|
||||
PC,
|
||||
PD,
|
||||
PE,
|
||||
PF,
|
||||
PG,
|
||||
};
|
||||
|
||||
struct SunxiD1Pinctrl {
|
||||
SunxiD1Pinctrl(void * const addr);
|
||||
|
||||
void set_pin_mode(
|
||||
const Bank bank,
|
||||
const uint8_t pin,
|
||||
const uint8_t mode);
|
||||
void set_pin_state(
|
||||
const Bank bank,
|
||||
const uint8_t pin,
|
||||
const bool state);
|
||||
bool get_pin_state(
|
||||
const Bank bank,
|
||||
const uint8_t pin);
|
||||
|
||||
private:
|
||||
Registers &m_registers;
|
||||
};
|
||||
|
||||
} // End namespace sunxi_d1_pinctrl
|
||||
} // End namespace drivers
|
9
kernel/drivers/sunxi_d1_pinctrl/meson.build
Normal file
9
kernel/drivers/sunxi_d1_pinctrl/meson.build
Normal file
|
@ -0,0 +1,9 @@
|
|||
kernel_sources += [
|
||||
files(
|
||||
'sunxi_d1_pinctrl.cpp',
|
||||
),
|
||||
]
|
||||
|
||||
kernel_includes += include_directories(
|
||||
'include'
|
||||
)
|
47
kernel/drivers/sunxi_d1_pinctrl/sunxi_d1_pinctrl.cpp
Normal file
47
kernel/drivers/sunxi_d1_pinctrl/sunxi_d1_pinctrl.cpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
#include "sunxi_d1_pinctrl/sunxi_d1_pinctrl.h"
|
||||
|
||||
namespace drivers {
|
||||
namespace sunxi_d1_pinctrl {
|
||||
|
||||
SunxiD1Pinctrl::SunxiD1Pinctrl(void * const addr) :
|
||||
m_registers(*reinterpret_cast<Registers *>(addr)) {}
|
||||
|
||||
void SunxiD1Pinctrl::set_pin_mode(
|
||||
const Bank bank,
|
||||
const uint8_t pin,
|
||||
const uint8_t mode) {
|
||||
// Config banks are split up every 8 GPIO pins
|
||||
// Each bank is 32 bits and configures up to 8 pins
|
||||
const int config_bank = pin / 8;
|
||||
// Each config is 4 bits per pin
|
||||
const int shift_amount = pin % 8 * 4;
|
||||
const uint32_t mask = 0b1111 << shift_amount;
|
||||
|
||||
auto config = m_registers.ports[bank].config[config_bank];
|
||||
config &= ~mask;
|
||||
config |= (mode & 0b1111) << shift_amount;
|
||||
m_registers.ports[bank].config[config_bank] = config;
|
||||
}
|
||||
|
||||
void SunxiD1Pinctrl::set_pin_state(
|
||||
const Bank bank,
|
||||
const uint8_t pin,
|
||||
const bool state) {
|
||||
const uint32_t mask = 0b1 << pin;
|
||||
|
||||
auto data = m_registers.ports[bank].data;
|
||||
if(state)
|
||||
data |= mask;
|
||||
else
|
||||
data &= ~mask;
|
||||
m_registers.ports[bank].data = data;
|
||||
}
|
||||
|
||||
bool SunxiD1Pinctrl::get_pin_state(
|
||||
const Bank bank,
|
||||
const uint8_t pin) {
|
||||
return m_registers.ports[bank].data >> pin & 1;
|
||||
}
|
||||
|
||||
} // End namespace sunxi_d1_pinctrl
|
||||
} // End namespace drivers
|
|
@ -13,6 +13,7 @@
|
|||
#include <opensbi/extensions/srst.h>
|
||||
#include <opensbi/extensions/pmu.h>
|
||||
|
||||
#include <sunxi_d1_pinctrl/sunxi_d1_pinctrl.h>
|
||||
|
||||
void fmt(const char *f, ...) {
|
||||
namespace legacy = drivers::opensbi::legacy;
|
||||
|
@ -110,6 +111,12 @@ extern "C" void kmain(unsigned long hart, void *dtb) {
|
|||
fmt("uintmax: {} bits\n", sizeof(uintmax_t) * 8);
|
||||
fmt("HART: {}, DTB: {}\n", hart, dtb);
|
||||
|
||||
namespace sunxi_d1_pinctrl = drivers::sunxi_d1_pinctrl;
|
||||
sunxi_d1_pinctrl::SunxiD1Pinctrl pinctrl((void *)0x2000000);
|
||||
|
||||
pinctrl.set_pin_mode(sunxi_d1_pinctrl::Bank::PC, 1, 1);
|
||||
pinctrl.set_pin_state(sunxi_d1_pinctrl::Bank::PC, 1, true);
|
||||
|
||||
fmt("HALT\n");
|
||||
while(1);
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ kernel_cpp_args = []
|
|||
kernel_link_args = ['-nostdlib']
|
||||
|
||||
subdir('drivers/opensbi')
|
||||
subdir('drivers/sunxi_d1_pinctrl')
|
||||
# subdir('common/dtb')
|
||||
|
||||
includes = [
|
||||
|
|
Loading…
Reference in a new issue