1use crate::pm::{Clock, HSBClock, PBBClock, disable_clock, enable_clock};
56use core::cell::Cell;
57use kernel::ErrorCode;
58use kernel::deferred_call::{DeferredCall, DeferredCallClient};
59use kernel::hil::crc::{Client, Crc, CrcAlgorithm, CrcOutput};
60use kernel::utilities::StaticRef;
61use kernel::utilities::cells::OptionalCell;
62use kernel::utilities::leasable_buffer::SubSliceMut;
63use kernel::utilities::registers::interfaces::{Readable, Writeable};
64use kernel::utilities::registers::{
65 FieldValue, InMemoryRegister, ReadOnly, ReadWrite, WriteOnly, register_bitfields,
66 register_structs,
67};
68
69pub const BASE_ADDRESS: StaticRef<CrccuRegisters> =
71 unsafe { StaticRef::new(0x400A4000 as *const CrccuRegisters) };
72
73register_structs! {
74 pub CrccuRegisters {
75 (0x000 => dscr: ReadWrite<u32, DescriptorBaseAddress::Register>),
76 (0x004 => _reserved0: u32),
77 (0x008 => dmaen: WriteOnly<u32, DmaEnable::Register>),
78 (0x00C => dmadis: WriteOnly<u32, DmaDisable::Register>),
79 (0x010 => dmasr: ReadOnly<u32, DmaStatus::Register>),
80 (0x014 => dmaier: WriteOnly<u32, DmaInterrupt::Register>),
81 (0x018 => dmaidr: WriteOnly<u32, DmaInterrupt::Register>),
82 (0x01C => dmaimr: ReadOnly<u32, DmaInterrupt::Register>),
83 (0x020 => dmaisr: ReadOnly<u32, DmaInterrupt::Register>),
84 (0x024 => _reserved1: [u32; 4]),
85 (0x034 => cr: WriteOnly<u32, Control::Register>),
86 (0x038 => mr: ReadWrite<u32, Mode::Register>),
87 (0x03C => sr: ReadOnly<u32, Status::Register>),
88 (0x040 => ier: WriteOnly<u32, Interrupt::Register>),
89 (0x044 => idr: WriteOnly<u32, Interrupt::Register>),
90 (0x048 => imr: ReadOnly<u32, Interrupt::Register>),
91 (0x04C => isr: ReadOnly<u32, Interrupt::Register>),
92 (0x050 => @END),
93 }
94}
95
96register_bitfields![u32,
97 DescriptorBaseAddress [
98 DSCR OFFSET(9) NUMBITS(23) []
100 ],
101
102 DmaEnable [
103 DMAEN 0
105 ],
106
107 DmaDisable [
108 DMADIS 0
110 ],
111
112 DmaStatus [
113 DMASR 0
115 ],
116
117 DmaInterrupt [
118 DMA 0
120 ],
121
122 Control [
123 RESET 0
125 ],
126
127 Mode [
128 DIVIDER OFFSET(4) NUMBITS(4) [],
130 PTYPE OFFSET(2) NUMBITS(2) [
132 Ccit8023 = 0,
133 Castagnoli = 1,
134 Ccit16 = 2
135 ],
136 COMPARE OFFSET(1) NUMBITS(1) [],
138 ENABLE OFFSET(0) NUMBITS(1) [
140 Enabled = 1,
141 Disabled = 0
142 ]
143 ],
144
145 Status [
146 CRC OFFSET(0) NUMBITS(32)
148 ],
149
150 Interrupt [
151 ERR 0
153 ]
154];
155
156#[repr(C)]
157#[repr(align(512))]
158struct Descriptor {
159 addr: InMemoryRegister<u32>,
161 ctrl: InMemoryRegister<u32>,
163 _res: [u32; 2],
164 crc: InMemoryRegister<u32>,
166}
167
168impl Descriptor {
169 pub fn new() -> Descriptor {
170 Descriptor {
171 addr: InMemoryRegister::new(0),
172 ctrl: InMemoryRegister::new(TCR::default().0),
173 _res: [0; 2],
174 crc: InMemoryRegister::new(0),
175 }
176 }
177}
178
179#[derive(Copy, Clone)]
181#[repr(C)]
182struct TCR(u32);
183
184impl TCR {
185 const fn new(enable_interrupt: bool, trwidth: TrWidth, btsize: u16) -> Self {
186 TCR((!enable_interrupt as u32) << 27 | (trwidth as u32) << 24 | (btsize as u32))
187 }
188
189 const fn default() -> Self {
190 Self::new(false, TrWidth::Byte, 0)
191 }
192
193 fn interrupt_enabled(self) -> bool {
194 (self.0 & (1 << 27)) == 0
195 }
196
197 #[allow(dead_code)]
198 fn get_btsize(self) -> u16 {
199 (self.0 & 0xffff) as u16
200 }
201}
202
203fn poly_for_alg(alg: CrcAlgorithm) -> FieldValue<u32, Mode::Register> {
204 match alg {
205 CrcAlgorithm::Crc32 => Mode::PTYPE::Ccit8023,
206 CrcAlgorithm::Crc32C => Mode::PTYPE::Castagnoli,
207 CrcAlgorithm::Crc16CCITT => Mode::PTYPE::Ccit16,
208 }
211}
212
213fn post_process(result: u32, alg: CrcAlgorithm) -> CrcOutput {
214 match alg {
215 CrcAlgorithm::Crc32 => CrcOutput::Crc32(reverse_and_invert(result)),
216 CrcAlgorithm::Crc32C => CrcOutput::Crc32C(reverse_and_invert(result)),
217 CrcAlgorithm::Crc16CCITT => CrcOutput::Crc16CCITT(result as u16),
218 }
221}
222
223fn reverse_and_invert(n: u32) -> u32 {
224 let mut out: u32 = 0;
225
226 for j in 0..32 {
228 let i = 31 - j;
229 out |= ((n & (1 << i)) >> i) << j;
230 }
231
232 out ^ 0xffffffff
234}
235
236#[allow(dead_code)]
238enum TrWidth {
239 Byte,
240 HalfWord,
241 Word,
242}
243
244#[derive(Copy, Clone, PartialEq)]
245enum State {
246 Invalid,
247 Initialized,
248 Enabled,
249}
250
251pub struct Crccu<'a> {
253 registers: StaticRef<CrccuRegisters>,
254 client: OptionalCell<&'a dyn Client>,
255 state: Cell<State>,
256 algorithm: OptionalCell<CrcAlgorithm>,
257
258 current_full_buffer: Cell<(*mut u8, usize)>,
261
262 compute_requested: Cell<bool>,
265
266 descriptor: Descriptor,
271
272 deferred_call: DeferredCall,
273}
274
275impl Crccu<'_> {
276 pub fn new(base_addr: StaticRef<CrccuRegisters>) -> Self {
277 Self {
278 registers: base_addr,
279 client: OptionalCell::empty(),
280 state: Cell::new(State::Invalid),
281 algorithm: OptionalCell::empty(),
282 current_full_buffer: Cell::new((core::ptr::null_mut::<u8>(), 0)),
283 compute_requested: Cell::new(false),
284 descriptor: Descriptor::new(),
285 deferred_call: DeferredCall::new(),
286 }
287 }
288
289 fn init(&self) {
290 if self.state.get() == State::Invalid {
291 self.descriptor.addr.set(0);
292 self.descriptor.ctrl.set(TCR::default().0);
293 self.descriptor.crc.set(0);
294 self.state.set(State::Initialized);
295 }
296 }
297
298 fn enable(&self) {
300 if self.state.get() != State::Enabled {
301 enable_clock(Clock::HSB(HSBClock::CRCCU));
303 enable_clock(Clock::PBB(PBBClock::CRCCU));
304 self.state.set(State::Enabled);
305 }
306 }
307
308 fn disable(&self) {
310 if self.state.get() == State::Enabled {
311 disable_clock(Clock::PBB(PBBClock::CRCCU));
312 disable_clock(Clock::HSB(HSBClock::CRCCU));
313 self.state.set(State::Initialized);
314 }
315 }
316
317 pub fn handle_interrupt(&self) {
319 if self.registers.isr.is_set(Interrupt::ERR) {
320 }
322
323 if self.registers.dmaisr.is_set(DmaInterrupt::DMA) {
324 if TCR(self.descriptor.ctrl.get()).interrupt_enabled() {
327 self.registers.mr.write(Mode::ENABLE::Disabled);
338
339 let window_addr = self.descriptor.addr.get();
341 let window_len = TCR(self.descriptor.ctrl.get()).get_btsize() as usize;
342
343 self.descriptor.addr.set(0);
345 self.descriptor.ctrl.set(TCR::default().0);
346 self.descriptor.crc.set(0);
347
348 self.registers.dmaidr.write(DmaInterrupt::DMA::SET);
350
351 self.registers.dmadis.write(DmaDisable::DMADIS::SET);
353
354 let (full_buffer_addr, full_buffer_len) = self.current_full_buffer.get();
357 let mut data = SubSliceMut::<'static, u8>::new(unsafe {
358 core::slice::from_raw_parts_mut(full_buffer_addr, full_buffer_len)
359 });
360
361 let start_offset = (window_addr as usize) - (full_buffer_addr as usize);
363 data.slice(start_offset..(start_offset + window_len));
364
365 self.client.map(move |client| {
368 client.input_done(Ok(()), data);
369 });
370 }
371 }
372 }
373}
374impl DeferredCallClient for Crccu<'_> {
375 fn handle_deferred_call(&self) {
376 let result = post_process(
380 self.registers.sr.read(Status::CRC),
381 self.algorithm.unwrap_or_panic(), );
383
384 self.registers.cr.write(Control::RESET::SET);
387 self.descriptor.ctrl.set(TCR::default().0);
388 self.compute_requested.set(false);
389
390 self.client.map(|client| {
391 client.crc_done(Ok(result));
392 });
393 }
394
395 fn register(&'static self) {
396 self.deferred_call.register(self);
397 }
398}
399
400impl<'a> Crc<'a> for Crccu<'a> {
402 fn set_client(&self, client: &'a dyn Client) {
404 self.client.set(client);
405 }
406
407 fn algorithm_supported(&self, algorithm: CrcAlgorithm) -> bool {
408 match algorithm {
411 CrcAlgorithm::Crc32 => true,
412 CrcAlgorithm::Crc32C => true,
413 CrcAlgorithm::Crc16CCITT => true,
414 }
415 }
416
417 fn set_algorithm(&self, algorithm: CrcAlgorithm) -> Result<(), ErrorCode> {
418 if TCR(self.descriptor.ctrl.get()).interrupt_enabled() || self.compute_requested.get() {
421 return Err(ErrorCode::BUSY);
423 }
424
425 self.init();
426 self.descriptor.addr.set(0);
428 self.descriptor.ctrl.set(TCR::default().0);
429 self.descriptor.crc.set(0);
430 self.algorithm.set(algorithm);
431
432 self.registers.cr.write(Control::RESET::SET);
434
435 Ok(())
436 }
437
438 fn input(
439 &self,
440 mut data: SubSliceMut<'static, u8>,
441 ) -> Result<(), (ErrorCode, SubSliceMut<'static, u8>)> {
442 let algorithm = if let Some(algorithm) = self.algorithm.get() {
443 algorithm
444 } else {
445 return Err((ErrorCode::RESERVE, data));
446 };
447
448 if TCR(self.descriptor.ctrl.get()).interrupt_enabled() || self.compute_requested.get() {
449 return Err((ErrorCode::BUSY, data));
451 }
452
453 self.init();
456
457 let len = data.len() as u16;
459 let ctrl = TCR::new(true, TrWidth::Byte, len);
460
461 if data.len() > u16::MAX as usize {
464 let window_ptr = data.as_ptr();
467 data.reset();
468 let start_ptr = data.as_ptr();
469 let start_offset = unsafe { window_ptr.offset_from(start_ptr) } as usize;
471
472 data.slice(start_offset..=(start_offset + u16::MAX as usize));
476 }
477
478 self.enable();
479
480 self.registers.dmaier.write(DmaInterrupt::DMA::SET);
482
483 self.registers.ier.write(Interrupt::ERR::SET);
485
486 self.descriptor.addr.set(data.as_ptr() as u32);
491 self.descriptor.ctrl.set(ctrl.0);
492 self.descriptor.crc.set(0); let full_slice = data.take();
498 let full_slice_ptr_len = (full_slice.as_mut_ptr(), full_slice.len());
499 self.current_full_buffer.set(full_slice_ptr_len);
500
501 self.registers
515 .dscr
516 .set(core::ptr::addr_of!(self.descriptor) as u32);
517
518 self.registers.mr.write(
520 Mode::DIVIDER.val(0)
521 + poly_for_alg(algorithm)
522 + Mode::COMPARE::CLEAR
523 + Mode::ENABLE::Enabled,
524 );
525
526 self.registers.dmaen.write(DmaEnable::DMAEN::SET);
528
529 Ok(())
530 }
531
532 fn compute(&self) -> Result<(), ErrorCode> {
533 if TCR(self.descriptor.ctrl.get()).interrupt_enabled() || self.compute_requested.get() {
538 return Err(ErrorCode::BUSY);
540 }
541
542 self.compute_requested.set(true);
544
545 self.deferred_call.set();
548
549 Ok(())
550 }
551
552 fn disable(&self) {
553 Crccu::disable(self);
554 }
555}