1use crate::dma::DMAChannel;
14use crate::dma::DMAClient;
15use crate::dma::DMAPeripheral;
16use crate::pm;
17use core::cell::Cell;
18use core::cmp;
19use kernel::hil::spi;
20use kernel::hil::spi::ClockPhase;
21use kernel::hil::spi::ClockPolarity;
22use kernel::hil::spi::SpiMasterClient;
23use kernel::hil::spi::SpiSlaveClient;
24use kernel::platform::chip::ClockInterface;
25use kernel::utilities::cells::OptionalCell;
26use kernel::utilities::leasable_buffer::SubSliceMut;
27use kernel::utilities::peripheral_management::{PeripheralManagement, PeripheralManager};
28use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
29use kernel::utilities::registers::{self, register_bitfields, ReadOnly, ReadWrite, WriteOnly};
30use kernel::utilities::StaticRef;
31use kernel::ErrorCode;
32
33#[repr(C)]
34pub struct SpiRegisters {
35 cr: WriteOnly<u32, Control::Register>,
36 mr: ReadWrite<u32, Mode::Register>,
37 rdr: ReadOnly<u32>,
38 tdr: WriteOnly<u32, TransmitData::Register>,
39 sr: ReadOnly<u32, Status::Register>,
40 ier: WriteOnly<u32, InterruptFlags::Register>,
41 idr: WriteOnly<u32, InterruptFlags::Register>,
42 imr: ReadOnly<u32, InterruptFlags::Register>,
43 _reserved0: [ReadOnly<u32>; 4],
44 csr: [ReadWrite<u32, ChipSelectParams::Register>; 4],
45 _reserved1: [ReadOnly<u32>; 41],
46 wpcr: ReadWrite<u32, WriteProtectionControl::Register>,
47 wpsr: ReadOnly<u32>,
48 _reserved2: [ReadOnly<u32>; 3],
49 features: ReadOnly<u32>,
50 version: ReadOnly<u32>,
51}
52
53register_bitfields![u32,
54 Control [
55 LASTXFER 24,
56 FLUSHFIFO 8,
57 SWRST 7,
58 SPIDIS 1,
59 SPIEN 0
60 ],
61
62 Mode [
64 DLYBCS OFFSET(24) NUMBITS(8) [],
66 PCS OFFSET(16) NUMBITS(4) [
68 PCS0 = 0b1110,
70 PCS1 = 0b1101,
71 PCS2 = 0b1011,
72 PCS3 = 0b0111
73 ],
74 LLB OFFSET( 7) NUMBITS(1) [],
76 RXFIFOEN OFFSET( 6) NUMBITS(1) [],
78 MODFDIS OFFSET( 4) NUMBITS(1) [],
80 PCSDEC OFFSET( 2) NUMBITS(1) [],
82 PS OFFSET( 1) NUMBITS(1) [],
84 MSTR OFFSET( 0) NUMBITS(1) []
86 ],
87
88 TransmitData [
89 LASTXFER OFFSET(24) NUMBITS(1),
90 PCS OFFSET(16) NUMBITS(4),
91 TD OFFSET(0) NUMBITS(16)
92 ],
93
94 Status [
95 SPIENS OFFSET(16),
96 UNDES OFFSET(10),
97 TXEMPTY OFFSET(9),
98 NSSR OFFSET(8),
99 OVRES OFFSET(3),
100 MODF OFFSET(2),
101 TDRE OFFSET(1),
102 RDRF OFFSET(0)
103 ],
104
105 InterruptFlags [
106 UNDES 10,
107 TXEMPTY 9,
108 NSSR 8,
109 OVRES 3,
110 MODF 2,
111 TDRE 1,
112 RDRF 0
113 ],
114
115 ChipSelectParams [
116 DLYBCT OFFSET(24) NUMBITS(8) [],
117 DLYBS OFFSET(16) NUMBITS(8) [],
118 SCBR OFFSET(8) NUMBITS(8) [],
119 BITS OFFSET(4) NUMBITS(8) [
120 Eight = 0,
121 Nine = 1,
122 Ten = 2,
123 Eleven = 3,
124 Twelve = 4,
125 Thirteen = 5,
126 Fourteen = 6,
127 Fifteen = 7,
128 Sixteen = 8,
129 Four = 9,
130 Five = 10,
131 Six = 11,
132 Seven = 12
133 ],
134 CSAAT OFFSET(3) NUMBITS(1) [
135 ActiveAfterTransfer = 1,
136 InactiveAfterTransfer = 0
137 ],
138 CSNAAT OFFSET(2) NUMBITS(1) [
139 DoNotRiseBetweenTransfers = 0,
140 RiseBetweenTransfers = 1
141 ],
142 NCPHA OFFSET(1) NUMBITS(1) [
143 CaptureLeading = 1,
144 CaptureTrailing = 0
145 ],
146 CPOL OFFSET(0) NUMBITS(1) [
147 InactiveHigh = 1,
148 InactiveLow = 0
149 ]
150 ],
151
152 WriteProtectionControl [
153 SPIWPKEY OFFSET(8) NUMBITS(24) [
154 Key = 0x535049
155 ],
156 SPIWPEN OFFSET(0) NUMBITS(1) []
157 ]
158];
159
160#[allow(unused_variables, dead_code)]
161mod spi_consts {
163 pub mod rdr {
164 pub const RD: u32 = 0xFFFF;
165 }
166
167 pub mod tdr {
168 pub const TD: u32 = 0xFFFF;
169 }
172}
173
174#[derive(Copy, Clone)]
176pub enum Peripheral {
177 Peripheral0,
178 Peripheral1,
179 Peripheral2,
180 Peripheral3,
181}
182
183impl spi::cs::IntoChipSelect<Peripheral, spi::cs::ActiveLow> for Peripheral {
184 fn into_cs(self) -> Peripheral {
185 self
186 }
187}
188
189#[derive(Copy, Clone, PartialEq)]
190pub enum SpiRole {
191 SpiMaster,
192 SpiSlave,
193}
194
195pub struct SpiHw<'a> {
197 client: OptionalCell<&'a dyn SpiMasterClient>,
198 dma_read: OptionalCell<&'static DMAChannel>,
199 dma_write: OptionalCell<&'static DMAChannel>,
200 transfers_in_progress: Cell<u8>,
203 dma_length: Cell<usize>,
204
205 slave_client: OptionalCell<&'a dyn SpiSlaveClient>,
207 role: Cell<SpiRole>,
208 pm: &'a pm::PowerManager,
209}
210
211const SPI_BASE: StaticRef<SpiRegisters> =
212 unsafe { StaticRef::new(0x40008000 as *const SpiRegisters) };
213
214impl PeripheralManagement<pm::Clock> for SpiHw<'_> {
215 type RegisterType = SpiRegisters;
216
217 fn get_registers(&self) -> &SpiRegisters {
218 &SPI_BASE
219 }
220
221 fn get_clock(&self) -> &pm::Clock {
222 &pm::Clock::PBA(pm::PBAClock::SPI)
223 }
224
225 fn before_peripheral_access(&self, clock: &pm::Clock, _: &SpiRegisters) {
226 clock.enable();
227 }
228
229 fn after_peripheral_access(&self, clock: &pm::Clock, registers: &SpiRegisters) {
230 if !registers.sr.is_set(Status::SPIENS) {
231 clock.disable();
232 }
233 }
234}
235
236type SpiRegisterManager<'a, 'm> = PeripheralManager<'m, SpiHw<'a>, pm::Clock>;
237
238impl<'a> SpiHw<'a> {
239 pub const fn new(pm: &'a pm::PowerManager) -> SpiHw<'a> {
241 SpiHw {
242 client: OptionalCell::empty(),
243 dma_read: OptionalCell::empty(),
244 dma_write: OptionalCell::empty(),
245 transfers_in_progress: Cell::new(0),
246 dma_length: Cell::new(0),
247
248 slave_client: OptionalCell::empty(),
249 role: Cell::new(SpiRole::SpiMaster),
250 pm,
251 }
252 }
253
254 fn init_as_role(&self, spi: &SpiRegisterManager<'a, '_>, role: SpiRole) {
255 self.role.set(role);
256
257 if role == SpiRole::SpiMaster {
258 spi.registers.cr.write(Control::LASTXFER::SET);
260 }
261
262 let csr = self.get_active_csr(spi);
264 csr.modify(ChipSelectParams::BITS::Eight);
265
266 let mode = match self.role.get() {
268 SpiRole::SpiMaster => Mode::MSTR::SET,
269 SpiRole::SpiSlave => Mode::MSTR::CLEAR,
270 };
271
272 spi.registers.mr.modify(mode + Mode::MODFDIS::SET);
274 }
275
276 fn enable(&self) {
277 let spi = &SpiRegisterManager::new(self);
278
279 spi.registers.cr.write(Control::SPIEN::SET);
280
281 if self.role.get() == SpiRole::SpiSlave {
282 spi.registers.ier.write(InterruptFlags::NSSR::SET); }
284 }
285
286 fn disable(&self) {
287 let spi = &SpiRegisterManager::new(self);
288
289 while !spi.registers.sr.is_set(Status::TXEMPTY) {}
293
294 self.dma_read.map(|read| read.disable());
295 self.dma_write.map(|write| write.disable());
296 spi.registers.cr.write(Control::SPIDIS::SET);
297
298 if self.role.get() == SpiRole::SpiSlave {
299 spi.registers.idr.write(InterruptFlags::NSSR::SET); }
301 }
302
303 pub fn set_baud_rate(&self, rate: u32) -> u32 {
314 let mut real_rate = rate;
316 let clock = self.pm.get_system_frequency();
317
318 if real_rate < 188235 {
319 real_rate = 188235;
320 }
321 if real_rate > clock {
322 real_rate = clock;
323 }
324
325 let mut scbr = clock / real_rate;
327 if clock % real_rate != 0 && scbr != 0xFF {
332 scbr += 1;
333 }
334 let spi = &SpiRegisterManager::new(self);
335 let csr = self.get_active_csr(spi);
336 csr.modify(ChipSelectParams::SCBR.val(scbr));
337 clock / scbr
338 }
339
340 fn get_baud_rate(&self) -> u32 {
341 let spi = &SpiRegisterManager::new(self);
342 let clock = 48000000;
343 let scbr = self.get_active_csr(spi).read(ChipSelectParams::SCBR);
344 clock / scbr
345 }
346
347 fn set_polarity(&self, polarity: ClockPolarity) {
348 let spi = &SpiRegisterManager::new(self);
349 let csr = self.get_active_csr(spi);
350 match polarity {
351 ClockPolarity::IdleHigh => csr.modify(ChipSelectParams::CPOL::InactiveHigh),
352 ClockPolarity::IdleLow => csr.modify(ChipSelectParams::CPOL::InactiveLow),
353 }
354 }
355
356 fn get_polarity(&self) -> ClockPolarity {
357 let spi = &SpiRegisterManager::new(self);
358 let csr = self.get_active_csr(spi);
359 if csr.matches_all(ChipSelectParams::CPOL::InactiveLow) {
360 ClockPolarity::IdleLow
361 } else {
362 ClockPolarity::IdleHigh
363 }
364 }
365
366 fn set_phase(&self, phase: ClockPhase) {
367 let spi = &SpiRegisterManager::new(self);
368 let csr = self.get_active_csr(spi);
369 match phase {
370 ClockPhase::SampleLeading => csr.modify(ChipSelectParams::NCPHA::CaptureLeading),
371 ClockPhase::SampleTrailing => csr.modify(ChipSelectParams::NCPHA::CaptureTrailing),
372 }
373 }
374
375 fn get_phase(&self) -> ClockPhase {
376 let spi = &SpiRegisterManager::new(self);
377 let csr = self.get_active_csr(spi);
378 if csr.matches_all(ChipSelectParams::NCPHA::CaptureTrailing) {
379 ClockPhase::SampleTrailing
380 } else {
381 ClockPhase::SampleLeading
382 }
383 }
384
385 fn get_active_peripheral(&self, spi: &SpiRegisterManager<'a, '_>) -> Peripheral {
387 if self.role.get() == SpiRole::SpiMaster {
388 if spi.registers.mr.matches_all(Mode::PCS::PCS3) {
389 Peripheral::Peripheral3
390 } else if spi.registers.mr.matches_all(Mode::PCS::PCS2) {
391 Peripheral::Peripheral2
392 } else if spi.registers.mr.matches_all(Mode::PCS::PCS1) {
393 Peripheral::Peripheral1
394 } else {
395 Peripheral::Peripheral0
397 }
398 } else {
399 Peripheral::Peripheral0
401 }
402 }
403
404 fn get_active_csr<'s>(
407 &'s self,
408 spi: &SpiRegisterManager<'a, 's>,
409 ) -> &'s registers::ReadWrite<u32, ChipSelectParams::Register> {
410 match self.get_active_peripheral(spi) {
411 Peripheral::Peripheral0 => &spi.registers.csr[0],
412 Peripheral::Peripheral1 => &spi.registers.csr[1],
413 Peripheral::Peripheral2 => &spi.registers.csr[2],
414 Peripheral::Peripheral3 => &spi.registers.csr[3],
415 }
416 }
417
418 pub fn set_dma(&self, read: &'static DMAChannel, write: &'static DMAChannel) {
420 self.dma_read.set(read);
421 self.dma_write.set(write);
422 }
423
424 pub fn handle_interrupt(&self) {
425 let spi = &SpiRegisterManager::new(self);
426
427 self.slave_client.map(|client| {
428 if spi.registers.sr.is_set(Status::NSSR) {
429 client.chip_selected()
431 }
432 });
435 }
436
437 fn read_write_bytes(
446 &self,
447 write_buffer: Option<SubSliceMut<'static, u8>>,
448 read_buffer: Option<SubSliceMut<'static, u8>>,
449 ) -> Result<
450 (),
451 (
452 ErrorCode,
453 Option<SubSliceMut<'static, u8>>,
454 Option<SubSliceMut<'static, u8>>,
455 ),
456 > {
457 let count = match (&write_buffer, &read_buffer) {
458 (Some(ref wb), Some(ref rb)) => cmp::min(wb.len(), rb.len()),
459 (Some(ref wb), None) => wb.len(),
460 (None, Some(ref rb)) => rb.len(),
461 (None, None) => return Err((ErrorCode::INVAL, write_buffer, read_buffer)),
462 };
463
464 self.enable();
466
467 self.dma_length.set(count);
469
470 self.transfers_in_progress.set(0);
473
474 read_buffer.map(|rbuf| {
482 self.transfers_in_progress
483 .set(self.transfers_in_progress.get() + 1);
484 self.dma_read.map(move |read| {
485 read.enable();
486 read.do_transfer(DMAPeripheral::SPI_RX, rbuf.take(), count);
487 });
488 });
489
490 write_buffer.map(|buf| {
494 self.transfers_in_progress
495 .set(self.transfers_in_progress.get() + 1);
496 self.dma_write.map(move |write| {
497 write.enable();
498 write.do_transfer(DMAPeripheral::SPI_TX, buf.take(), count);
499 });
500 });
501
502 Ok(())
503 }
504}
505
506impl<'a> spi::SpiMaster<'a> for SpiHw<'a> {
507 type ChipSelect = Peripheral;
508
509 fn set_client(&self, client: &'a dyn SpiMasterClient) {
510 self.client.set(client);
511 }
512
513 fn init(&self) -> Result<(), ErrorCode> {
516 let spi = &SpiRegisterManager::new(self);
517 self.init_as_role(spi, SpiRole::SpiMaster);
518 Ok(())
519 }
520
521 fn is_busy(&self) -> bool {
522 self.transfers_in_progress.get() != 0
523 }
524
525 fn write_byte(&self, out_byte: u8) -> Result<(), ErrorCode> {
528 let spi = &SpiRegisterManager::new(self);
529
530 let tdr = (out_byte as u32) & spi_consts::tdr::TD;
531 while !spi.registers.sr.is_set(Status::TDRE) {}
534 spi.registers.tdr.set(tdr);
535 Ok(())
536 }
537
538 fn read_byte(&self) -> Result<u8, ErrorCode> {
541 self.read_write_byte(0)
542 }
543
544 fn read_write_byte(&self, val: u8) -> Result<u8, ErrorCode> {
547 let spi = &SpiRegisterManager::new(self);
548
549 self.write_byte(val)?;
550 while !spi.registers.sr.is_set(Status::RDRF) {}
551 Ok(spi.registers.rdr.get() as u8)
552 }
553
554 fn read_write_bytes(
565 &self,
566 write_buffer: SubSliceMut<'static, u8>,
567 read_buffer: Option<SubSliceMut<'static, u8>>,
568 ) -> Result<
569 (),
570 (
571 ErrorCode,
572 SubSliceMut<'static, u8>,
573 Option<SubSliceMut<'static, u8>>,
574 ),
575 > {
576 if self.is_busy() {
578 return Err((ErrorCode::BUSY, write_buffer, read_buffer));
579 }
580
581 if let Err((err, write_buffer, read_buffer)) =
582 self.read_write_bytes(Some(write_buffer), read_buffer)
583 {
584 Err((
585 err,
586 write_buffer.unwrap_or((&mut [] as &mut [u8]).into()),
587 read_buffer,
588 ))
589 } else {
590 Ok(())
591 }
592 }
593
594 fn set_rate(&self, rate: u32) -> Result<u32, ErrorCode> {
595 Ok(self.set_baud_rate(rate))
596 }
597
598 fn get_rate(&self) -> u32 {
599 self.get_baud_rate()
600 }
601
602 fn set_polarity(&self, polarity: ClockPolarity) -> Result<(), ErrorCode> {
603 self.set_polarity(polarity);
604 Ok(())
605 }
606
607 fn get_polarity(&self) -> ClockPolarity {
608 self.get_polarity()
609 }
610
611 fn set_phase(&self, phase: ClockPhase) -> Result<(), ErrorCode> {
612 self.set_phase(phase);
613 Ok(())
614 }
615
616 fn get_phase(&self) -> ClockPhase {
617 self.get_phase()
618 }
619
620 fn hold_low(&self) {
621 let spi = &SpiRegisterManager::new(self);
622 let csr = self.get_active_csr(spi);
623 csr.modify(ChipSelectParams::CSAAT::ActiveAfterTransfer);
624 }
625
626 fn release_low(&self) {
627 let spi = &SpiRegisterManager::new(self);
628 let csr = self.get_active_csr(spi);
629 csr.modify(ChipSelectParams::CSAAT::InactiveAfterTransfer);
630 }
631
632 fn specify_chip_select(&self, cs: Self::ChipSelect) -> Result<(), ErrorCode> {
633 if self.role.get() == SpiRole::SpiMaster {
635 let spi = &SpiRegisterManager::new(self);
636 let mr = match cs {
637 Peripheral::Peripheral0 => Mode::PCS::PCS0,
638 Peripheral::Peripheral1 => Mode::PCS::PCS1,
639 Peripheral::Peripheral2 => Mode::PCS::PCS2,
640 Peripheral::Peripheral3 => Mode::PCS::PCS3,
641 };
642 spi.registers.mr.modify(mr);
643 Ok(())
644 } else {
645 Err(ErrorCode::INVAL)
646 }
647 }
648}
649
650impl<'a> spi::SpiSlave<'a> for SpiHw<'a> {
651 fn set_client(&self, client: Option<&'a dyn SpiSlaveClient>) {
653 self.slave_client.insert(client);
654 }
655
656 fn has_client(&self) -> bool {
657 self.slave_client.is_some()
658 }
659
660 fn init(&self) -> Result<(), ErrorCode> {
661 let spi = &SpiRegisterManager::new(self);
662 self.init_as_role(spi, SpiRole::SpiSlave);
663 Ok(())
664 }
665
666 fn set_write_byte(&self, write_byte: u8) {
669 let spi = SpiRegisterManager::new(self);
670 spi.registers.tdr.set(write_byte as u32);
671 }
672
673 fn read_write_bytes(
679 &self,
680 write_buffer: Option<&'static mut [u8]>,
681 read_buffer: Option<&'static mut [u8]>,
682 len: usize,
683 ) -> Result<
684 (),
685 (
686 ErrorCode,
687 Option<&'static mut [u8]>,
688 Option<&'static mut [u8]>,
689 ),
690 > {
691 let write_buffer = write_buffer.map(|b| {
692 let mut buf: SubSliceMut<u8> = b.into();
693 if buf.len() > len {
694 buf.slice(..len);
695 }
696 buf
697 });
698 let read_buffer = read_buffer.map(|b| {
699 let mut buf: SubSliceMut<u8> = b.into();
700 if buf.len() > len {
701 buf.slice(..len);
702 }
703 buf
704 });
705
706 if let Err((e, mwb, mrb)) = self.read_write_bytes(write_buffer, read_buffer) {
707 Err((e, mwb.map(|b| b.take()), mrb.map(|b| b.take())))
708 } else {
709 Ok(())
710 }
711 }
712
713 fn set_polarity(&self, polarity: ClockPolarity) -> Result<(), ErrorCode> {
714 self.set_polarity(polarity);
715 Ok(())
716 }
717
718 fn get_polarity(&self) -> ClockPolarity {
719 self.get_polarity()
720 }
721
722 fn set_phase(&self, phase: ClockPhase) -> Result<(), ErrorCode> {
723 self.set_phase(phase);
724 Ok(())
725 }
726
727 fn get_phase(&self) -> ClockPhase {
728 self.get_phase()
729 }
730}
731
732impl DMAClient for SpiHw<'_> {
733 fn transfer_done(&self, _pid: DMAPeripheral) {
734 self.transfers_in_progress
742 .set(self.transfers_in_progress.get() - 1);
743
744 if self.transfers_in_progress.get() == 0 {
745 let txbuf = self.dma_write.map_or(None, |dma| {
746 let buf = dma.abort_transfer();
747 dma.disable();
748 buf
749 });
750
751 let rxbuf = self.dma_read.map_or(None, |dma| {
752 let buf = dma.abort_transfer();
753 dma.disable();
754 buf
755 });
756
757 let len = self.dma_length.get();
758 self.dma_length.set(0);
759
760 match self.role.get() {
761 SpiRole::SpiMaster => {
762 self.client.map(|cb| {
763 txbuf.map(|txbuf| {
764 cb.read_write_done(txbuf.into(), rxbuf.map(|b| b.into()), Ok(len));
765 });
766 });
767 }
768 SpiRole::SpiSlave => {
769 self.slave_client.map(|cb| {
770 cb.read_write_done(txbuf, rxbuf, len, Ok(()));
771 });
772 }
773 }
774 if self.transfers_in_progress.get() == 0 {
775 self.disable();
776 }
777 }
778 }
779}