sam4l/
spi.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Implementation of DMA-based SPI master and slave communication for the
6//! SAM4L.
7//!
8//! Driver for the SPI hardware (separate from the USARTS), described in chapter
9//! 26 of the datasheet.
10//!
11//! - Authors: Sam Crow <samcrow@uw.edu>, Philip Levis <pal@cs.stanford.edu>
12
13use 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 of the SPI peripheral.
63    Mode [
64        /// Delay between chip selects
65        DLYBCS   OFFSET(24)  NUMBITS(8) [],
66        /// Peripheral chip select
67        PCS      OFFSET(16)  NUMBITS(4) [
68            /// One-hot encoding
69            PCS0 = 0b1110,
70            PCS1 = 0b1101,
71            PCS2 = 0b1011,
72            PCS3 = 0b0111
73        ],
74        /// Local loopback enable
75        LLB      OFFSET( 7)  NUMBITS(1) [],
76        /// FIFO in reception enable
77        RXFIFOEN OFFSET( 6)  NUMBITS(1) [],
78        /// Mode fault detection
79        MODFDIS  OFFSET( 4)  NUMBITS(1) [],
80        /// Chip select decode
81        PCSDEC   OFFSET( 2)  NUMBITS(1) [],
82        /// Peripheral select
83        PS       OFFSET( 1)  NUMBITS(1) [],
84        /// Master/slave mode
85        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)]
161// Per-register masks defined in the SPI manual in chapter 26.8
162mod 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        // PCSx masks from MR also apply here
170        // LASTXFER from CR also applies here
171    }
172}
173
174/// Values for selected peripherals
175#[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
195/// Abstraction of the SPI Hardware
196pub struct SpiHw<'a> {
197    client: OptionalCell<&'a dyn SpiMasterClient>,
198    dma_read: OptionalCell<&'static DMAChannel>,
199    dma_write: OptionalCell<&'static DMAChannel>,
200    // keep track of which how many DMA transfers are pending to correctly
201    // issue completion event only after both complete.
202    transfers_in_progress: Cell<u8>,
203    dma_length: Cell<usize>,
204
205    // Slave client is distinct from master client
206    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    /// Creates a new SPI object, with peripheral 0 selected
240    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            // Only need to set LASTXFER if we are master
259            spi.registers.cr.write(Control::LASTXFER::SET);
260        }
261
262        // Sets bits per transfer to 8
263        let csr = self.get_active_csr(spi);
264        csr.modify(ChipSelectParams::BITS::Eight);
265
266        // Set mode to master or slave
267        let mode = match self.role.get() {
268            SpiRole::SpiMaster => Mode::MSTR::SET,
269            SpiRole::SpiSlave => Mode::MSTR::CLEAR,
270        };
271
272        // Disable mode fault detection (open drain outputs not supported)
273        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); // Enable NSSR
283        }
284    }
285
286    fn disable(&self) {
287        let spi = &SpiRegisterManager::new(self);
288
289        // TODO(alevy): we actually probably want to do this asynchrounously but
290        // because we're using DMA, a transfer may have completed with a byte
291        // still in the TX buffer.
292        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); // Disable NSSR
300        }
301    }
302
303    /// Sets the approximate baud rate for the active peripheral,
304    /// and return the actual baud rate set.
305    ///
306    /// Since the only supported baud rates are (system clock / n) where n
307    /// is an integer from 1 to 255, the exact baud rate may not
308    /// be available. In that case, the next lower baud rate will
309    /// be selected.
310    ///
311    /// The lowest available baud rate is 188235 baud. If the
312    /// requested rate is lower, 188235 baud will be selected.
313    pub fn set_baud_rate(&self, rate: u32) -> u32 {
314        // Main clock frequency
315        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        // Divide and truncate, resulting in a n value that might be too low
326        let mut scbr = clock / real_rate;
327        // If the division was not exact, increase the n to get a slower baud
328        // rate, but only if we are not at the slowest rate. Since scbr is the
329        // clock rate divisor, the highest divisor 0xFF corresponds to the
330        // lowest rate.
331        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    /// Returns the currently active peripheral
386    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                // default
396                Peripheral::Peripheral0
397            }
398        } else {
399            // The active peripheral is always 0 in slave mode
400            Peripheral::Peripheral0
401        }
402    }
403
404    /// Returns the value of CSR0, CSR1, CSR2, or CSR3,
405    /// whichever corresponds to the active peripheral
406    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    /// Set the DMA channels used for reading and writing.
419    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                // NSSR
430                client.chip_selected()
431            }
432            // TODO: Do we want to support byte-level interrupts too?
433            // They currently conflict with DMA.
434        });
435    }
436
437    /// Asynchronous buffer read/write of SPI.
438    ///
439    /// Returns:
440    /// - `Ok(())` if operation starts (will receive callback through
441    ///   SpiMasterClient)
442    /// - `INVAL` if no buffers were passed in
443    // The write buffer has to be mutable because it's passed back to
444    // the caller, and the caller may want to be able write into it.
445    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        // Start by enabling the SPI driver.
465        self.enable();
466
467        // Configure DMA to transfer that many bytes.
468        self.dma_length.set(count);
469
470        // Reset the number of transfers in progress. This is incremented
471        // depending on the presence of the read/write below
472        self.transfers_in_progress.set(0);
473
474        // Only setup the RX channel if we were passed a read_buffer inside
475        // of the option. `map()` checks this for us.
476        // The read DMA transfer has to be set up before the write because
477        // otherwise when the CPU speed is not significantly faster than the
478        // SPI's baud rate, transfer_done does not capture the interrupt
479        // signaling the RX is done - may be due to missing the first read
480        // byte when you start read after write.
481        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        // The ordering of these operations matters.
491        // For transfers 4 bytes or longer, this will work as expected.
492        // For shorter transfers, the first byte will be missing.
493        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    /// By default, initialize SPI to operate at 40KHz, clock is
514    /// idle on low, and sample on the leading edge.
515    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    /// Write a byte to the SPI and discard the read; if an
526    /// asynchronous operation is outstanding, do nothing.
527    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        // Wait for data to leave TDR and enter serializer, so TDR is free
532        // for this next byte
533        while !spi.registers.sr.is_set(Status::TDRE) {}
534        spi.registers.tdr.set(tdr);
535        Ok(())
536    }
537
538    /// Write 0 to the SPI and return the read; if an
539    /// asynchronous operation is outstanding, do nothing.
540    fn read_byte(&self) -> Result<u8, ErrorCode> {
541        self.read_write_byte(0)
542    }
543
544    /// Write a byte to the SPI and return the read; if an
545    /// asynchronous operation is outstanding, do nothing.
546    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    /// Asynchronous buffer read/write of SPI. `write_buffer` must be present;
555    /// `read_buffer` may be `None`. If read_buffer is present, then the length
556    /// of the read/write is the minimum of two buffer lengths.
557    ///
558    /// Returns:
559    /// - `Ok(())` if operation starts (will receive callback through
560    ///   SpiMasterClient)
561    /// - `BUSY` if the operation does not start
562    // The write buffer has to be mutable because it's passed back to
563    // the caller, and the caller may want to be able write into it.
564    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 busy, don't start.
577        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        // Slave cannot set active peripheral
634        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    // Set to None to disable the whole thing
652    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    /// This sets the value in the TDR register, to be sent as soon as the
667    /// chip select pin is low.
668    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    /// Setup buffers for a SPI transaction initiated by the master device.
674    ///
675    /// Returns:
676    /// - `Ok(())` if the operation starts. A callback will be generated.
677    /// - `INVAL` if neither the read or write buffer is provided.
678    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        // Only callback that the transfer is done if either:
735        // 1) The transfer was TX only and TX finished
736        // 2) The transfer was TX and RX, in that case wait for both of them to complete. Although
737        //    both transactions happen simultaneously over the wire, the DMA may not finish copying
738        //    data over to/from the controller at the same time, so we don't want to abort
739        //    prematurely.
740
741        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}