1use core::cell::Cell;
6
7use kernel::hil;
8use kernel::hil::i2c::{self, Error, I2CHwMasterClient, I2CMaster};
9use kernel::platform::chip::ClockInterface;
10use kernel::utilities::cells::{OptionalCell, TakeCell};
11use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
12use kernel::utilities::registers::{register_bitfields, ReadWrite};
13use kernel::utilities::StaticRef;
14
15use crate::rcc;
16
17pub enum I2CSpeed {
18 Speed100k,
19 Speed400k,
20 Speed1M,
21}
22
23#[repr(C)]
25struct I2CRegisters {
26 cr1: ReadWrite<u32, CR1::Register>,
28 cr2: ReadWrite<u32, CR2::Register>,
30 oar1: ReadWrite<u32, OAR1::Register>,
32 oar2: ReadWrite<u32, OAR2::Register>,
34 timingr: ReadWrite<u32, TIMINGR::Register>,
36 timeout: ReadWrite<u32, TIMEOUT::Register>,
38 isr: ReadWrite<u32, ISR::Register>,
40 icr: ReadWrite<u32, ICR::Register>,
42 pecr: ReadWrite<u32, PECR::Register>,
44 rxdr: ReadWrite<u32, RXDR::Register>,
46 txdr: ReadWrite<u32, TXDR::Register>,
48}
49
50register_bitfields![u32,
51 CR1 [
52 PCEN OFFSET(23) NUMBITS(1) [],
54 ALERTEN OFFSET(22) NUMBITS(1) [],
56 SMBDEN OFFSET(21) NUMBITS(1) [],
58 SMBHEN OFFSET(20) NUMBITS(1) [],
60 GCEN OFFSET(19) NUMBITS(1) [],
62 WUPEN OFFSET(18) NUMBITS(1) [],
64 NOSTRETCH OFFSET(17) NUMBITS(1) [],
66 SBC OFFSET(16) NUMBITS(1) [],
68 RXDMAEN OFFSET(15) NUMBITS(1) [],
70 TXDMAEN OFFSET(14) NUMBITS(1) [],
72 ANOFF OFFSET(12) NUMBITS(1) [],
74 DNF OFFSET(8) NUMBITS(4) [],
76 ERRIE OFFSET(7) NUMBITS(1) [],
78 TCIE OFFSET(6) NUMBITS(1) [],
80 STOPIE OFFSET(5) NUMBITS(1) [],
82 NACKIE OFFSET(4) NUMBITS(1) [],
84 ADDRIE OFFSET(3) NUMBITS(3) [],
86 RXIE OFFSET(2) NUMBITS(1) [],
88 TXIE OFFSET(1) NUMBITS(1) [],
90 PE OFFSET(0) NUMBITS(1) []
92 ],
93 CR2 [
94 PECBYTE OFFSET(26) NUMBITS(1) [],
96 AUTOEND OFFSET(25) NUMBITS(1) [],
98 RELOAD OFFSET(24) NUMBITS(1) [],
100 NBYTES OFFSET(16) NUMBITS(8) [],
102 NACK OFFSET(15) NUMBITS(1) [],
104 STOP OFFSET(14) NUMBITS(1) [],
106 START OFFSET(13) NUMBITS(1) [],
108 HEAD10R OFFSET(12) NUMBITS(1) [],
110 ADD10 OFFSET(11) NUMBITS(1) [],
112 RD_WRN OFFSET(10) NUMBITS(1) [],
114 SADD8_9 OFFSET(8) NUMBITS(2) [],
116 SADD7_1 OFFSET(1) NUMBITS(7) [],
118 SADD OFFSET(0) NUMBITS(1) []
120 ],
121 OAR1 [
122 OA1EN OFFSET(15) NUMBITS(1) [],
124 OA1MODE OFFSET(10) NUMBITS(1) [],
126 OA1 OFFSET(0) NUMBITS(10) []
128 ],
129 OAR2 [
130 OA2EN OFFSET(15) NUMBITS(1) [],
132 OA2MSK OFFSET(8) NUMBITS(3) [],
134 OA2 OFFSET(1) NUMBITS(7) []
136 ],
137 TIMINGR [
138 PRESC OFFSET(28) NUMBITS(4) [],
140 SCLDEL OFFSET(20) NUMBITS(4) [],
142 SDAEL OFFSET(16) NUMBITS(4) [],
144 SCLH OFFSET(8) NUMBITS(8) [],
146 SCLL OFFSET(0) NUMBITS(8) []
148 ],
149 TIMEOUT [
150 TEXTEN OFFSET(31) NUMBITS(1) [],
152 TIMEOUTB OFFSET(16) NUMBITS(12) [],
154 TIMOUTEN OFFSET(15) NUMBITS(1) [],
156 TIDLE OFFSET(12) NUMBITS(1) [],
158 TIMEOUTA OFFSET(0) NUMBITS(12) []
160 ],
161 ISR [
162 ADDCODE OFFSET(17) NUMBITS(7) [],
164 DIR OFFSET(16) NUMBITS(1) [],
166 BUSY OFFSET(15) NUMBITS(1) [],
168 ALERT OFFSET(13) NUMBITS(1) [],
170 TIMEOUT OFFSET(12) NUMBITS(1) [],
172 PECERR OFFSET(11) NUMBITS(1) [],
174 OVR OFFSET(10) NUMBITS(1) [],
176 ARLO OFFSET(9) NUMBITS(1) [],
178 BERR OFFSET(8) NUMBITS(1) [],
180 TCR OFFSET(7) NUMBITS(1) [],
182 TC OFFSET(6) NUMBITS(1) [],
184 STOPF OFFSET(5) NUMBITS(1) [],
186 NACKF OFFSET(4) NUMBITS(1) [],
188 ADDR OFFSET(3) NUMBITS(1) [],
190 RXNE OFFSET(2) NUMBITS(1) [],
192 TXIS OFFSET(1) NUMBITS(1) [],
194 TXE OFFSET(0) NUMBITS(1) []
196 ],
197 ICR [
198 ALERTCF OFFSET(13) NUMBITS(1) [],
200 TIMOUTCF OFFSET(12) NUMBITS(1) [],
202 PECCF OFFSET(11) NUMBITS(1) [],
204 OVRCF OFFSET(10) NUMBITS(1) [],
206 ARLOCF OFFSET(9) NUMBITS(1) [],
208 BERRCF OFFSET(8) NUMBITS(1) [],
210 STOPCF OFFSET(5) NUMBITS(1) [],
212 NACKCF OFFSET(4) NUMBITS(1) [],
214 ADDRCF OFFSET(3) NUMBITS(1) []
216 ],
217 PECR [
218 PEC OFFSET(0) NUMBITS(8) []
220 ],
221 RXDR [
222 RXDATA OFFSET(0) NUMBITS(8) []
224 ],
225 TXDR [
226 TXDATA OFFSET(0) NUMBITS(8) []
228 ]
229];
230
231const I2C1_BASE: StaticRef<I2CRegisters> =
232 unsafe { StaticRef::new(0x4000_5400 as *const I2CRegisters) };
233
234pub struct I2C<'a> {
238 registers: StaticRef<I2CRegisters>,
239 clock: I2CClock<'a>,
240
241 master_client: OptionalCell<&'a dyn hil::i2c::I2CHwMasterClient>,
243
244 buffer: TakeCell<'static, [u8]>,
245 tx_position: Cell<usize>,
246 rx_position: Cell<usize>,
247 tx_len: Cell<usize>,
248 rx_len: Cell<usize>,
249
250 slave_address: Cell<u8>,
251
252 status: Cell<I2CStatus>,
253 }
255
256#[derive(Copy, Clone, PartialEq)]
257enum I2CStatus {
258 Idle,
259 Writing,
260 WritingReading,
261 Reading,
262}
263
264impl<'a> I2C<'a> {
265 fn new(base_addr: StaticRef<I2CRegisters>, clock: I2CClock<'a>) -> Self {
266 Self {
267 registers: base_addr,
268 clock,
269
270 master_client: OptionalCell::empty(),
271
272 slave_address: Cell::new(0),
273
274 buffer: TakeCell::empty(),
275 tx_position: Cell::new(0),
276 rx_position: Cell::new(0),
277
278 tx_len: Cell::new(0),
279 rx_len: Cell::new(0),
280
281 status: Cell::new(I2CStatus::Idle),
282 }
283 }
284
285 pub fn new_i2c1(rcc: &'a rcc::Rcc) -> Self {
286 Self::new(
287 I2C1_BASE,
288 I2CClock(rcc::PeripheralClock::new(
289 rcc::PeripheralClockType::APB1(rcc::PCLK1::I2C1),
290 rcc,
291 )),
292 )
293 }
294
295 pub fn set_speed(&self, speed: I2CSpeed, system_clock_in_mhz: usize) {
296 self.disable();
297 match speed {
298 I2CSpeed::Speed100k => {
299 let prescaler = system_clock_in_mhz / 4 - 1;
300 self.registers.timingr.modify(
301 TIMINGR::PRESC.val(prescaler as u32)
302 + TIMINGR::SCLL.val(19)
303 + TIMINGR::SCLH.val(15)
304 + TIMINGR::SDAEL.val(2)
305 + TIMINGR::SCLDEL.val(4),
306 );
307 }
308 I2CSpeed::Speed400k => {
309 let prescaler = system_clock_in_mhz / 8 - 1;
310 self.registers.timingr.modify(
311 TIMINGR::PRESC.val(prescaler as u32)
312 + TIMINGR::SCLL.val(9)
313 + TIMINGR::SCLH.val(3)
314 + TIMINGR::SDAEL.val(3)
315 + TIMINGR::SCLDEL.val(3),
316 );
317 }
318 I2CSpeed::Speed1M => {
319 panic!("i2c speed 1MHz not implemented");
320 }
321 }
322 self.enable();
323 }
324
325 pub fn is_enabled_clock(&self) -> bool {
326 self.clock.is_enabled()
327 }
328
329 pub fn enable_clock(&self) {
330 self.clock.enable();
331 }
332
333 pub fn disable_clock(&self) {
334 self.clock.disable();
335 }
336
337 pub fn handle_event(&self) {
338 if self.registers.isr.is_set(ISR::TXIS) {
339 if self.buffer.is_some() && self.tx_position.get() < self.tx_len.get() {
341 self.buffer.map(|buf| {
342 let byte = buf[self.tx_position.get()];
343 self.registers.txdr.write(TXDR::TXDATA.val(byte as u32));
344 self.tx_position.set(self.tx_position.get() + 1);
345 });
346 } else {
347 panic!("i2c attempted to read more bytes than the available buffer");
348 }
349 }
350
351 while self.registers.isr.is_set(ISR::RXNE) {
352 let byte = self.registers.rxdr.read(RXDR::RXDATA) as u8;
354 if self.buffer.is_some() && self.rx_position.get() < self.rx_len.get() {
355 self.buffer.map(|buf| {
356 buf[self.rx_position.get()] = byte;
357 self.rx_position.set(self.rx_position.get() + 1);
358 });
359 }
360 }
361
362 if self.registers.isr.is_set(ISR::TC) {
363 match self.status.get() {
364 I2CStatus::Writing | I2CStatus::WritingReading => {
365 if self.tx_position.get() < self.tx_len.get() {
366 self.registers.cr2.modify(CR2::STOP::SET);
367 self.stop();
368 self.master_client.map(|client| {
369 self.buffer
370 .take()
371 .map(|buf| client.command_complete(buf, Err(Error::DataNak)))
372 });
373 } else {
374 if self.status.get() == I2CStatus::Writing {
375 self.registers.cr2.modify(CR2::STOP::SET);
376 self.stop();
377 self.master_client.map(|client| {
378 self.buffer
379 .take()
380 .map(|buf| client.command_complete(buf, Ok(())))
381 });
382 } else {
383 self.status.set(I2CStatus::Reading);
384 self.start_read();
385 }
386 }
387 }
388 I2CStatus::Reading => {
389 let status = if self.rx_position.get() == self.rx_len.get() {
390 Ok(())
391 } else {
392 Err(Error::DataNak)
393 };
394 self.registers.cr2.modify(CR2::STOP::SET);
395 self.stop();
396 self.master_client.map(|client| {
397 self.buffer
398 .take()
399 .map(|buf| client.command_complete(buf, status))
400 });
401 }
402 _ => panic!("i2c status error"),
403 }
404 }
405
406 if self.registers.isr.is_set(ISR::NACKF) {
407 self.registers.cr2.modify(CR2::STOP::SET);
409 self.stop();
410 self.registers.icr.modify(ICR::NACKCF::SET);
411 self.master_client.map(|client| {
412 self.buffer
413 .take()
414 .map(|buf| client.command_complete(buf, Err(Error::AddressNak)))
415 });
416 }
417 }
418
419 pub fn handle_error(&self) {
420 self.master_client.map(|client| {
422 self.buffer
423 .take()
424 .map(|buf| client.command_complete(buf, Err(Error::DataNak)))
425 });
426 self.stop();
427 }
428
429 fn reset(&self) {
430 self.disable();
431 self.enable();
432 }
433
434 fn start_write(&self) {
435 self.tx_position.set(0);
436 self.registers
437 .cr2
438 .modify(CR2::NBYTES.val(self.tx_len.get() as u32));
439 self.registers
440 .cr2
441 .modify(CR2::SADD7_1.val(self.slave_address.get() as u32));
442 self.registers.cr2.modify(CR2::RD_WRN::CLEAR);
443 self.registers
444 .cr1
445 .modify(CR1::TXIE::SET + CR1::ERRIE::SET + CR1::NACKIE::SET + CR1::TCIE::SET);
446 self.registers.cr2.modify(CR2::START::SET);
447 }
448
449 fn stop(&self) {
450 self.registers.cr1.modify(
451 CR1::TXIE::CLEAR
452 + CR1::ERRIE::CLEAR
453 + CR1::NACKIE::CLEAR
454 + CR1::TCIE::CLEAR
455 + CR1::STOPIE::CLEAR
456 + CR1::RXIE::CLEAR,
457 );
458 self.status.set(I2CStatus::Idle);
459 }
460
461 fn start_read(&self) {
462 self.rx_position.set(0);
463 self.registers
464 .cr2
465 .modify(CR2::NBYTES.val(self.rx_len.get() as u32));
466 self.registers
467 .cr2
468 .modify(CR2::SADD7_1.val(self.slave_address.get() as u32));
469 self.registers.cr2.modify(CR2::AUTOEND::CLEAR);
470 self.registers.cr2.modify(CR2::RD_WRN::SET);
471 self.registers
472 .cr1
473 .modify(CR1::ERRIE::SET + CR1::NACKIE::SET + CR1::TCIE::SET + CR1::RXIE::SET);
474 self.registers.cr2.modify(CR2::START::SET);
475 }
476}
477
478impl<'a> i2c::I2CMaster<'a> for I2C<'a> {
479 fn set_master_client(&self, master_client: &'a dyn I2CHwMasterClient) {
480 self.master_client.replace(master_client);
481 }
482 fn enable(&self) {
483 self.registers.cr1.modify(CR1::PE::SET);
484 }
485 fn disable(&self) {
486 self.registers.cr1.modify(CR1::PE::CLEAR);
487 }
488 fn write_read(
489 &self,
490 addr: u8,
491 data: &'static mut [u8],
492 write_len: usize,
493 read_len: usize,
494 ) -> Result<(), (Error, &'static mut [u8])> {
495 if self.status.get() == I2CStatus::Idle {
496 self.reset();
497 self.status.set(I2CStatus::WritingReading);
498 self.slave_address.set(addr);
499 self.buffer.replace(data);
500 self.tx_len.set(write_len);
501 self.rx_len.set(read_len);
502 self.registers.cr2.modify(CR2::AUTOEND::CLEAR);
503 self.start_write();
504 Ok(())
505 } else {
506 Err((Error::Busy, data))
507 }
508 }
509 fn write(
510 &self,
511 addr: u8,
512 data: &'static mut [u8],
513 len: usize,
514 ) -> Result<(), (Error, &'static mut [u8])> {
515 if self.status.get() == I2CStatus::Idle {
516 self.reset();
517 self.status.set(I2CStatus::Writing);
518 self.slave_address.set(addr);
519 self.buffer.replace(data);
520 self.tx_len.set(len);
521 self.registers.cr2.modify(CR2::AUTOEND::CLEAR);
522 self.start_write();
523 Ok(())
524 } else {
525 Err((Error::Busy, data))
526 }
527 }
528 fn read(
529 &self,
530 addr: u8,
531 buffer: &'static mut [u8],
532 len: usize,
533 ) -> Result<(), (Error, &'static mut [u8])> {
534 if self.status.get() == I2CStatus::Idle {
535 self.reset();
536 self.status.set(I2CStatus::Reading);
537 self.slave_address.set(addr);
538 self.buffer.replace(buffer);
539 self.rx_len.set(len);
540 self.registers.cr2.modify(CR2::AUTOEND::CLEAR);
541 self.start_read();
542 Ok(())
543 } else {
544 Err((Error::Busy, buffer))
545 }
546 }
547}
548
549struct I2CClock<'a>(rcc::PeripheralClock<'a>);
550
551impl ClockInterface for I2CClock<'_> {
552 fn is_enabled(&self) -> bool {
553 self.0.is_enabled()
554 }
555
556 fn enable(&self) {
557 self.0.enable();
558 }
559
560 fn disable(&self) {
561 self.0.disable();
562 }
563}