1use core::cell::Cell;
11
12use kernel::collections::list::{List, ListLink, ListNode};
13use kernel::deferred_call::{DeferredCall, DeferredCallClient};
14use kernel::hil::i2c::{self, Error, I2CClient, I2CHwMasterClient, NoSMBus};
15use kernel::utilities::cells::{OptionalCell, TakeCell};
16pub struct MuxI2C<'a, I: i2c::I2CMaster<'a>, S: i2c::SMBusMaster<'a> = NoSMBus> {
18 i2c: &'a I,
19 smbus: Option<&'a S>,
20 i2c_devices: List<'a, I2CDevice<'a, I, S>>,
21 smbus_devices: List<'a, SMBusDevice<'a, I, S>>,
22 enabled: Cell<usize>,
23 i2c_inflight: OptionalCell<&'a I2CDevice<'a, I, S>>,
24 smbus_inflight: OptionalCell<&'a SMBusDevice<'a, I, S>>,
25 deferred_call: DeferredCall,
26}
27
28impl<'a, I: i2c::I2CMaster<'a>, S: i2c::SMBusMaster<'a>> I2CHwMasterClient for MuxI2C<'a, I, S> {
29 fn command_complete(&self, buffer: &'static mut [u8], status: Result<(), Error>) {
30 if self.i2c_inflight.is_some() {
31 self.i2c_inflight.take().map(move |device| {
32 device.command_complete(buffer, status);
33 });
34 } else if self.smbus_inflight.is_some() {
35 self.smbus_inflight.take().map(move |device| {
36 device.command_complete(buffer, status);
37 });
38 }
39 self.do_next_op();
40 }
41}
42
43impl<'a, I: i2c::I2CMaster<'a>, S: i2c::SMBusMaster<'a>> MuxI2C<'a, I, S> {
44 pub fn new(i2c: &'a I, smbus: Option<&'a S>) -> Self {
45 Self {
46 i2c,
47 smbus,
48 i2c_devices: List::new(),
49 smbus_devices: List::new(),
50 enabled: Cell::new(0),
51 i2c_inflight: OptionalCell::empty(),
52 smbus_inflight: OptionalCell::empty(),
53 deferred_call: DeferredCall::new(),
54 }
55 }
56
57 fn enable(&self) {
58 let enabled = self.enabled.get();
59 self.enabled.set(enabled + 1);
60 if enabled == 0 {
61 self.i2c.enable();
62 }
63 }
64
65 fn disable(&self) {
66 let enabled = self.enabled.get();
67 self.enabled.set(enabled - 1);
68 if enabled == 1 {
69 self.i2c.disable();
70 }
71 }
72
73 fn do_next_op(&self) {
74 if self.i2c_inflight.is_none() && self.smbus_inflight.is_none() {
75 let mnode = self
79 .i2c_devices
80 .iter()
81 .find(|node| node.operation.get() != Op::Idle);
82 mnode.map(|node| {
83 node.buffer.take().map(|buf| {
84 match node.operation.get() {
85 Op::Write(len) => match self.i2c.write(node.addr, buf, len) {
86 Ok(()) => {}
87 Err((error, buffer)) => {
88 node.buffer.replace(buffer);
89 node.operation.set(Op::CommandComplete(Err(error)));
90 node.mux.do_next_op_async();
91 }
92 },
93 Op::Read(len) => match self.i2c.read(node.addr, buf, len) {
94 Ok(()) => {}
95 Err((error, buffer)) => {
96 node.buffer.replace(buffer);
97 node.operation.set(Op::CommandComplete(Err(error)));
98 node.mux.do_next_op_async();
99 }
100 },
101 Op::WriteRead(wlen, rlen) => {
102 match self.i2c.write_read(node.addr, buf, wlen, rlen) {
103 Ok(()) => {}
104 Err((error, buffer)) => {
105 node.buffer.replace(buffer);
106 node.operation.set(Op::CommandComplete(Err(error)));
107 node.mux.do_next_op_async();
108 }
109 }
110 }
111 Op::CommandComplete(err) => {
112 self.command_complete(buf, err);
113 }
114 Op::Idle => {} }
116 });
117 node.operation.set(Op::Idle);
118 self.i2c_inflight.set(node);
119 });
120
121 if self.i2c_inflight.is_none() && self.smbus.is_some() {
122 let mnode = self
124 .smbus_devices
125 .iter()
126 .find(|node| node.operation.get() != Op::Idle);
127 mnode.map(|node| {
128 node.buffer.take().map(|buf| match node.operation.get() {
129 Op::Write(len) => {
130 match self.smbus.unwrap().smbus_write(node.addr, buf, len) {
131 Ok(()) => {}
132 Err(e) => {
133 node.buffer.replace(e.1);
134 node.operation.set(Op::CommandComplete(Err(e.0)));
135 node.mux.do_next_op_async();
136 }
137 }
138 }
139 Op::Read(len) => {
140 match self.smbus.unwrap().smbus_read(node.addr, buf, len) {
141 Ok(()) => {}
142 Err(e) => {
143 node.buffer.replace(e.1);
144 node.operation.set(Op::CommandComplete(Err(e.0)));
145 node.mux.do_next_op_async();
146 }
147 }
148 }
149 Op::WriteRead(wlen, rlen) => {
150 match self
151 .smbus
152 .unwrap()
153 .smbus_write_read(node.addr, buf, wlen, rlen)
154 {
155 Ok(()) => {}
156 Err(e) => {
157 node.buffer.replace(e.1);
158 node.operation.set(Op::CommandComplete(Err(e.0)));
159 node.mux.do_next_op_async();
160 }
161 }
162 }
163 Op::CommandComplete(err) => {
164 self.command_complete(buf, err);
165 }
166 Op::Idle => unreachable!(),
167 });
168 node.operation.set(Op::Idle);
169 self.smbus_inflight.set(node);
170 });
171 }
172 }
173 }
174
175 fn do_next_op_async(&self) {
183 self.deferred_call.set();
184 }
185}
186
187impl<'a, I: i2c::I2CMaster<'a>, S: i2c::SMBusMaster<'a>> DeferredCallClient for MuxI2C<'a, I, S> {
188 fn handle_deferred_call(&self) {
189 self.do_next_op();
190 }
191
192 fn register(&'static self) {
193 self.deferred_call.register(self);
194 }
195}
196
197#[derive(Copy, Clone, PartialEq)]
198enum Op {
199 Idle,
200 Write(usize),
201 Read(usize),
202 WriteRead(usize, usize),
203 CommandComplete(Result<(), Error>),
204}
205
206pub struct I2CDevice<'a, I: i2c::I2CMaster<'a>, S: i2c::SMBusMaster<'a> = NoSMBus> {
207 mux: &'a MuxI2C<'a, I, S>,
208 addr: u8,
209 enabled: Cell<bool>,
210 buffer: TakeCell<'static, [u8]>,
211 operation: Cell<Op>,
212 next: ListLink<'a, I2CDevice<'a, I, S>>,
213 client: OptionalCell<&'a dyn I2CClient>,
214}
215
216impl<'a, I: i2c::I2CMaster<'a>, S: i2c::SMBusMaster<'a>> I2CDevice<'a, I, S> {
217 pub fn new(mux: &'a MuxI2C<'a, I, S>, addr: u8) -> I2CDevice<'a, I, S> {
218 I2CDevice {
219 mux,
220 addr,
221 enabled: Cell::new(false),
222 buffer: TakeCell::empty(),
223 operation: Cell::new(Op::Idle),
224 next: ListLink::empty(),
225 client: OptionalCell::empty(),
226 }
227 }
228
229 pub fn set_client(&'a self, client: &'a dyn I2CClient) {
230 self.mux.i2c_devices.push_head(self);
231 self.client.set(client);
232 }
233}
234
235impl<'a, I: i2c::I2CMaster<'a>, S: i2c::SMBusMaster<'a>> I2CClient for I2CDevice<'a, I, S> {
236 fn command_complete(&self, buffer: &'static mut [u8], status: Result<(), Error>) {
237 self.client.map(move |client| {
238 client.command_complete(buffer, status);
239 });
240 }
241}
242
243impl<'a, I: i2c::I2CMaster<'a>, S: i2c::SMBusMaster<'a>> ListNode<'a, I2CDevice<'a, I, S>>
244 for I2CDevice<'a, I, S>
245{
246 fn next(&'a self) -> &'a ListLink<'a, I2CDevice<'a, I, S>> {
247 &self.next
248 }
249}
250
251impl<'a, I: i2c::I2CMaster<'a>> i2c::I2CDevice for I2CDevice<'a, I> {
252 fn enable(&self) {
253 if !self.enabled.get() {
254 self.enabled.set(true);
255 self.mux.enable();
256 }
257 }
258
259 fn disable(&self) {
260 if self.enabled.get() {
261 self.enabled.set(false);
262 self.mux.disable();
263 }
264 }
265
266 fn write_read(
267 &self,
268 data: &'static mut [u8],
269 write_len: usize,
270 read_len: usize,
271 ) -> Result<(), (Error, &'static mut [u8])> {
272 if self.operation.get() == Op::Idle {
273 self.buffer.replace(data);
274 self.operation.set(Op::WriteRead(write_len, read_len));
275 self.mux.do_next_op();
276 Ok(())
277 } else {
278 Err((Error::ArbitrationLost, data))
279 }
280 }
281
282 fn write(&self, data: &'static mut [u8], len: usize) -> Result<(), (Error, &'static mut [u8])> {
283 if self.operation.get() == Op::Idle {
284 self.buffer.replace(data);
285 self.operation.set(Op::Write(len));
286 self.mux.do_next_op();
287 Ok(())
288 } else {
289 Err((Error::ArbitrationLost, data))
290 }
291 }
292
293 fn read(
294 &self,
295 buffer: &'static mut [u8],
296 len: usize,
297 ) -> Result<(), (Error, &'static mut [u8])> {
298 if self.operation.get() == Op::Idle {
299 self.buffer.replace(buffer);
300 self.operation.set(Op::Read(len));
301 self.mux.do_next_op();
302 Ok(())
303 } else {
304 Err((Error::ArbitrationLost, buffer))
305 }
306 }
307}
308
309pub struct SMBusDevice<'a, I: i2c::I2CMaster<'a>, S: i2c::SMBusMaster<'a>> {
310 mux: &'a MuxI2C<'a, I, S>,
311 addr: u8,
312 enabled: Cell<bool>,
313 buffer: TakeCell<'static, [u8]>,
314 operation: Cell<Op>,
315 next: ListLink<'a, SMBusDevice<'a, I, S>>,
316 client: OptionalCell<&'a dyn I2CClient>,
317}
318
319impl<'a, I: i2c::I2CMaster<'a>, S: i2c::SMBusMaster<'a>> SMBusDevice<'a, I, S> {
320 pub fn new(mux: &'a MuxI2C<'a, I, S>, addr: u8) -> SMBusDevice<'a, I, S> {
321 if mux.smbus.is_none() {
322 panic!("There is no SMBus to attach to");
323 }
324
325 SMBusDevice {
326 mux,
327 addr,
328 enabled: Cell::new(false),
329 buffer: TakeCell::empty(),
330 operation: Cell::new(Op::Idle),
331 next: ListLink::empty(),
332 client: OptionalCell::empty(),
333 }
334 }
335
336 pub fn set_client(&'a self, client: &'a dyn I2CClient) {
337 self.mux.smbus_devices.push_head(self);
338 self.client.set(client);
339 }
340}
341
342impl<'a, I: i2c::I2CMaster<'a>, S: i2c::SMBusMaster<'a>> I2CClient for SMBusDevice<'a, I, S> {
343 fn command_complete(&self, buffer: &'static mut [u8], status: Result<(), Error>) {
344 self.client.map(move |client| {
345 client.command_complete(buffer, status);
346 });
347 }
348}
349
350impl<'a, I: i2c::I2CMaster<'a>, S: i2c::SMBusMaster<'a>> ListNode<'a, SMBusDevice<'a, I, S>>
351 for SMBusDevice<'a, I, S>
352{
353 fn next(&'a self) -> &'a ListLink<'a, SMBusDevice<'a, I, S>> {
354 &self.next
355 }
356}
357
358impl<'a, I: i2c::I2CMaster<'a>, S: i2c::SMBusMaster<'a>> i2c::I2CDevice for SMBusDevice<'a, I, S> {
359 fn enable(&self) {
360 if !self.enabled.get() {
361 self.enabled.set(true);
362 self.mux.enable();
363 }
364 }
365
366 fn disable(&self) {
367 if self.enabled.get() {
368 self.enabled.set(false);
369 self.mux.disable();
370 }
371 }
372
373 fn write_read(
374 &self,
375 data: &'static mut [u8],
376 write_len: usize,
377 read_len: usize,
378 ) -> Result<(), (Error, &'static mut [u8])> {
379 if self.operation.get() == Op::Idle {
380 self.buffer.replace(data);
381 self.operation.set(Op::WriteRead(write_len, read_len));
382 self.mux.do_next_op();
383 Ok(())
384 } else {
385 Err((Error::ArbitrationLost, data))
386 }
387 }
388
389 fn write(&self, data: &'static mut [u8], len: usize) -> Result<(), (Error, &'static mut [u8])> {
390 if self.operation.get() == Op::Idle {
391 self.buffer.replace(data);
392 self.operation.set(Op::Write(len));
393 self.mux.do_next_op();
394 Ok(())
395 } else {
396 Err((Error::ArbitrationLost, data))
397 }
398 }
399
400 fn read(
401 &self,
402 buffer: &'static mut [u8],
403 len: usize,
404 ) -> Result<(), (Error, &'static mut [u8])> {
405 if self.operation.get() == Op::Idle {
406 self.buffer.replace(buffer);
407 self.operation.set(Op::Read(len));
408 self.mux.do_next_op();
409 Ok(())
410 } else {
411 Err((Error::ArbitrationLost, buffer))
412 }
413 }
414}
415
416impl<'a, I: i2c::I2CMaster<'a>, S: i2c::SMBusMaster<'a>> i2c::SMBusDevice
417 for SMBusDevice<'a, I, S>
418{
419 fn smbus_write_read(
420 &self,
421 data: &'static mut [u8],
422 write_len: usize,
423 read_len: usize,
424 ) -> Result<(), (Error, &'static mut [u8])> {
425 if self.operation.get() == Op::Idle {
426 self.buffer.replace(data);
427 self.operation.set(Op::WriteRead(write_len, read_len));
428 self.mux.do_next_op();
429 Ok(())
430 } else {
431 Err((Error::ArbitrationLost, data))
432 }
433 }
434
435 fn smbus_write(
436 &self,
437 data: &'static mut [u8],
438 len: usize,
439 ) -> Result<(), (Error, &'static mut [u8])> {
440 if self.operation.get() == Op::Idle {
441 self.buffer.replace(data);
442 self.operation.set(Op::Write(len));
443 self.mux.do_next_op();
444 Ok(())
445 } else {
446 Err((Error::ArbitrationLost, data))
447 }
448 }
449
450 fn smbus_read(
451 &self,
452 buffer: &'static mut [u8],
453 len: usize,
454 ) -> Result<(), (Error, &'static mut [u8])> {
455 if self.operation.get() == Op::Idle {
456 self.buffer.replace(buffer);
457 self.operation.set(Op::Read(len));
458 self.mux.do_next_op();
459 Ok(())
460 } else {
461 Err((Error::ArbitrationLost, buffer))
462 }
463 }
464}