1use core::cell::Cell;
6use core::cmp;
7use kernel::utilities::leasable_buffer::SubSliceMut;
8use kernel::ErrorCode;
9
10use kernel::hil;
11use kernel::hil::gpio::Output;
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};
16use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite};
17use kernel::utilities::StaticRef;
18
19use crate::clocks::phclk;
20use crate::dma;
21use crate::dma::{Dma1, Dma1Peripheral};
22
23#[repr(C)]
25pub struct SpiRegisters {
26 cr1: ReadWrite<u32, CR1::Register>,
28 cr2: ReadWrite<u32, CR2::Register>,
30 sr: ReadWrite<u32, SR::Register>,
32 dr: ReadWrite<u32, DR::Register>,
34 crcpr: ReadWrite<u32>,
36 rxcrcr: ReadOnly<u32>,
38 txcrcr: ReadOnly<u32>,
40 i2scfgr: ReadWrite<u32, I2SCFGR::Register>,
42 i2spr: ReadWrite<u32, I2SPR::Register>,
44}
45
46register_bitfields![u32,
47 CR1 [
48 BIDIMODE OFFSET(15) NUMBITS(1) [],
50 BIDIOE OFFSET(14) NUMBITS(1) [],
52 CRCEN OFFSET(13) NUMBITS(1) [],
54 CRCNEXT OFFSET(12) NUMBITS(1) [],
56 DFF OFFSET(11) NUMBITS(1) [],
58 RXONLY OFFSET(10) NUMBITS(1) [],
60 SSM OFFSET(9) NUMBITS(1) [],
62 SSI OFFSET(8) NUMBITS(1) [],
64 LSBFIRST OFFSET(7) NUMBITS(1) [],
66 SPE OFFSET(6) NUMBITS(1) [],
68 BR OFFSET(3) NUMBITS(3) [],
70 MSTR OFFSET(2) NUMBITS(1) [],
72 CPOL OFFSET(1) NUMBITS(1) [],
74 CPHA OFFSET(0) NUMBITS(1) []
76 ],
77 CR2 [
78 TXEIE OFFSET(7) NUMBITS(1) [],
80 RXNEIE OFFSET(6) NUMBITS(1) [],
82 ERRIE OFFSET(5) NUMBITS(1) [],
84 FRF OFFSET(4) NUMBITS(1) [],
86 SSOE OFFSET(2) NUMBITS(1) [],
88 TXDMAEN OFFSET(1) NUMBITS(1) [],
90 RXDMAEN OFFSET(0) NUMBITS(1) []
92 ],
93 SR [
94 TIFRFE OFFSET(8) NUMBITS(1) [],
96 BSY OFFSET(7) NUMBITS(1) [],
98 OVR OFFSET(6) NUMBITS(1) [],
100 MODF OFFSET(5) NUMBITS(1) [],
102 CRCERR OFFSET(4) NUMBITS(1) [],
104 UDR OFFSET(3) NUMBITS(1) [],
106 CHSIDE OFFSET(2) NUMBITS(1) [],
108 TXE OFFSET(1) NUMBITS(1) [],
110 RXNE OFFSET(0) NUMBITS(1) []
112 ],
113 DR [
114 DR OFFSET(0) NUMBITS(8) []
116 ],
117 I2SCFGR [
118 I2SMOD OFFSET(11) NUMBITS(1) [],
120 I2SE OFFSET(10) NUMBITS(1) [],
122 I2SCFG OFFSET(8) NUMBITS(2) [],
124 PCMSYNC OFFSET(7) NUMBITS(1) [],
126 I2SSTD OFFSET(4) NUMBITS(2) [],
128 CKPOL OFFSET(3) NUMBITS(1) [],
130 DATLEN OFFSET(1) NUMBITS(2) [],
132 CHLEN OFFSET(0) NUMBITS(1) []
134 ],
135 I2SPR [
136 MCKOE OFFSET(9) NUMBITS(1) [],
138 ODD OFFSET(8) NUMBITS(1) [],
140 I2SDIV OFFSET(0) NUMBITS(8) []
142 ]
143];
144
145pub(crate) fn get_address_dr(regs: StaticRef<SpiRegisters>) -> u32 {
147 core::ptr::addr_of!(regs.dr) as u32
148}
149
150pub const SPI3_BASE: StaticRef<SpiRegisters> =
151 unsafe { StaticRef::new(0x40003C00 as *const SpiRegisters) };
152
153pub struct Spi<'a> {
154 registers: StaticRef<SpiRegisters>,
155 clock: SpiClock<'a>,
156
157 master_client: OptionalCell<&'a dyn hil::spi::SpiMasterClient>,
159
160 tx_dma: OptionalCell<&'a dma::Stream<'a, Dma1<'a>>>,
161 tx_dma_pid: Dma1Peripheral,
162 rx_dma: OptionalCell<&'a dma::Stream<'a, Dma1<'a>>>,
163 rx_dma_pid: Dma1Peripheral,
164
165 dma_len: Cell<usize>,
166 transfers_in_progress: Cell<u8>,
167
168 active_slave: OptionalCell<&'a crate::gpio::Pin<'a>>,
169
170 active_after: Cell<bool>,
171}
172
173pub struct TxDMA<'a>(pub &'a dma::Stream<'a, Dma1<'a>>);
175pub struct RxDMA<'a>(pub &'a dma::Stream<'a, Dma1<'a>>);
176
177impl<'a> Spi<'a> {
178 pub const fn new(
179 base_addr: StaticRef<SpiRegisters>,
180 clock: SpiClock<'a>,
181 tx_dma_pid: Dma1Peripheral,
182 rx_dma_pid: Dma1Peripheral,
183 ) -> Spi<'a> {
184 Spi {
185 registers: base_addr,
186 clock,
187
188 master_client: OptionalCell::empty(),
189
190 tx_dma: OptionalCell::empty(),
191 tx_dma_pid,
192 rx_dma: OptionalCell::empty(),
193 rx_dma_pid,
194
195 dma_len: Cell::new(0),
196 transfers_in_progress: Cell::new(0),
197
198 active_slave: OptionalCell::empty(),
199
200 active_after: Cell::new(false),
201 }
202 }
203
204 pub fn is_enabled_clock(&self) -> bool {
205 self.clock.is_enabled()
206 }
207
208 pub fn enable_clock(&self) {
209 self.clock.enable();
210 }
211
212 pub fn disable_clock(&self) {
213 self.clock.disable();
214 }
215
216 pub fn set_dma(&self, tx_dma: TxDMA<'a>, rx_dma: RxDMA<'a>) {
217 self.tx_dma.set(tx_dma.0);
218 self.rx_dma.set(rx_dma.0);
219 }
220
221 pub fn handle_interrupt(&self) {
222 }
225
226 fn set_active_slave(&self, slave_pin: &'a crate::gpio::Pin<'a>) {
227 self.active_slave.set(slave_pin);
228 }
229
230 fn set_cr<F>(&self, f: F)
231 where
232 F: FnOnce(),
233 {
234 self.registers.cr1.modify(CR1::SPE::CLEAR);
235 f();
236 self.registers.cr1.modify(CR1::SPE::SET);
237 }
238
239 fn set_polarity(&self, polarity: ClockPolarity) {
242 self.set_cr(|| match polarity {
243 ClockPolarity::IdleLow => self.registers.cr1.modify(CR1::CPOL::CLEAR),
244 ClockPolarity::IdleHigh => self.registers.cr1.modify(CR1::CPOL::SET),
245 });
246 }
247
248 fn get_polarity(&self) -> ClockPolarity {
249 if !self.registers.cr1.is_set(CR1::CPOL) {
250 ClockPolarity::IdleLow
251 } else {
252 ClockPolarity::IdleHigh
253 }
254 }
255
256 fn set_phase(&self, phase: ClockPhase) {
259 self.set_cr(|| match phase {
260 ClockPhase::SampleLeading => self.registers.cr1.modify(CR1::CPHA::CLEAR),
261 ClockPhase::SampleTrailing => self.registers.cr1.modify(CR1::CPHA::SET),
262 });
263 }
264
265 fn get_phase(&self) -> ClockPhase {
266 if !self.registers.cr1.is_set(CR1::CPHA) {
267 ClockPhase::SampleLeading
268 } else {
269 ClockPhase::SampleTrailing
270 }
271 }
272
273 fn enable_tx(&self) {
274 self.registers.cr2.modify(CR2::TXDMAEN::SET);
275 }
276
277 fn disable_tx(&self) {
278 self.registers.cr2.modify(CR2::TXDMAEN::CLEAR);
279 }
280
281 fn enable_rx(&self) {
282 self.registers.cr2.modify(CR2::RXDMAEN::SET);
283 }
284
285 fn disable_rx(&self) {
286 self.registers.cr2.modify(CR2::RXDMAEN::CLEAR);
287 }
288
289 fn read_write_bytes(
290 &self,
291 write_buffer: SubSliceMut<'static, u8>,
292 read_buffer: Option<SubSliceMut<'static, u8>>,
293 ) -> Result<
294 (),
295 (
296 ErrorCode,
297 SubSliceMut<'static, u8>,
298 Option<SubSliceMut<'static, u8>>,
299 ),
300 > {
301 self.active_slave.map(|p| {
302 p.clear();
303 });
304
305 let mut count: usize = write_buffer.len();
306 read_buffer
307 .as_ref()
308 .map(|buf| count = cmp::min(count, buf.len()));
309
310 self.dma_len.set(count);
311
312 self.transfers_in_progress.set(0);
313
314 read_buffer.map(|rx_buffer| {
315 self.transfers_in_progress
316 .set(self.transfers_in_progress.get() + 1);
317 self.rx_dma.map(move |dma| {
318 dma.do_transfer(rx_buffer);
319 });
320 self.enable_rx();
321 });
322
323 self.transfers_in_progress
324 .set(self.transfers_in_progress.get() + 1);
325 self.tx_dma.map(move |dma| {
326 dma.do_transfer(write_buffer);
327 });
328 self.enable_tx();
329
330 Ok(())
331 }
332}
333
334impl<'a> spi::SpiMaster<'a> for Spi<'a> {
335 type ChipSelect = &'a crate::gpio::Pin<'a>;
336
337 fn set_client(&self, client: &'a dyn SpiMasterClient) {
338 self.master_client.set(client);
339 }
340
341 fn init(&self) -> Result<(), ErrorCode> {
342 self.registers.cr1.modify(
351 CR1::BIDIMODE::CLEAR
352 + CR1::MSTR::SET
353 + CR1::SSM::SET
354 + CR1::SSI::SET
355 + CR1::DFF::CLEAR
356 + CR1::SPE::SET,
357 );
358 Ok(())
359 }
360
361 fn is_busy(&self) -> bool {
362 self.registers.sr.is_set(SR::BSY)
363 }
364
365 fn write_byte(&self, out_byte: u8) -> Result<(), ErrorCode> {
366 while !self.registers.sr.is_set(SR::TXE) {}
368
369 self.registers.dr.modify(DR::DR.val(out_byte as u32));
370 Ok(())
371 }
372
373 fn read_byte(&self) -> Result<u8, ErrorCode> {
374 self.read_write_byte(0)
375 }
376
377 fn read_write_byte(&self, val: u8) -> Result<u8, ErrorCode> {
378 match self.write_byte(val) {
379 Ok(()) => {
380 while !self.registers.sr.is_set(SR::RXNE) {}
382
383 Ok(self.registers.dr.read(DR::DR) as u8)
384 }
385 Err(e) => Err(e),
386 }
387 }
388
389 fn read_write_bytes(
390 &self,
391 write_buffer: SubSliceMut<'static, u8>,
392 read_buffer: Option<SubSliceMut<'static, u8>>,
393 ) -> Result<
394 (),
395 (
396 ErrorCode,
397 SubSliceMut<'static, u8>,
398 Option<SubSliceMut<'static, u8>>,
399 ),
400 > {
401 if self.is_busy() {
403 return Err((ErrorCode::BUSY, write_buffer, read_buffer));
404 }
405
406 self.read_write_bytes(write_buffer, read_buffer)
407 }
408
409 fn set_rate(&self, rate: u32) -> Result<u32, ErrorCode> {
412 match rate {
413 1_000_000 => self.set_cr(|| {
414 self.registers.cr1.modify(CR1::BR.val(0b011));
416 }),
417 4_000_000 => self.set_cr(|| {
418 self.registers.cr1.modify(CR1::BR.val(0b001));
420 }),
421 _ => panic!("SPI rate must be 1_000_000 or 4_000_000"),
422 }
423 Ok(rate)
424 }
425
426 fn get_rate(&self) -> u32 {
429 match self.registers.cr1.read(CR1::BR) {
431 0b011 => 1_000_000, 0b001 => 4_000_000, _ => panic!("Current SPI rate not supported by tock OS!"),
434 }
435 }
436
437 fn set_polarity(&self, polarity: ClockPolarity) -> Result<(), ErrorCode> {
438 self.set_polarity(polarity);
439 Ok(())
440 }
441
442 fn get_polarity(&self) -> ClockPolarity {
443 self.get_polarity()
444 }
445
446 fn set_phase(&self, phase: ClockPhase) -> Result<(), ErrorCode> {
447 self.set_phase(phase);
448 Ok(())
449 }
450
451 fn get_phase(&self) -> ClockPhase {
452 self.get_phase()
453 }
454
455 fn hold_low(&self) {
456 self.active_after.set(true);
457 }
458
459 fn release_low(&self) {
460 self.active_after.set(false);
461 }
462
463 fn specify_chip_select(&self, cs: Self::ChipSelect) -> Result<(), ErrorCode> {
464 self.set_active_slave(cs);
465 Ok(())
466 }
467}
468
469impl<'a> dma::StreamClient<'a, Dma1<'a>> for Spi<'a> {
470 fn transfer_done(&self, pid: Dma1Peripheral) {
471 if pid == self.tx_dma_pid {
472 self.disable_tx();
473 }
474
475 if pid == self.rx_dma_pid {
476 self.disable_rx();
477 }
478
479 self.transfers_in_progress
480 .set(self.transfers_in_progress.get() - 1);
481
482 if self.transfers_in_progress.get() == 0 {
483 if !self.active_after.get() {
484 self.active_slave.map(|p| {
485 p.set();
486 });
487 }
488
489 let tx_buffer = self.tx_dma.and_then(|tx_dma| tx_dma.return_buffer());
490 let rx_buffer = self.rx_dma.and_then(|rx_dma| rx_dma.return_buffer());
491
492 let length = self.dma_len.get();
493 self.dma_len.set(0);
494
495 self.master_client.map(|client| {
496 tx_buffer.map(|t| {
497 client.read_write_done(t, rx_buffer, Ok(length));
498 });
499 });
500 }
501 }
502}
503
504pub struct SpiClock<'a>(pub phclk::PeripheralClock<'a>);
505
506impl ClockInterface for SpiClock<'_> {
507 fn is_enabled(&self) -> bool {
508 self.0.is_enabled()
509 }
510
511 fn enable(&self) {
512 self.0.enable();
513 }
514
515 fn disable(&self) {
516 self.0.disable();
517 }
518}