1use core::cell::Cell;
6use core::cmp;
7use kernel::utilities::cells::MapCell;
8use kernel::utilities::leasable_buffer::SubSliceMut;
9use kernel::ErrorCode;
10
11use kernel::hil;
12use kernel::hil::spi::{self, ClockPhase, ClockPolarity, SpiMasterClient};
13use kernel::platform::chip::ClockInterface;
14use kernel::utilities::cells::OptionalCell;
15use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
16use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite};
17use kernel::utilities::StaticRef;
18
19use crate::rcc;
20
21const SPI_READ_IN_PROGRESS: u8 = 0b001;
22const SPI_WRITE_IN_PROGRESS: u8 = 0b010;
23const SPI_IN_PROGRESS: u8 = 0b100;
24const SPI_IDLE: u8 = 0b000;
25
26#[repr(C)]
28struct SpiRegisters {
29    cr1: ReadWrite<u32, CR1::Register>,
31    cr2: ReadWrite<u32, CR2::Register>,
33    sr: ReadWrite<u32, SR::Register>,
35    dr: ReadWrite<u8, DR::Register>,
40    crcpr: ReadWrite<u32, CRCPR::Register>,
42    rxcrcr: ReadOnly<u32, RXCRCR::Register>,
44    txcrcr: ReadOnly<u32, TXCRCR::Register>,
46    i2scfgr: ReadWrite<u32, I2SCFGR::Register>,
48    i2spr: ReadWrite<u32, I2SPR::Register>,
50}
51
52register_bitfields![u8,
53    DR [
54        DR OFFSET(0) NUMBITS(8) []
56    ]
57];
58
59register_bitfields![u32,
60    CR1 [
61        BIDIMODE OFFSET(15) NUMBITS(1) [],
63        BIDIOE OFFSET(14) NUMBITS(1) [],
65        CRCEN OFFSET(13) NUMBITS(1) [],
67        CRCNEXT OFFSET(12) NUMBITS(1) [],
69        CRCL OFFSET(11) NUMBITS(1) [],
71        RXONLY OFFSET(10) NUMBITS(1) [],
73        SSM OFFSET(9) NUMBITS(1) [],
75        SSI OFFSET(8) NUMBITS(1) [],
77        LSBFIRST OFFSET(7) NUMBITS(1) [],
79        SPE OFFSET(6) NUMBITS(1) [],
81        BR OFFSET(3) NUMBITS(3) [],
83        MSTR OFFSET(2) NUMBITS(1) [],
85        CPOL OFFSET(1) NUMBITS(1) [],
87        CPHA OFFSET(0) NUMBITS(1) []
89    ],
90    CR2 [
91        LDMA_TX OFFSET(14) NUMBITS(1) [],
93        LDMA_RX OFFSET(13) NUMBITS(1) [],
95        FRXTH OFFSET(12) NUMBITS(1) [],
97        DS OFFSET(8) NUMBITS(4) [],
99        TXEIE OFFSET(7) NUMBITS(1) [],
101        RXNEIE OFFSET(6) NUMBITS(1) [],
103        ERRIE OFFSET(5) NUMBITS(1) [],
105        FRF OFFSET(4) NUMBITS(1) [],
107        NSS OFFSET(3) NUMBITS(1) [],
109        SSOE OFFSET(2) NUMBITS(1) [],
111        TXDMAEN OFFSET(1) NUMBITS(1) [],
113        RXDMAEN OFFSET(0) NUMBITS(1) []
115    ],
116    SR [
117        FTLVL OFFSET(11) NUMBITS(2) [],
119        FRLVL OFFSET(9) NUMBITS(2) [],
121        FRE OFFSET(8) NUMBITS(1) [],
123        BSY OFFSET(7) NUMBITS(1) [],
125        OVR OFFSET(6) NUMBITS(1) [],
127        MODF OFFSET(5) NUMBITS(1) [],
129        CRCERR OFFSET(4) NUMBITS(1) [],
131        UDR OFFSET(3) NUMBITS(1) [],
133        CHSIDE OFFSET(2) NUMBITS(1) [],
135        TXE OFFSET(1) NUMBITS(1) [],
137        RXNE OFFSET(0) NUMBITS(1) []
139    ],
140    CRCPR [
141        CRCPOLY OFFSET(0) NUMBITS(16) []
143    ],
144    RXCRCR [
145        RXCRC OFFSET(0) NUMBITS(16) []
147    ],
148    TXCRCR [
149        TXCRC OFFSET(0) NUMBITS(16) []
151    ],
152    I2SCFGR [
153        I2SMOD OFFSET(11) NUMBITS(1) [],
155        I2SE OFFSET(10) NUMBITS(1) [],
157        I2SCFG OFFSET(8) NUMBITS(2) [],
159        PCMSYNC OFFSET(7) NUMBITS(1) [],
161        I2SSTD OFFSET(4) NUMBITS(2) [],
163        CKPOL OFFSET(3) NUMBITS(1) [],
165        DATLEN OFFSET(1) NUMBITS(2) [],
167        CHLEN OFFSET(0) NUMBITS(1) []
169    ],
170    I2SPR [
171        MCKOE OFFSET(9) NUMBITS(1) [],
173        ODD OFFSET(8) NUMBITS(1) [],
175        I2SDIV OFFSET(0) NUMBITS(8) []
177    ]
178];
179
180const SPI1_BASE: StaticRef<SpiRegisters> =
181    unsafe { StaticRef::new(0x4001_3000 as *const SpiRegisters) };
182
183pub struct Spi<'a> {
190    registers: StaticRef<SpiRegisters>,
191    clock: SpiClock<'a>,
192
193    master_client: OptionalCell<&'a dyn hil::spi::SpiMasterClient>,
195
196    active_slave: OptionalCell<spi::cs::ChipSelectPolar<'a, crate::gpio::Pin<'a>>>,
197
198    tx_buffer: MapCell<SubSliceMut<'static, u8>>,
199    tx_position: Cell<usize>,
200
201    rx_buffer: MapCell<SubSliceMut<'static, u8>>,
202    rx_position: Cell<usize>,
203    len: Cell<usize>,
204
205    transfers: Cell<u8>,
206
207    active_after: Cell<bool>,
208}
209
210impl<'a> Spi<'a> {
211    fn new(base_addr: StaticRef<SpiRegisters>, clock: SpiClock<'a>) -> Self {
212        Self {
213            registers: base_addr,
214            clock,
215
216            master_client: OptionalCell::empty(),
217            active_slave: OptionalCell::empty(),
218
219            tx_buffer: MapCell::empty(),
220            tx_position: Cell::new(0),
221
222            rx_buffer: MapCell::empty(),
223            rx_position: Cell::new(0),
224
225            len: Cell::new(0),
226
227            transfers: Cell::new(SPI_IDLE),
228
229            active_after: Cell::new(false),
230        }
231    }
232
233    pub fn new_spi1(rcc: &'a rcc::Rcc) -> Self {
234        Self::new(
235            SPI1_BASE,
236            SpiClock(rcc::PeripheralClock::new(
237                rcc::PeripheralClockType::APB2(rcc::PCLK2::SPI1),
238                rcc,
239            )),
240        )
241    }
242
243    pub fn is_enabled_clock(&self) -> bool {
244        self.clock.is_enabled()
245    }
246
247    pub fn enable_clock(&self) {
248        self.clock.enable();
249    }
250
251    pub fn disable_clock(&self) {
252        self.clock.disable();
253    }
254
255    pub fn handle_interrupt(&self) {
256        if self.registers.sr.is_set(SR::TXE) {
257            if self.tx_buffer.is_some() && self.tx_position.get() < self.len.get() {
258                self.tx_buffer.map(|buf| {
259                    self.registers
260                        .dr
261                        .write(DR::DR.val(buf[self.tx_position.get()]));
262                    self.tx_position.set(self.tx_position.get() + 1);
263                });
264            } else {
265                self.registers.cr2.modify(CR2::TXEIE::CLEAR);
266                self.transfers
267                    .set(self.transfers.get() & !SPI_WRITE_IN_PROGRESS);
268            }
269        }
270
271        if self.registers.sr.is_set(SR::RXNE) {
272            while self.registers.sr.read(SR::FRLVL) > 0 {
273                let byte = self.registers.dr.read(DR::DR);
274                if self.rx_buffer.is_some() && self.rx_position.get() < self.len.get() {
275                    self.rx_buffer.map(|buf| {
276                        buf[self.rx_position.get()] = byte;
277                    });
278                }
279                self.rx_position.set(self.rx_position.get() + 1);
280            }
281
282            if self.rx_position.get() >= self.len.get() {
283                self.transfers
284                    .set(self.transfers.get() & !SPI_READ_IN_PROGRESS);
285            }
286        }
287
288        if self.transfers.get() == SPI_IN_PROGRESS {
289            if !self.active_after.get() {
292                self.active_slave.map(|p| {
293                    p.deactivate();
294                });
295            }
296            self.transfers.set(SPI_IDLE);
297            self.master_client.map(|client| {
298                self.tx_buffer.take().map(|buf| {
299                    client.read_write_done(buf, self.rx_buffer.take(), Ok(self.len.get()))
300                })
301            });
302            self.transfers.set(SPI_IDLE);
303        }
304    }
305
306    fn set_cr<F>(&self, f: F)
307    where
308        F: FnOnce(),
309    {
310        self.registers.cr1.modify(CR1::SPE::CLEAR);
311        f();
312        self.registers.cr1.modify(CR1::SPE::SET);
313    }
314
315    fn set_polarity(&self, polarity: ClockPolarity) {
318        self.set_cr(|| match polarity {
319            ClockPolarity::IdleLow => self.registers.cr1.modify(CR1::CPOL::CLEAR),
320            ClockPolarity::IdleHigh => self.registers.cr1.modify(CR1::CPOL::SET),
321        });
322    }
323
324    fn get_polarity(&self) -> ClockPolarity {
325        if !self.registers.cr1.is_set(CR1::CPOL) {
326            ClockPolarity::IdleLow
327        } else {
328            ClockPolarity::IdleHigh
329        }
330    }
331
332    fn set_phase(&self, phase: ClockPhase) {
335        self.set_cr(|| match phase {
336            ClockPhase::SampleLeading => self.registers.cr1.modify(CR1::CPHA::CLEAR),
337            ClockPhase::SampleTrailing => self.registers.cr1.modify(CR1::CPHA::SET),
338        });
339    }
340
341    fn get_phase(&self) -> ClockPhase {
342        if !self.registers.cr1.is_set(CR1::CPHA) {
343            ClockPhase::SampleLeading
344        } else {
345            ClockPhase::SampleTrailing
346        }
347    }
348
349    fn read_write_bytes(
350        &self,
351        write_buffer: SubSliceMut<'static, u8>,
352        read_buffer: Option<SubSliceMut<'static, u8>>,
353    ) -> Result<
354        (),
355        (
356            ErrorCode,
357            SubSliceMut<'static, u8>,
358            Option<SubSliceMut<'static, u8>>,
359        ),
360    > {
361        if self.transfers.get() == 0 {
362            self.registers.cr2.modify(CR2::RXNEIE::CLEAR);
363            self.active_slave.map(|p| {
364                p.activate();
365            });
366
367            self.transfers.set(self.transfers.get() | SPI_IN_PROGRESS);
368
369            let mut count: usize = write_buffer.len();
370            read_buffer
371                .as_ref()
372                .map(|buf| count = cmp::min(count, buf.len()));
373
374            self.transfers
375                .set(self.transfers.get() | SPI_WRITE_IN_PROGRESS);
376
377            if read_buffer.is_some() {
378                self.transfers
379                    .set(self.transfers.get() | SPI_READ_IN_PROGRESS);
380            }
381
382            self.rx_position.set(0);
383
384            read_buffer.map(|buf| {
385                self.rx_buffer.replace(buf);
386                self.len.set(count);
387            });
388
389            self.registers.cr2.modify(CR2::RXNEIE::SET);
390
391            self.tx_buffer.replace(write_buffer);
392            self.len.set(count);
393            self.tx_position.set(0);
394            self.registers.cr2.modify(CR2::TXEIE::SET);
395
396            Ok(())
397        } else {
398            Err((ErrorCode::BUSY, write_buffer, read_buffer))
399        }
400    }
401}
402
403impl<'a> spi::SpiMaster<'a> for Spi<'a> {
404    type ChipSelect = spi::cs::ChipSelectPolar<'a, crate::gpio::Pin<'a>>;
405
406    fn set_client(&self, client: &'a dyn SpiMasterClient) {
407        self.master_client.set(client);
408    }
409
410    fn init(&self) -> Result<(), ErrorCode> {
411        self.registers
417            .cr2
418            .modify(CR2::DS.val(0b0111) + CR2::FRXTH::SET);
419
420        self.registers.cr1.modify(
425            CR1::BIDIMODE::CLEAR + CR1::MSTR::SET + CR1::SSM::SET + CR1::SSI::SET + CR1::SPE::SET,
426        );
427        Ok(())
428    }
429
430    fn is_busy(&self) -> bool {
431        self.registers.sr.is_set(SR::BSY)
432    }
433
434    fn write_byte(&self, out_byte: u8) -> Result<(), ErrorCode> {
435        while !self.registers.sr.is_set(SR::TXE) {}
438
439        self.registers.dr.modify(DR::DR.val(out_byte));
440        Ok(())
441    }
442
443    fn read_byte(&self) -> Result<u8, ErrorCode> {
444        self.read_write_byte(0)
445    }
446
447    fn read_write_byte(&self, val: u8) -> Result<u8, ErrorCode> {
448        self.write_byte(val)?;
449        while !self.registers.sr.is_set(SR::RXNE) {}
451        Ok(self.registers.dr.read(DR::DR))
452    }
453
454    fn read_write_bytes(
455        &self,
456        write_buffer: SubSliceMut<'static, u8>,
457        read_buffer: Option<SubSliceMut<'static, u8>>,
458    ) -> Result<
459        (),
460        (
461            ErrorCode,
462            SubSliceMut<'static, u8>,
463            Option<SubSliceMut<'static, u8>>,
464        ),
465    > {
466        if self.is_busy() {
468            return Err((ErrorCode::BUSY, write_buffer, read_buffer));
469        }
470
471        if let Err((err, write_buffer, read_buffer)) =
472            self.read_write_bytes(write_buffer, read_buffer)
473        {
474            Err((err, write_buffer, read_buffer))
475        } else {
476            Ok(())
477        }
478    }
479
480    fn set_rate(&self, rate: u32) -> Result<u32, ErrorCode> {
483        if rate != 1_000_000 {
485            return Err(ErrorCode::INVAL);
486        }
487
488        self.set_cr(|| {
489            self.registers.cr1.modify(CR1::BR.val(0b010));
491        });
492
493        Ok(1_000_000)
494    }
495
496    fn get_rate(&self) -> u32 {
499        if self.registers.cr1.read(CR1::BR) != 0b010 {
500            panic!("rate not set to 1_000_000");
501        }
502
503        1_000_000
504    }
505
506    fn set_polarity(&self, polarity: ClockPolarity) -> Result<(), ErrorCode> {
507        self.set_polarity(polarity);
508        Ok(())
509    }
510
511    fn get_polarity(&self) -> ClockPolarity {
512        self.get_polarity()
513    }
514
515    fn set_phase(&self, phase: ClockPhase) -> Result<(), ErrorCode> {
516        self.set_phase(phase);
517        Ok(())
518    }
519
520    fn get_phase(&self) -> ClockPhase {
521        self.get_phase()
522    }
523
524    fn hold_low(&self) {
525        self.active_after.set(true);
526    }
527
528    fn release_low(&self) {
529        self.active_after.set(false);
530    }
531
532    fn specify_chip_select(&self, cs: Self::ChipSelect) -> Result<(), ErrorCode> {
533        self.active_slave.set(cs);
534        Ok(())
535    }
536}
537
538struct SpiClock<'a>(rcc::PeripheralClock<'a>);
539
540impl ClockInterface for SpiClock<'_> {
541    fn is_enabled(&self) -> bool {
542        self.0.is_enabled()
543    }
544
545    fn enable(&self) {
546        self.0.enable();
547    }
548
549    fn disable(&self) {
550        self.0.disable();
551    }
552}