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