use crate::pm::{self, Clock, PBAClock};
use crate::scif::{self, ClockSource, GenericClock};
use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
use kernel::utilities::registers::{register_bitfields, ReadWrite};
use kernel::utilities::StaticRef;
#[repr(C)]
pub struct GlocRegisters {
cr: ReadWrite<u32, Control::Register>,
truth: ReadWrite<u32, Truth::Register>,
}
register_bitfields![u32,
Control [
FILTEN OFFSET(31) NUMBITS(1) [
NoGlitchFilter = 0,
GlitchFilter = 1
],
AEN OFFSET(0) NUMBITS(4) []
],
Truth [
TRUTH OFFSET(0) NUMBITS(16) []
]
];
const GLOC_BASE_ADDR: usize = 0x40060000;
const GLOC_LUT_SIZE: usize = 0x8;
pub const IN_0_4: u8 = 0b0001; pub const IN_1_5: u8 = 0b0010; pub const IN_2_6: u8 = 0b0100; pub const IN_3_7: u8 = 0b1000; pub enum Lut {
Lut0 = 0,
Lut1 = 1,
}
pub struct Gloc {
lut_regs: [StaticRef<GlocRegisters>; 2],
}
impl Gloc {
pub const fn new() -> Self {
Self {
lut_regs: [get_lut_reg(Lut::Lut0), get_lut_reg(Lut::Lut1)],
}
}
}
const fn get_lut_reg(lut: Lut) -> StaticRef<GlocRegisters> {
unsafe {
StaticRef::new((GLOC_BASE_ADDR + (lut as usize) * GLOC_LUT_SIZE) as *const GlocRegisters)
}
}
impl Gloc {
pub fn enable(&self) {
pm::enable_clock(Clock::PBA(PBAClock::GLOC));
}
pub fn disable(&self) {
self.disable_lut(Lut::Lut0);
self.disable_lut(Lut::Lut1);
scif::generic_clock_disable(GenericClock::GCLK5);
pm::disable_clock(Clock::PBA(PBAClock::GLOC));
}
fn lut_registers(&self, lut: Lut) -> &GlocRegisters {
&self.lut_regs[lut as usize]
}
pub fn configure_lut(&self, lut: Lut, config: u16) {
let registers = self.lut_registers(lut);
registers.truth.write(Truth::TRUTH.val(config as u32));
}
pub fn enable_lut_inputs(&self, lut: Lut, inputs: u8) {
let registers = self.lut_registers(lut);
let aen: u32 = registers.cr.read(Control::AEN) | (inputs as u32);
registers.cr.modify(Control::AEN.val(aen));
}
pub fn disable_lut_inputs(&self, lut: Lut, inputs: u8) {
let registers = self.lut_registers(lut);
let aen: u32 = registers.cr.read(Control::AEN) & !(inputs as u32);
registers.cr.modify(Control::AEN.val(aen));
}
pub fn disable_lut(&self, lut: Lut) {
let registers = self.lut_registers(lut);
registers.truth.write(Truth::TRUTH.val(0));
registers.cr.modify(Control::AEN.val(0));
}
pub fn enable_lut_filter(&self, lut: Lut) {
scif::generic_clock_enable(GenericClock::GCLK5, ClockSource::CLK_CPU);
let registers = self.lut_registers(lut);
registers.cr.modify(Control::FILTEN::GlitchFilter);
}
pub fn disable_lut_filter(&self, lut: Lut) {
let registers = self.lut_registers(lut);
registers.cr.modify(Control::FILTEN::NoGlitchFilter);
}
}