1use crate::registers::i2c_regs::{
8    CTRL, FDATA, FIFO_CTRL, INTR, RDATA, STATUS, TIMING0, TIMING1, TIMING2, TIMING3, TIMING4,
9};
10use core::cell::Cell;
11use kernel::hil;
12use kernel::hil::i2c;
13use kernel::utilities::cells::OptionalCell;
14use kernel::utilities::cells::TakeCell;
15use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
16use kernel::utilities::StaticRef;
17
18pub use crate::registers::i2c_regs::I2cRegisters;
19
20pub struct I2c<'a> {
21    registers: StaticRef<I2cRegisters>,
22    clock_period_nanos: u32,
23
24    master_client: OptionalCell<&'a dyn hil::i2c::I2CHwMasterClient>,
25
26    slave_read_address: Cell<u8>,
30
31    buffer: TakeCell<'static, [u8]>,
32    write_len: Cell<usize>,
33    write_index: Cell<usize>,
34
35    read_len: Cell<usize>,
36    read_index: Cell<usize>,
37}
38
39impl<'a> I2c<'a> {
40    pub fn new(base: StaticRef<I2cRegisters>, clock_period_nanos: u32) -> I2c<'a> {
41        I2c {
42            registers: base,
43            clock_period_nanos,
44            master_client: OptionalCell::empty(),
45            slave_read_address: Cell::new(0),
46            buffer: TakeCell::empty(),
47            write_len: Cell::new(0),
48            write_index: Cell::new(0),
49            read_len: Cell::new(0),
50            read_index: Cell::new(0),
51        }
52    }
53
54    pub fn handle_interrupt(&self) {
55        let regs = self.registers;
56        let irqs = regs.intr_state.extract();
57
58        regs.intr_state.modify(
60            INTR::FMT_THRESHOLD::SET
61                + INTR::RX_THRESHOLD::SET
62                + INTR::FMT_OVERFLOW::SET
63                + INTR::RX_OVERFLOW::SET
64                + INTR::NAK::SET
65                + INTR::SCL_INTERFERENCE::SET
66                + INTR::SDA_INTERFERENCE::SET
67                + INTR::STRETCH_TIMEOUT::SET
68                + INTR::SDA_UNSTABLE::SET,
69        );
70
71        if irqs.is_set(INTR::FMT_THRESHOLD) {
72            if self.slave_read_address.get() != 0 {
74                self.write_read_data();
75            } else {
76                self.write_data();
77            }
78        }
79
80        if irqs.is_set(INTR::RX_THRESHOLD) {
81            self.read_data();
83        }
84    }
85
86    fn timing_parameter_init(&self, clock_period_nanos: u32) {
87        let regs = self.registers;
88
89        regs.timing0.modify(
91            TIMING0::THIGH.val(600 / clock_period_nanos)
92                + TIMING0::TLOW.val(1300 / clock_period_nanos),
93        );
94        regs.timing1
95            .modify(TIMING1::T_F.val(167) + TIMING1::T_R.val(40));
96        regs.timing2.modify(
97            TIMING2::THD_STA.val(600 / clock_period_nanos)
98                + TIMING2::TSU_STA.val(600 / clock_period_nanos),
99        );
100        regs.timing3
101            .modify(TIMING3::THD_DAT.val(100 / clock_period_nanos) + TIMING3::TSU_DAT.val(0));
102        regs.timing4.modify(
103            TIMING4::T_BUF.val(600 / clock_period_nanos)
104                + TIMING4::TSU_STO.val(1300 / clock_period_nanos),
105        );
106    }
107
108    fn fifo_reset(&self) {
109        let regs = self.registers;
110
111        regs.fifo_ctrl
112            .modify(FIFO_CTRL::RXRST::SET + FIFO_CTRL::FMTRST::SET);
113    }
114
115    fn read_data(&self) {
116        let regs = self.registers;
117        let mut data_popped = self.read_index.get();
118        let len = self.read_len.get();
119
120        self.buffer.map(|buf| {
121            for i in self.read_index.get()..len {
122                if regs.status.is_set(STATUS::RXEMPTY) {
123                    data_popped = i;
125                    break;
126                }
127                buf[i] = regs.rdata.read(RDATA::RDATA) as u8;
129                data_popped = i;
130            }
131
132            if data_popped == len {
133                self.master_client.map(|client| {
135                    client.command_complete(self.buffer.take().unwrap(), Ok(()));
136                });
137            } else {
138                self.read_index.set(data_popped + 1);
139
140                if len - data_popped > 8 {
142                    regs.fifo_ctrl.modify(FIFO_CTRL::RXILVL::RXLVL8);
143                } else if len - data_popped > 4 {
144                    regs.fifo_ctrl.modify(FIFO_CTRL::RXILVL::RXLVL4);
145                } else {
146                    regs.fifo_ctrl.modify(FIFO_CTRL::RXILVL::RXLVL1);
147                }
148            }
149        });
150    }
151
152    fn write_data(&self) {
153        let regs = self.registers;
154        let mut data_pushed = self.write_index.get();
155        let len = self.write_len.get();
156
157        self.buffer.map(|buf| {
158            for i in self.write_index.get()..(len - 1) {
159                if regs.status.read(STATUS::FMTFULL) != 0 {
160                    data_pushed = i;
162                    break;
163                }
164                regs.fdata
166                    .write(FDATA::FBYTE.val(*buf.get(i).unwrap_or(&0) as u32));
167                data_pushed = i;
168            }
169
170            if regs.status.read(STATUS::FMTFULL) == 0 && data_pushed == (len - 1) {
172                regs.fdata
174                    .write(FDATA::FBYTE.val(*buf.get(len).unwrap_or(&0) as u32) + FDATA::STOP::SET);
175
176                data_pushed = len;
177            }
178
179            if data_pushed == len {
180                self.master_client.map(|client| {
182                    client.command_complete(self.buffer.take().unwrap(), Ok(()));
183                });
184            } else {
185                self.write_index.set(data_pushed + 1);
186
187                if len - data_pushed > 8 {
189                    regs.fifo_ctrl.modify(FIFO_CTRL::FMTILVL::FMTLVL8);
190                } else if len - data_pushed > 4 {
191                    regs.fifo_ctrl.modify(FIFO_CTRL::FMTILVL::FMTLVL4);
192                } else {
193                    regs.fifo_ctrl.modify(FIFO_CTRL::FMTILVL::FMTLVL1);
194                }
195            }
196        });
197    }
198
199    fn write_read_data(&self) {
200        let regs = self.registers;
201        let mut data_pushed = self.write_index.get();
202        let len = self.write_len.get();
203
204        self.buffer.map(|buf| {
205            let start_index = data_pushed;
206            for i in start_index..(len - 1) {
207                if regs.status.read(STATUS::FMTFULL) != 0 {
208                    data_pushed = i;
210                    break;
211                }
212                regs.fdata
214                    .write(FDATA::FBYTE.val(*buf.get(i).unwrap_or(&0) as u32));
215                data_pushed = i;
216            }
217
218            if regs.status.read(STATUS::FMTFULL) == 0 && data_pushed == (len - 1) {
220                regs.fdata
222                    .write(FDATA::FBYTE.val(*buf.get(len).unwrap_or(&0) as u32) + FDATA::STOP::SET);
223
224                data_pushed = len;
225            }
226
227            if data_pushed == len {
228                let read_addr = self.slave_read_address.get() | 1;
231
232                regs.fdata
234                    .write(FDATA::START::SET + FDATA::FBYTE.val(read_addr as u32));
235
236                self.read_data();
237            } else {
238                self.write_index.set(data_pushed + 1);
239
240                if len - data_pushed > 8 {
242                    regs.fifo_ctrl.modify(FIFO_CTRL::FMTILVL::FMTLVL8);
243                } else if len - data_pushed > 4 {
244                    regs.fifo_ctrl.modify(FIFO_CTRL::FMTILVL::FMTLVL4);
245                } else {
246                    regs.fifo_ctrl.modify(FIFO_CTRL::FMTILVL::FMTLVL1);
247                }
248            }
249        });
250    }
251}
252
253impl<'a> hil::i2c::I2CMaster<'a> for I2c<'a> {
254    fn set_master_client(&self, master_client: &'a dyn i2c::I2CHwMasterClient) {
255        self.master_client.set(master_client);
256    }
257
258    fn enable(&self) {
259        let regs = self.registers;
260
261        self.timing_parameter_init(self.clock_period_nanos);
262        self.fifo_reset();
263
264        regs.intr_enable.modify(
266            INTR::FMT_THRESHOLD::SET
267                + INTR::RX_THRESHOLD::SET
268                + INTR::FMT_OVERFLOW::SET
269                + INTR::RX_OVERFLOW::SET
270                + INTR::NAK::SET
271                + INTR::SCL_INTERFERENCE::SET
272                + INTR::SDA_INTERFERENCE::SET
273                + INTR::STRETCH_TIMEOUT::SET
274                + INTR::SDA_UNSTABLE::SET,
275        );
276
277        regs.ctrl.modify(CTRL::ENABLEHOST::SET);
279    }
280
281    fn disable(&self) {
282        let regs = self.registers;
283
284        regs.ctrl.modify(CTRL::ENABLEHOST::CLEAR);
285    }
286
287    fn write_read(
288        &self,
289        addr: u8,
290        data: &'static mut [u8],
291        write_len: usize,
292        read_len: usize,
293    ) -> Result<(), (hil::i2c::Error, &'static mut [u8])> {
294        let regs = self.registers;
295
296        if write_len > 8 {
298            regs.fifo_ctrl.modify(FIFO_CTRL::FMTILVL::FMTLVL8);
299        } else if write_len > 4 {
300            regs.fifo_ctrl.modify(FIFO_CTRL::FMTILVL::FMTLVL4);
301        } else {
302            regs.fifo_ctrl.modify(FIFO_CTRL::FMTILVL::FMTLVL1);
303        }
304
305        if read_len > 8 {
306            regs.fifo_ctrl.modify(FIFO_CTRL::RXILVL::RXLVL8);
307        } else if read_len > 4 {
308            regs.fifo_ctrl.modify(FIFO_CTRL::RXILVL::RXLVL4);
309        } else {
310            regs.fifo_ctrl.modify(FIFO_CTRL::RXILVL::RXLVL1);
311        }
312
313        self.fifo_reset();
314
315        let write_addr = addr & !1;
317
318        regs.fdata
320            .write(FDATA::START::SET + FDATA::FBYTE.val(write_addr as u32));
321
322        self.slave_read_address.set(addr);
324        self.buffer.replace(data);
325        self.write_len.set(write_len);
326        self.read_len.set(read_len);
327        self.write_index.set(0);
328        self.read_index.set(0);
329
330        self.write_read_data();
331
332        Ok(())
333    }
334
335    fn write(
336        &self,
337        addr: u8,
338        data: &'static mut [u8],
339        len: usize,
340    ) -> Result<(), (hil::i2c::Error, &'static mut [u8])> {
341        let regs = self.registers;
342
343        if len > 8 {
345            regs.fifo_ctrl.modify(FIFO_CTRL::FMTILVL::FMTLVL8);
346        } else if len > 4 {
347            regs.fifo_ctrl.modify(FIFO_CTRL::FMTILVL::FMTLVL4);
348        } else {
349            regs.fifo_ctrl.modify(FIFO_CTRL::FMTILVL::FMTLVL1);
350        }
351
352        self.fifo_reset();
353
354        let write_addr = addr & !1;
356
357        regs.fdata
359            .write(FDATA::START::SET + FDATA::FBYTE.val(write_addr as u32));
360
361        self.slave_read_address.set(0);
363        self.buffer.replace(data);
364        self.write_len.set(len);
365        self.write_index.set(0);
366
367        self.write_data();
368
369        Ok(())
370    }
371
372    fn read(
373        &self,
374        addr: u8,
375        buffer: &'static mut [u8],
376        len: usize,
377    ) -> Result<(), (hil::i2c::Error, &'static mut [u8])> {
378        let regs = self.registers;
379
380        if len > 8 {
382            regs.fifo_ctrl.modify(FIFO_CTRL::RXILVL::RXLVL8);
383        } else if len > 4 {
384            regs.fifo_ctrl.modify(FIFO_CTRL::RXILVL::RXLVL4);
385        } else {
386            regs.fifo_ctrl.modify(FIFO_CTRL::RXILVL::RXLVL1);
387        }
388
389        self.fifo_reset();
390
391        let read_addr = addr | 1;
393
394        regs.fdata
396            .write(FDATA::START::SET + FDATA::FBYTE.val(read_addr as u32));
397
398        self.slave_read_address.set(0);
400        self.buffer.replace(buffer);
401        self.read_len.set(len);
402        self.read_index.set(0);
403
404        self.read_data();
405
406        Ok(())
407    }
408}