1use crate::usci::{self, UsciBRegisters};
6use core::cell::Cell;
7use kernel::hil::i2c::{self, Error};
8use kernel::utilities::cells::{OptionalCell, TakeCell};
9use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
10use kernel::utilities::StaticRef;
11
12#[derive(Copy, Clone, PartialEq)]
13pub enum Speed {
14 K100, K375, }
17
18#[derive(Copy, Clone, PartialEq)]
19enum OperatingMode {
20 Unconfigured,
21 Disabled,
22 Idle,
23 Write,
24 Read,
25 WriteReadWrite,
26 WriteReadRead,
27}
28
29pub struct I2c<'a> {
30 registers: StaticRef<UsciBRegisters>,
31 mode: Cell<OperatingMode>,
32 read_len: Cell<usize>,
33 write_len: Cell<usize>,
34 buf_idx: Cell<usize>,
35 buffer: TakeCell<'static, [u8]>,
36 master_client: OptionalCell<&'a dyn i2c::I2CHwMasterClient>,
37}
38
39impl I2c<'_> {
40 pub fn new(registers: StaticRef<UsciBRegisters>) -> Self {
41 Self {
42 registers,
43 mode: Cell::new(OperatingMode::Unconfigured),
44 read_len: Cell::new(0),
45 write_len: Cell::new(0),
46 buf_idx: Cell::new(0),
47 buffer: TakeCell::empty(),
48 master_client: OptionalCell::empty(),
49 }
50 }
51
52 fn set_module_to_reset(&self) {
53 self.registers.ctlw0.modify(usci::UCBxCTLW0::UCSWRST::SET);
55 }
56
57 fn clear_module_reset(&self) {
58 self.registers.ctlw0.modify(usci::UCBxCTLW0::UCSWRST::CLEAR);
60
61 self.enable_interrupts();
63 }
64
65 fn set_slave_address(&self, addr: u8) {
66 self.registers.i2csa.set(addr as u16);
67 }
68
69 fn generate_start_condition(&self) {
70 self.registers
71 .ctlw0
72 .modify(usci::UCBxCTLW0::UCTXSTT::GenerateSTARTCondition);
73 }
74
75 fn generate_stop_condition(&self) {
76 self.registers
77 .ctlw0
78 .modify(usci::UCBxCTLW0::UCTXSTP::GenerateSTOP);
79 }
80
81 fn set_stop_condition_automatically(&self, val: bool) {
82 if val {
83 self.registers
84 .ctlw1
85 .modify(usci::UCBxCTLW1::UCASTP::ByteCounterStopCondition)
86 } else {
87 self.registers.ctlw1.modify(usci::UCBxCTLW1::UCASTP::Manual);
88 }
89 }
90
91 fn enable_interrupts(&self) {
92 self.registers.ie.modify(
100 usci::UCBxIE::UCNACKIE::SET
101 + usci::UCBxIE::UCRXIE0::SET
102 + usci::UCBxIE::UCSTPIE::SET
103 + usci::UCBxIE::UCSTTIE::SET
104 + usci::UCBxIE::UCALIE::SET,
105 );
106 }
107
108 fn enable_transmit_mode(&self) {
109 self.registers
110 .ctlw0
111 .modify(usci::UCBxCTLW0::UCTR::Transmitter);
112 }
113
114 fn enable_receive_mode(&self) {
115 self.registers.ctlw0.modify(usci::UCBxCTLW0::UCTR::Receiver);
116 }
117
118 fn enable_transmit_interrupt(&self) {
119 self.registers.ie.modify(usci::UCBxIE::UCTXIE0::SET);
120 }
121
122 fn disable_transmit_interrupt(&self) {
123 self.registers.ie.modify(usci::UCBxIE::UCTXIE0::CLEAR);
124 }
125
126 fn set_byte_counter(&self, val: usize) {
127 self.registers.tbcnt.set(val as u16);
128 }
129
130 fn invoke_callback(&self, status: Result<(), Error>) {
131 self.buf_idx.set(0);
133 self.mode.set(OperatingMode::Idle);
134
135 self.buffer.take().map(|buf| {
136 self.master_client
137 .map(move |cl| cl.command_complete(buf, status))
138 });
139 }
140
141 fn setup(&self) {
142 self.set_module_to_reset();
143
144 self.registers.ctlw0.modify(
151 usci::UCBxCTLW0::UCSLA10::AddressSlaveWith7BitAddress
152 + usci::UCBxCTLW0::UCMST::MasterMode
153 + usci::UCBxCTLW0::UCMM::SingleMasterEnvironment
154 + usci::UCBxCTLW0::UCMODE::I2CMode
155 + usci::UCBxCTLW0::UCSYNC::SynchronousMode
156 + usci::UCBxCTLW0::UCSSEL::SMCLK,
157 );
158
159 self.registers.ctlw1.modify(
164 usci::UCBxCTLW1::UCCLTO::CLEAR
165 + usci::UCBxCTLW1::UCSTPNACK::NackBeforeStop
166 + usci::UCBxCTLW1::UCSWACK::HardwareTriggered
167 + usci::UCBxCTLW1::UCGLIT::_50ns,
168 );
169
170 self.mode.set(OperatingMode::Disabled);
172 }
173
174 pub fn set_speed(&self, speed: Speed) {
175 self.set_module_to_reset();
176
177 if speed == Speed::K100 {
181 self.registers.brw.set(15);
182 } else if speed == Speed::K375 {
183 self.registers.brw.set(4);
184 }
185
186 self.clear_module_reset();
187 }
188
189 pub fn handle_interrupt(&self) {
190 let ifg = self.registers.ifg.get();
191 let mode = self.mode.get();
192 let idx = self.buf_idx.get();
193
194 self.registers.ifg.set(0);
196
197 if (ifg & (1 << usci::UCBxIFG::UCTXIFG0.shift)) > 0 {
198 if idx < self.write_len.get() {
200 self.buffer
202 .map(|buf| self.registers.txbuf.set(buf[idx] as u16));
203 self.buf_idx.set(idx + 1);
204 } else {
205 self.disable_transmit_interrupt();
206 if mode == OperatingMode::WriteReadWrite {
207 self.mode.set(OperatingMode::WriteReadRead);
209 self.buf_idx.set(0);
210
211 self.enable_receive_mode();
213 self.generate_start_condition();
214 if self.read_len.get() == 1 {
215 self.generate_stop_condition();
219 }
220 }
221 }
222 } else if (ifg & (1 << usci::UCBxIFG::UCRXIFG0.shift)) > 0 {
223 if idx < self.read_len.get() {
225 if idx == (self.read_len.get() - 1) && mode == OperatingMode::WriteReadRead {
226 self.generate_stop_condition();
230 }
231 self.buffer
233 .map(|buf| buf[idx] = self.registers.rxbuf.get() as u8);
234 self.buf_idx.set(idx + 1);
235 } else if mode == OperatingMode::WriteReadRead {
236 self.invoke_callback(Ok(()));
240 }
241 } else if (ifg & (1 << usci::UCBxIFG::UCSTTIFG.shift)) > 0 {
242 if mode == OperatingMode::Write || mode == OperatingMode::WriteReadWrite {
244 self.buffer
245 .map(|buf| self.registers.txbuf.set(buf[idx] as u16));
246 self.buf_idx.set(idx + 1);
247 }
248 } else if (ifg & (1 << usci::UCBxIFG::UCSTPIFG.shift)) > 0 {
249 self.invoke_callback(Ok(()));
254 } else if (ifg & (1 << usci::UCBxIFG::UCNACKIFG.shift)) > 0 {
255 self.generate_stop_condition();
260 self.invoke_callback(Err(Error::DataNak));
261 } else if (ifg & (1 << usci::UCBxIFG::UCALIFG.shift)) > 0 {
262 self.generate_stop_condition();
266 self.invoke_callback(Err(Error::Busy));
267 } else {
268 panic!("I2C: unhandled interrupt, ifg: {}", ifg);
269 }
270 }
271}
272
273impl<'a> i2c::I2CMaster<'a> for I2c<'a> {
274 fn set_master_client(&self, master_client: &'a dyn i2c::I2CHwMasterClient) {
275 self.master_client.replace(master_client);
276 }
277
278 fn enable(&self) {
279 if self.mode.get() == OperatingMode::Unconfigured {
280 self.setup();
281 }
282
283 self.clear_module_reset();
284 self.mode.set(OperatingMode::Idle);
285 }
286
287 fn disable(&self) {
288 self.set_module_to_reset();
289 self.mode.set(OperatingMode::Disabled);
290 }
291
292 fn write(
293 &self,
294 addr: u8,
295 data: &'static mut [u8],
296 len: usize,
297 ) -> Result<(), (Error, &'static mut [u8])> {
298 if self.mode.get() != OperatingMode::Idle {
299 return Err((Error::Busy, data));
301 }
302
303 self.buffer.replace(data);
304 self.write_len.set(len);
305
306 self.set_module_to_reset();
308
309 self.set_byte_counter(len);
312
313 self.set_stop_condition_automatically(true);
316 self.clear_module_reset();
317
318 self.set_slave_address(addr);
319 self.enable_transmit_mode();
320 self.enable_transmit_interrupt();
321
322 self.mode.set(OperatingMode::Write);
323
324 self.generate_start_condition();
326
327 Ok(())
328 }
329
330 fn read(
331 &self,
332 addr: u8,
333 buffer: &'static mut [u8],
334 len: usize,
335 ) -> Result<(), (Error, &'static mut [u8])> {
336 if self.mode.get() != OperatingMode::Idle {
337 return Err((Error::Busy, buffer));
339 }
340
341 self.buffer.replace(buffer);
342 self.read_len.set(len);
343
344 self.set_module_to_reset();
346
347 self.set_byte_counter(len);
350
351 self.set_stop_condition_automatically(true);
354 self.clear_module_reset();
355
356 self.set_slave_address(addr);
357 self.enable_receive_mode();
358 self.mode.set(OperatingMode::Read);
359
360 self.generate_start_condition();
362 Ok(())
363 }
364
365 fn write_read(
366 &self,
367 addr: u8,
368 data: &'static mut [u8],
369 write_len: usize,
370 read_len: usize,
371 ) -> Result<(), (Error, &'static mut [u8])> {
372 if self.mode.get() != OperatingMode::Idle {
373 return Err((Error::Busy, data));
375 }
376
377 self.buffer.replace(data);
378 self.write_len.set(write_len);
379 self.read_len.set(read_len);
380
381 self.set_module_to_reset();
383
384 self.set_stop_condition_automatically(false);
387 self.clear_module_reset();
388
389 self.set_slave_address(addr);
390 self.enable_transmit_mode();
391 self.enable_transmit_interrupt();
392 self.mode.set(OperatingMode::WriteReadWrite);
393
394 self.generate_start_condition();
396
397 Ok(())
398 }
399}