1use crate::pm::{self, Clock, PBAClock};
11use crate::scif::{self, ClockSource, GenericClock};
12use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
13use kernel::utilities::registers::{register_bitfields, ReadWrite};
14use kernel::utilities::StaticRef;
15
16#[repr(C)]
17pub struct GlocRegisters {
18 cr: ReadWrite<u32, Control::Register>,
19 truth: ReadWrite<u32, Truth::Register>,
20}
21
22register_bitfields![u32,
23 Control [
24 FILTEN OFFSET(31) NUMBITS(1) [
26 NoGlitchFilter = 0,
27 GlitchFilter = 1
28 ],
29 AEN OFFSET(0) NUMBITS(4) []
31 ],
32
33 Truth [
34 TRUTH OFFSET(0) NUMBITS(16) []
36 ]
37];
38
39const GLOC_BASE_ADDR: usize = 0x40060000;
41
42const GLOC_LUT_SIZE: usize = 0x8;
44
45pub 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 {
53 Lut0 = 0,
54 Lut1 = 1,
55}
56
57pub struct Gloc {
58 lut_regs: [StaticRef<GlocRegisters>; 2],
59}
60
61impl Gloc {
62 pub const fn new() -> Self {
63 Self {
64 lut_regs: [get_lut_reg(Lut::Lut0), get_lut_reg(Lut::Lut1)],
65 }
66 }
67}
68
69const fn get_lut_reg(lut: Lut) -> StaticRef<GlocRegisters> {
71 unsafe {
72 StaticRef::new((GLOC_BASE_ADDR + (lut as usize) * GLOC_LUT_SIZE) as *const GlocRegisters)
73 }
74}
75
76impl Gloc {
77 pub fn enable(&self) {
79 pm::enable_clock(Clock::PBA(PBAClock::GLOC));
80 }
81
82 pub fn disable(&self) {
84 self.disable_lut(Lut::Lut0);
85 self.disable_lut(Lut::Lut1);
86 scif::generic_clock_disable(GenericClock::GCLK5);
87 pm::disable_clock(Clock::PBA(PBAClock::GLOC));
88 }
89
90 fn lut_registers(&self, lut: Lut) -> &GlocRegisters {
92 &self.lut_regs[lut as usize]
93 }
94
95 pub fn configure_lut(&self, lut: Lut, config: u16) {
97 let registers = self.lut_registers(lut);
98 registers.truth.write(Truth::TRUTH.val(config as u32));
99 }
100
101 pub fn enable_lut_inputs(&self, lut: Lut, inputs: u8) {
103 let registers = self.lut_registers(lut);
104 let aen: u32 = registers.cr.read(Control::AEN) | (inputs as u32);
105 registers.cr.modify(Control::AEN.val(aen));
106 }
107
108 pub fn disable_lut_inputs(&self, lut: Lut, inputs: u8) {
110 let registers = self.lut_registers(lut);
111 let aen: u32 = registers.cr.read(Control::AEN) & !(inputs as u32);
112 registers.cr.modify(Control::AEN.val(aen));
113 }
114
115 pub fn disable_lut(&self, lut: Lut) {
117 let registers = self.lut_registers(lut);
118 registers.truth.write(Truth::TRUTH.val(0));
119 registers.cr.modify(Control::AEN.val(0));
120 }
121
122 pub fn enable_lut_filter(&self, lut: Lut) {
125 scif::generic_clock_enable(GenericClock::GCLK5, ClockSource::CLK_CPU);
126 let registers = self.lut_registers(lut);
127 registers.cr.modify(Control::FILTEN::GlitchFilter);
128 }
129
130 pub fn disable_lut_filter(&self, lut: Lut) {
132 let registers = self.lut_registers(lut);
133 registers.cr.modify(Control::FILTEN::NoGlitchFilter);
134 }
135}