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}