1use crate::pm::{disable_clock, enable_clock, Clock, HSBClock, PBBClock};
56use core::cell::Cell;
57use kernel::deferred_call::{DeferredCall, DeferredCallClient};
58use kernel::hil::crc::{Client, Crc, CrcAlgorithm, CrcOutput};
59use kernel::utilities::cells::OptionalCell;
60use kernel::utilities::leasable_buffer::SubSliceMut;
61use kernel::utilities::registers::interfaces::{Readable, Writeable};
62use kernel::utilities::registers::{
63    register_bitfields, FieldValue, InMemoryRegister, ReadOnly, ReadWrite, WriteOnly,
64};
65use kernel::utilities::StaticRef;
66use kernel::ErrorCode;
67
68pub const BASE_ADDRESS: StaticRef<CrccuRegisters> =
70    unsafe { StaticRef::new(0x400A4000 as *const CrccuRegisters) };
71
72#[repr(C)]
73pub struct CrccuRegisters {
74    dscr: ReadWrite<u32, DescriptorBaseAddress::Register>,
76    _reserved0: u32,
77    dmaen: WriteOnly<u32, DmaEnable::Register>,
78    dmadis: WriteOnly<u32, DmaDisable::Register>,
79    dmasr: ReadOnly<u32, DmaStatus::Register>,
80    dmaier: WriteOnly<u32, DmaInterrupt::Register>,
81    dmaidr: WriteOnly<u32, DmaInterrupt::Register>,
82    dmaimr: ReadOnly<u32, DmaInterrupt::Register>,
83    dmaisr: ReadOnly<u32, DmaInterrupt::Register>,
84    _reserved1: [u32; 4],
85    cr: WriteOnly<u32, Control::Register>,
86    mr: ReadWrite<u32, Mode::Register>,
87    sr: ReadOnly<u32, Status::Register>,
88    ier: WriteOnly<u32, Interrupt::Register>,
89    idr: WriteOnly<u32, Interrupt::Register>,
90    imr: ReadOnly<u32, Interrupt::Register>,
91    isr: ReadOnly<u32, Interrupt::Register>,
92}
93
94register_bitfields![u32,
95    DescriptorBaseAddress [
96        DSCR OFFSET(9) NUMBITS(23) []
98    ],
99
100    DmaEnable [
101        DMAEN 0
103    ],
104
105    DmaDisable [
106        DMADIS 0
108    ],
109
110    DmaStatus [
111        DMASR 0
113    ],
114
115    DmaInterrupt [
116        DMA 0
118    ],
119
120    Control [
121        RESET 0
123    ],
124
125    Mode [
126        DIVIDER OFFSET(4) NUMBITS(4) [],
128        PTYPE OFFSET(2) NUMBITS(2) [
130            Ccit8023 = 0,
131            Castagnoli = 1,
132            Ccit16 = 2
133        ],
134        COMPARE OFFSET(1) NUMBITS(1) [],
136        ENABLE OFFSET(0) NUMBITS(1) [
138            Enabled = 1,
139            Disabled = 0
140        ]
141    ],
142
143    Status [
144        CRC OFFSET(0) NUMBITS(32)
146    ],
147
148    Interrupt [
149        ERR 0
151    ]
152];
153
154#[repr(C)]
155#[repr(align(512))]
156struct Descriptor {
157    addr: InMemoryRegister<u32>,
159    ctrl: InMemoryRegister<u32>,
161    _res: [u32; 2],
162    crc: InMemoryRegister<u32>,
164}
165
166impl Descriptor {
167    pub fn new() -> Descriptor {
168        Descriptor {
169            addr: InMemoryRegister::new(0),
170            ctrl: InMemoryRegister::new(TCR::default().0),
171            _res: [0; 2],
172            crc: InMemoryRegister::new(0),
173        }
174    }
175}
176
177#[derive(Copy, Clone)]
179#[repr(C)]
180struct TCR(u32);
181
182impl TCR {
183    const fn new(enable_interrupt: bool, trwidth: TrWidth, btsize: u16) -> Self {
184        TCR((!enable_interrupt as u32) << 27 | (trwidth as u32) << 24 | (btsize as u32))
185    }
186
187    const fn default() -> Self {
188        Self::new(false, TrWidth::Byte, 0)
189    }
190
191    fn interrupt_enabled(self) -> bool {
192        (self.0 & (1 << 27)) == 0
193    }
194
195    #[allow(dead_code)]
196    fn get_btsize(self) -> u16 {
197        (self.0 & 0xffff) as u16
198    }
199}
200
201fn poly_for_alg(alg: CrcAlgorithm) -> FieldValue<u32, Mode::Register> {
202    match alg {
203        CrcAlgorithm::Crc32 => Mode::PTYPE::Ccit8023,
204        CrcAlgorithm::Crc32C => Mode::PTYPE::Castagnoli,
205        CrcAlgorithm::Crc16CCITT => Mode::PTYPE::Ccit16,
206        }
209}
210
211fn post_process(result: u32, alg: CrcAlgorithm) -> CrcOutput {
212    match alg {
213        CrcAlgorithm::Crc32 => CrcOutput::Crc32(reverse_and_invert(result)),
214        CrcAlgorithm::Crc32C => CrcOutput::Crc32C(reverse_and_invert(result)),
215        CrcAlgorithm::Crc16CCITT => CrcOutput::Crc16CCITT(result as u16),
216        }
219}
220
221fn reverse_and_invert(n: u32) -> u32 {
222    let mut out: u32 = 0;
223
224    for j in 0..32 {
226        let i = 31 - j;
227        out |= ((n & (1 << i)) >> i) << j;
228    }
229
230    out ^ 0xffffffff
232}
233
234#[allow(dead_code)]
236enum TrWidth {
237    Byte,
238    HalfWord,
239    Word,
240}
241
242#[derive(Copy, Clone, PartialEq)]
243enum State {
244    Invalid,
245    Initialized,
246    Enabled,
247}
248
249pub struct Crccu<'a> {
251    registers: StaticRef<CrccuRegisters>,
252    client: OptionalCell<&'a dyn Client>,
253    state: Cell<State>,
254    algorithm: OptionalCell<CrcAlgorithm>,
255
256    current_full_buffer: Cell<(*mut u8, usize)>,
259
260    compute_requested: Cell<bool>,
263
264    descriptor: Descriptor,
269
270    deferred_call: DeferredCall,
271}
272
273impl Crccu<'_> {
274    pub fn new(base_addr: StaticRef<CrccuRegisters>) -> Self {
275        Self {
276            registers: base_addr,
277            client: OptionalCell::empty(),
278            state: Cell::new(State::Invalid),
279            algorithm: OptionalCell::empty(),
280            current_full_buffer: Cell::new((core::ptr::null_mut::<u8>(), 0)),
281            compute_requested: Cell::new(false),
282            descriptor: Descriptor::new(),
283            deferred_call: DeferredCall::new(),
284        }
285    }
286
287    fn init(&self) {
288        if self.state.get() == State::Invalid {
289            self.descriptor.addr.set(0);
290            self.descriptor.ctrl.set(TCR::default().0);
291            self.descriptor.crc.set(0);
292            self.state.set(State::Initialized);
293        }
294    }
295
296    fn enable(&self) {
298        if self.state.get() != State::Enabled {
299            enable_clock(Clock::HSB(HSBClock::CRCCU));
301            enable_clock(Clock::PBB(PBBClock::CRCCU));
302            self.state.set(State::Enabled);
303        }
304    }
305
306    fn disable(&self) {
308        if self.state.get() == State::Enabled {
309            disable_clock(Clock::PBB(PBBClock::CRCCU));
310            disable_clock(Clock::HSB(HSBClock::CRCCU));
311            self.state.set(State::Initialized);
312        }
313    }
314
315    pub fn handle_interrupt(&self) {
317        if self.registers.isr.is_set(Interrupt::ERR) {
318            }
320
321        if self.registers.dmaisr.is_set(DmaInterrupt::DMA) {
322            if TCR(self.descriptor.ctrl.get()).interrupt_enabled() {
325                self.registers.mr.write(Mode::ENABLE::Disabled);
336
337                let window_addr = self.descriptor.addr.get();
339                let window_len = TCR(self.descriptor.ctrl.get()).get_btsize() as usize;
340
341                self.descriptor.addr.set(0);
343                self.descriptor.ctrl.set(TCR::default().0);
344                self.descriptor.crc.set(0);
345
346                self.registers.dmaidr.write(DmaInterrupt::DMA::SET);
348
349                self.registers.dmadis.write(DmaDisable::DMADIS::SET);
351
352                let (full_buffer_addr, full_buffer_len) = self.current_full_buffer.get();
355                let mut data = SubSliceMut::<'static, u8>::new(unsafe {
356                    core::slice::from_raw_parts_mut(full_buffer_addr, full_buffer_len)
357                });
358
359                let start_offset = (window_addr as usize) - (full_buffer_addr as usize);
361                data.slice(start_offset..(start_offset + window_len));
362
363                self.client.map(move |client| {
366                    client.input_done(Ok(()), data);
367                });
368            }
369        }
370    }
371}
372impl DeferredCallClient for Crccu<'_> {
373    fn handle_deferred_call(&self) {
374        let result = post_process(
378            self.registers.sr.read(Status::CRC),
379            self.algorithm.unwrap_or_panic(), );
381
382        self.registers.cr.write(Control::RESET::SET);
385        self.descriptor.ctrl.set(TCR::default().0);
386        self.compute_requested.set(false);
387
388        self.client.map(|client| {
389            client.crc_done(Ok(result));
390        });
391    }
392
393    fn register(&'static self) {
394        self.deferred_call.register(self);
395    }
396}
397
398impl<'a> Crc<'a> for Crccu<'a> {
400    fn set_client(&self, client: &'a dyn Client) {
402        self.client.set(client);
403    }
404
405    fn algorithm_supported(&self, algorithm: CrcAlgorithm) -> bool {
406        match algorithm {
409            CrcAlgorithm::Crc32 => true,
410            CrcAlgorithm::Crc32C => true,
411            CrcAlgorithm::Crc16CCITT => true,
412        }
413    }
414
415    fn set_algorithm(&self, algorithm: CrcAlgorithm) -> Result<(), ErrorCode> {
416        if TCR(self.descriptor.ctrl.get()).interrupt_enabled() || self.compute_requested.get() {
419            return Err(ErrorCode::BUSY);
421        }
422
423        self.init();
424        self.descriptor.addr.set(0);
426        self.descriptor.ctrl.set(TCR::default().0);
427        self.descriptor.crc.set(0);
428        self.algorithm.set(algorithm);
429
430        self.registers.cr.write(Control::RESET::SET);
432
433        Ok(())
434    }
435
436    fn input(
437        &self,
438        mut data: SubSliceMut<'static, u8>,
439    ) -> Result<(), (ErrorCode, SubSliceMut<'static, u8>)> {
440        let algorithm = if let Some(algorithm) = self.algorithm.get() {
441            algorithm
442        } else {
443            return Err((ErrorCode::RESERVE, data));
444        };
445
446        if TCR(self.descriptor.ctrl.get()).interrupt_enabled() || self.compute_requested.get() {
447            return Err((ErrorCode::BUSY, data));
449        }
450
451        self.init();
454
455        let len = data.len() as u16;
457        let ctrl = TCR::new(true, TrWidth::Byte, len);
458
459        if data.len() > u16::MAX as usize {
462            let window_ptr = data.as_ptr();
465            data.reset();
466            let start_ptr = data.as_ptr();
467            let start_offset = unsafe { window_ptr.offset_from(start_ptr) } as usize;
469
470            data.slice(start_offset..=(start_offset + u16::MAX as usize));
474        }
475
476        self.enable();
477
478        self.registers.dmaier.write(DmaInterrupt::DMA::SET);
480
481        self.registers.ier.write(Interrupt::ERR::SET);
483
484        self.descriptor.addr.set(data.as_ptr() as u32);
489        self.descriptor.ctrl.set(ctrl.0);
490        self.descriptor.crc.set(0); let full_slice = data.take();
496        let full_slice_ptr_len = (full_slice.as_mut_ptr(), full_slice.len());
497        self.current_full_buffer.set(full_slice_ptr_len);
498
499        self.registers
513            .dscr
514            .set(core::ptr::addr_of!(self.descriptor) as u32);
515
516        self.registers.mr.write(
518            Mode::DIVIDER.val(0)
519                + poly_for_alg(algorithm)
520                + Mode::COMPARE::CLEAR
521                + Mode::ENABLE::Enabled,
522        );
523
524        self.registers.dmaen.write(DmaEnable::DMAEN::SET);
526
527        Ok(())
528    }
529
530    fn compute(&self) -> Result<(), ErrorCode> {
531        if TCR(self.descriptor.ctrl.get()).interrupt_enabled() || self.compute_requested.get() {
536            return Err(ErrorCode::BUSY);
538        }
539
540        self.compute_requested.set(true);
542
543        self.deferred_call.set();
546
547        Ok(())
548    }
549
550    fn disable(&self) {
551        Crccu::disable(self);
552    }
553}