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}