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}