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::clocks::{phclk, Stm32f4Clocks};
16
17pub enum I2CSpeed {
18 Speed100k,
19 Speed400k,
20}
21
22#[repr(C)]
24struct I2CRegisters {
25 cr1: ReadWrite<u32, CR1::Register>,
27 cr2: ReadWrite<u32, CR2::Register>,
29 oar1: ReadWrite<u32, OAR1::Register>,
31 oar2: ReadWrite<u32, OAR2::Register>,
33 dr: ReadWrite<u32, DR::Register>,
35 sr1: ReadWrite<u32, SR1::Register>,
37 sr2: ReadWrite<u32, SR2::Register>,
39 ccr: ReadWrite<u32, CCR::Register>,
41 trise: ReadWrite<u32, TRISE::Register>,
43 fltr: ReadWrite<u32, FLTR::Register>,
45}
46
47register_bitfields![u32,
48 CR1 [
49 SWRST OFFSET(15) NUMBITS(1) [],
51 ALERT OFFSET(13) NUMBITS(1) [],
53 PEC OFFSET(12) NUMBITS(1) [],
55 POS OFFSET(11) NUMBITS(1) [],
57 ACK OFFSET(10) NUMBITS(1) [],
59 STOP OFFSET(9) NUMBITS(1) [],
61 START OFFSET(8) NUMBITS(1) [],
63 NOSTRETCH OFFSET(7) NUMBITS(1) [],
65 ENGC OFFSET(6) NUMBITS(1) [],
67 ENPEC OFFSET(5) NUMBITS(1) [],
69 ENARP OFFSET(4) NUMBITS(1) [],
71 SMBTYPE OFFSET(3) NUMBITS(1) [],
73 SMBUS OFFSET(1) NUMBITS(1) [],
75 PE OFFSET(0) NUMBITS(1) []
77 ],
78 CR2 [
79 LAST OFFSET(12) NUMBITS(1) [],
81 DMAEN OFFSET(11) NUMBITS(1) [],
83 ITBUFEN OFFSET(10) NUMBITS(1) [],
85 ITEVTEN OFFSET(9) NUMBITS(1) [],
87 ITERREN OFFSET(8) NUMBITS(1) [],
89 FREQ OFFSET(0) NUMBITS(6) []
91 ],
92 OAR1 [
93 ADDMODE OFFSET(15) NUMBITS(1) [],
95 ADD OFFSET(0) NUMBITS(10) []
97 ],
98 OAR2 [
99 ADD2 OFFSET(1) NUMBITS(7) [],
101 ENDUAL OFFSET(1) NUMBITS(1) []
103 ],
104 DR [
105 DR OFFSET(0) NUMBITS(8) []
107 ],
108 SR1 [
109 SMBALERT OFFSET(15) NUMBITS(1) [],
111 TIMEOUT OFFSET(14) NUMBITS(1) [],
113 PECERR OFFSET(12) NUMBITS(1) [],
115 OVR OFFSET(11) NUMBITS(1) [],
117 AF OFFSET(10) NUMBITS(1) [],
119 ARLO OFFSET(9) NUMBITS(1) [],
121 BERR OFFSET(8) NUMBITS(1) [],
123 TXE OFFSET(7) NUMBITS(1) [],
125 RXNE OFFSET(6) NUMBITS(1) [],
127 STOPF OFFSET(4) NUMBITS(1) [],
129 ADD10 OFFSET(3) NUMBITS(1) [],
131 BTF OFFSET(2) NUMBITS(1) [],
133 ADDR OFFSET(1) NUMBITS(1) [],
135 SB OFFSET(0) NUMBITS(1) []
137 ],
138 SR2 [
139 PEC OFFSET(8) NUMBITS(8) [],
141 DUALF OFFSET(7) NUMBITS(1) [],
143 SMBHOST OFFSET(6) NUMBITS(1) [],
145 SMBDEFAULT OFFSET(5) NUMBITS(1) [],
147 GENCALL OFFSET(4) NUMBITS(1) [],
149 TRA OFFSET(2) NUMBITS(1) [],
151 BUSY OFFSET(1) NUMBITS(1) [],
153 MSL OFFSET(0) NUMBITS(1) []
155 ],
156 CCR [
157 FS OFFSET(15) NUMBITS(1) [
159 SM_MODE = 0,
160 FM_MODE = 1
161 ],
162 DUTY OFFSET(14) NUMBITS(1) [],
164 CCR OFFSET(0) NUMBITS(12) []
166 ],
167 TRISE [
168 TRISE OFFSET(0) NUMBITS(6) []
170 ],
171 FLTR [
172 ANOFF OFFSET(4) NUMBITS(1) [],
174 DNF OFFSET(0) NUMBITS(4) []
176 ]
177];
178
179const I2C1_BASE: StaticRef<I2CRegisters> =
180 unsafe { StaticRef::new(0x4000_5400 as *const I2CRegisters) };
181pub struct I2C<'a> {
187 registers: StaticRef<I2CRegisters>,
188 clock: I2CClock<'a>,
189
190 master_client: OptionalCell<&'a dyn hil::i2c::I2CHwMasterClient>,
192
193 buffer: TakeCell<'static, [u8]>,
194 tx_position: Cell<usize>,
195 rx_position: Cell<usize>,
196 tx_len: Cell<usize>,
197 rx_len: Cell<usize>,
198
199 slave_address: Cell<u8>,
200
201 status: Cell<I2CStatus>,
202}
203
204#[derive(Copy, Clone, PartialEq)]
205enum I2CStatus {
206 Idle,
207 Writing,
208 WritingReading,
209 Reading,
210}
211
212impl<'a> I2C<'a> {
213 pub fn new(clocks: &'a dyn Stm32f4Clocks) -> Self {
214 Self {
215 registers: I2C1_BASE,
216 clock: I2CClock(phclk::PeripheralClock::new(
217 phclk::PeripheralClockType::APB1(phclk::PCLK1::I2C1),
218 clocks,
219 )),
220
221 master_client: OptionalCell::empty(),
222
223 slave_address: Cell::new(0),
224
225 buffer: TakeCell::empty(),
226 tx_position: Cell::new(0),
227 rx_position: Cell::new(0),
228
229 tx_len: Cell::new(0),
230 rx_len: Cell::new(0),
231
232 status: Cell::new(I2CStatus::Idle),
233 }
234 }
235
236 pub fn set_speed(&self, speed: I2CSpeed, system_clock_in_mhz: usize) {
237 self.disable();
238 self.registers
239 .cr2
240 .modify(CR2::FREQ.val(system_clock_in_mhz as u32));
241 match speed {
242 I2CSpeed::Speed100k => {
243 self.registers
244 .ccr
245 .modify(CCR::CCR.val(system_clock_in_mhz as u32 * 5) + CCR::FS::SM_MODE);
246 self.registers
247 .trise
248 .modify(TRISE::TRISE.val(system_clock_in_mhz as u32 + 1));
249 }
250 I2CSpeed::Speed400k => {
251 self.registers
252 .ccr
253 .modify(CCR::CCR.val(system_clock_in_mhz as u32 * 5 / 6) + CCR::FS::FM_MODE);
254 self.registers
255 .trise
256 .modify(TRISE::TRISE.val(system_clock_in_mhz as u32 + 1));
257 }
258 }
259 self.enable();
260 }
261
262 pub fn is_enabled_clock(&self) -> bool {
263 self.clock.is_enabled()
264 }
265
266 pub fn enable_clock(&self) {
267 self.clock.enable();
268 }
269
270 pub fn disable_clock(&self) {
271 self.clock.disable();
272 }
273
274 pub fn handle_event(&self) {
275 if self.registers.sr1.is_set(SR1::SB) {
276 let dir = match self.status.get() {
277 I2CStatus::Writing | I2CStatus::WritingReading => 0,
278 I2CStatus::Reading => 1,
279 _ => panic!("invalid i2c state when setting address"),
280 };
281 self.registers
282 .dr
283 .write(DR::DR.val(((self.slave_address.get() << 1) as u32) | dir));
284 }
285 if self.registers.sr1.is_set(SR1::ADDR) {
286 self.registers.sr2.get();
288 }
289 if self.registers.sr1.is_set(SR1::TXE) {
290 if self.buffer.is_some() && self.tx_position.get() < self.tx_len.get() {
292 self.buffer.map(|buf| {
293 let byte = buf[self.tx_position.get()];
294 self.registers.dr.write(DR::DR.val(byte as u32));
295 self.tx_position.set(self.tx_position.get() + 1);
296 });
297 }
298 }
299
300 while self.registers.sr1.is_set(SR1::RXNE) {
301 let byte = self.registers.dr.read(DR::DR);
303 if self.buffer.is_some() && self.rx_position.get() < self.rx_len.get() {
304 self.buffer.map(|buf| {
305 buf[self.rx_position.get()] = byte as u8;
306 self.rx_position.set(self.rx_position.get() + 1);
307 });
308 }
309
310 if self.buffer.is_some() && self.rx_position.get() == self.rx_len.get() {
311 self.registers.cr1.modify(CR1::STOP::SET);
312 self.stop();
313 self.master_client.map(|client| {
314 self.buffer
315 .take()
316 .map(|buf| client.command_complete(buf, Ok(())))
317 });
318 }
319 }
320
321 if self.registers.sr1.is_set(SR1::BTF) {
322 match self.status.get() {
323 I2CStatus::Writing | I2CStatus::WritingReading => {
324 if self.tx_position.get() < self.tx_len.get() {
325 self.registers.cr1.modify(CR1::STOP::SET);
326 self.stop();
327 self.master_client.map(|client| {
328 self.buffer
329 .take()
330 .map(|buf| client.command_complete(buf, Err(Error::DataNak)))
331 });
332 } else {
333 if self.status.get() == I2CStatus::Writing {
334 self.registers.cr1.modify(CR1::STOP::SET);
335 self.stop();
336 self.master_client.map(|client| {
337 self.buffer
338 .take()
339 .map(|buf| client.command_complete(buf, Ok(())))
340 });
341 } else {
342 self.status.set(I2CStatus::Reading);
343 self.start_read();
344 }
345 }
346 }
347 I2CStatus::Reading => {
348 let status = if self.rx_position.get() == self.rx_len.get() {
349 Ok(())
350 } else {
351 Err(Error::DataNak)
352 };
353 self.registers.cr1.modify(CR1::STOP::SET);
354 self.stop();
355 self.master_client.map(|client| {
356 self.buffer
357 .take()
358 .map(|buf| client.command_complete(buf, status))
359 });
360 }
361 _ => panic!("i2c status error"),
362 }
363 }
364 }
365
366 pub fn handle_error(&self) {
367 self.master_client.map(|client| {
368 self.buffer
369 .take()
370 .map(|buf| client.command_complete(buf, Err(Error::DataNak)))
371 });
372 self.stop();
373 }
374
375 fn reset(&self) {
376 self.disable();
377 self.enable();
378 }
379
380 fn start_write(&self) {
381 self.tx_position.set(0);
382 self.registers
383 .cr2
384 .modify(CR2::ITEVTEN::SET + CR2::ITERREN::SET + CR2::ITBUFEN::SET);
385 self.registers.cr1.modify(CR1::ACK::SET);
386 self.registers.cr1.modify(CR1::START::SET);
387 }
388
389 fn stop(&self) {
390 self.registers
391 .cr2
392 .modify(CR2::ITEVTEN::CLEAR + CR2::ITERREN::CLEAR + CR2::ITBUFEN::CLEAR);
393 self.registers.cr1.modify(CR1::ACK::CLEAR);
394 self.status.set(I2CStatus::Idle);
395 }
396
397 fn start_read(&self) {
398 self.rx_position.set(0);
399 self.registers
400 .cr2
401 .modify(CR2::ITEVTEN::SET + CR2::ITERREN::SET + CR2::ITBUFEN::SET);
402 self.registers.cr1.modify(CR1::ACK::SET);
403 self.registers.cr1.modify(CR1::START::SET);
404 }
405}
406
407impl<'a> i2c::I2CMaster<'a> for I2C<'a> {
408 fn set_master_client(&self, master_client: &'a dyn I2CHwMasterClient) {
409 self.master_client.replace(master_client);
410 }
411 fn enable(&self) {
412 self.registers.cr1.modify(CR1::PE::SET);
413 }
414 fn disable(&self) {
415 self.registers.cr1.modify(CR1::PE::CLEAR);
416 }
417 fn write_read(
418 &self,
419 addr: u8,
420 data: &'static mut [u8],
421 write_len: usize,
422 read_len: usize,
423 ) -> Result<(), (Error, &'static mut [u8])> {
424 if self.status.get() == I2CStatus::Idle {
425 self.reset();
426 self.status.set(I2CStatus::WritingReading);
427 self.slave_address.set(addr);
428 self.buffer.replace(data);
429 self.tx_len.set(write_len);
430 self.rx_len.set(read_len);
431 self.start_write();
432 Ok(())
433 } else {
434 Err((Error::Busy, data))
435 }
436 }
437 fn write(
438 &self,
439 addr: u8,
440 data: &'static mut [u8],
441 len: usize,
442 ) -> Result<(), (Error, &'static mut [u8])> {
443 if self.status.get() == I2CStatus::Idle {
444 self.reset();
445 self.status.set(I2CStatus::Writing);
446 self.slave_address.set(addr);
447 self.buffer.replace(data);
448 self.tx_len.set(len);
449 self.start_write();
450 Ok(())
451 } else {
452 Err((Error::Busy, data))
453 }
454 }
455 fn read(
456 &self,
457 addr: u8,
458 buffer: &'static mut [u8],
459 len: usize,
460 ) -> Result<(), (Error, &'static mut [u8])> {
461 if self.status.get() == I2CStatus::Idle {
462 self.reset();
463 self.status.set(I2CStatus::Reading);
464 self.slave_address.set(addr);
465 self.buffer.replace(buffer);
466 self.rx_len.set(len);
467 self.start_read();
468 Ok(())
469 } else {
470 Err((Error::ArbitrationLost, buffer))
471 }
472 }
473}
474
475struct I2CClock<'a>(phclk::PeripheralClock<'a>);
476
477impl ClockInterface for I2CClock<'_> {
478 fn is_enabled(&self) -> bool {
479 self.0.is_enabled()
480 }
481
482 fn enable(&self) {
483 self.0.enable();
484 }
485
486 fn disable(&self) {
487 self.0.disable();
488 }
489}