1use crate::ios::i2c::SlaveTransmissionType;
36use core::cell::Cell;
37use kernel::debug;
38use kernel::hil::i2c::{self, Error, I2CHwSlaveClient, I2CSlave};
39use kernel::utilities::cells::OptionalCell;
40use kernel::utilities::cells::TakeCell;
41use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
42use kernel::utilities::registers::{register_bitfields, register_structs, ReadOnly, ReadWrite};
43use kernel::utilities::StaticRef;
44
45const SRAM_ROBASE_OFFSET: u32 = 0x78;
46
47const IOS_BASE: StaticRef<IosRegisters> =
48 unsafe { StaticRef::new(0x5000_0100 as *const IosRegisters) };
49
50register_structs! {
51 pub IosRegisters {
52 (0x000 => fifoptr: ReadWrite<u32, FIFOPTR::Register>),
53 (0x004 => fifocfg: ReadWrite<u32, FIFOCFG::Register>),
54 (0x008 => fifothr: ReadWrite<u32, FIFOTHR::Register>),
55 (0x00C => fupd: ReadWrite<u32, FUPD::Register>),
56 (0x010 => fifoctr: ReadWrite<u32, FIFOCTR::Register>),
57 (0x014 => fifoinc : ReadWrite<u32, FIFOINC::Register>),
58 (0x018 => cfg: ReadWrite<u32, CFG::Register>),
59 (0x01C => prenc: ReadWrite<u32, PRENC::Register>),
60 (0x020 => iointctl: ReadWrite<u32, IOINTCTL::Register>),
61 (0x024 => genadd: ReadOnly<u32, GENADD::Register>),
62 (0x028 => _reserved2),
63 (0x100 => inten: ReadWrite<u32, INT::Register>),
64 (0x104 => intstat: ReadWrite<u32, INT::Register>),
65 (0x108 => intclr: ReadWrite<u32, INT::Register>),
66 (0x10C => intset: ReadWrite<u32, INT::Register>),
67 (0x110 => regaccinten: ReadWrite<u32, REGACC::Register>),
68 (0x114 => regaccintstat: ReadWrite<u32, REGACC::Register>),
69 (0x118 => regaccintclr: ReadWrite<u32, REGACC::Register>),
70 (0x11C => regaccintset: ReadWrite<u32, REGACC::Register>),
71 (0x120 => @END),
72 }
73}
74
75register_bitfields![u32,
76 FIFOPTR [
77 FIFOPTR OFFSET(0) NUMBITS(8) [],
78 FIFOSIZ OFFSET(8) NUMBITS(8) []
79 ],
80 FIFOCFG [
81 FIFOBASE OFFSET(0) NUMBITS(5) [],
82 FIFOMAX OFFSET(8) NUMBITS(6) [],
83 ROBASE OFFSET(24) NUMBITS(6) [],
84 ],
85 FIFOTHR [
86 FIFOTHR OFFSET(8) NUMBITS(8) []
87 ],
88 FUPD [
89 FIFOUPD OFFSET(0) NUMBITS(1) [],
90 IOREAD OFFSET(1) NUMBITS(1) []
91 ],
92 FIFOCTR [
93 FIFOCTR OFFSET(0) NUMBITS(10) []
94 ],
95 FIFOINC [
96 FIFOINC OFFSET(0) NUMBITS(10) []
97 ],
98 CFG [
99 IFCSEL OFFSET(0) NUMBITS(1) [],
100 SPOL OFFSET(1) NUMBITS(1) [],
101 LSB OFFSET(2) NUMBITS(1) [],
102 STARTRD OFFSET(4) NUMBITS(1) [],
103 I2CADDR OFFSET(8) NUMBITS(11) [],
104 IFCEN OFFSET(31) NUMBITS(1) []
105 ],
106 PRENC [
107 PRENC OFFSET(0) NUMBITS(5) []
108 ],
109 IOINTCTL [
110 IOINTEN OFFSET(0) NUMBITS(8) [],
111 IOINT OFFSET(8) NUMBITS(8) [],
112 IOINTCLR OFFSET(16) NUMBITS(1) [],
113 IOINTSET OFFSET(24) NUMBITS(8) []
114 ],
115 GENADD [
116 GADATA OFFSET(0) NUMBITS(8) [],
117 ],
118 INT [
119 FSIZE OFFSET(0) NUMBITS(1) [],
120 FOVFL OFFSET(1) NUMBITS(1) [],
121 FUNDFL OFFSET(2) NUMBITS(1) [],
122 FRDERR OFFSET(3) NUMBITS(1) [],
123 GENAD OFFSET(4) NUMBITS(1) [],
124 IOINTW OFFSET(5) NUMBITS(1) [],
125 XCMPRF OFFSET(6) NUMBITS(1) [],
126 XCMPRR OFFSET(7) NUMBITS(1) [],
127 XCMPWF OFFSET(8) NUMBITS(1) [],
128 XCMPWR OFFSET(9) NUMBITS(1) []
129 ],
130 REGACC [
131 REGACC OFFSET(0) NUMBITS(32) []
132 ]
133];
134
135#[derive(Clone, Copy, PartialEq, Debug)]
136enum Operation {
137 None,
138 I2C,
139}
140
141pub struct Ios<'a> {
142 registers: StaticRef<IosRegisters>,
143
144 i2c_slave_client: OptionalCell<&'a dyn I2CHwSlaveClient>,
145
146 write_buf: TakeCell<'static, [u8]>,
147 write_len: Cell<usize>,
148 read_buf: TakeCell<'static, [u8]>,
149 read_len: Cell<usize>,
150 op: Cell<Operation>,
151}
152
153impl<'a> Ios<'a> {
154 pub fn new() -> Ios<'a> {
155 Ios {
156 registers: IOS_BASE,
157 i2c_slave_client: OptionalCell::empty(),
158 write_buf: TakeCell::empty(),
159 write_len: Cell::new(0),
160 read_buf: TakeCell::empty(),
161 read_len: Cell::new(0),
162 op: Cell::new(Operation::None),
163 }
164 }
165
166 fn i2c_interface_enable(&self) {
167 let regs = self.registers;
168
169 regs.cfg.modify(CFG::IFCEN::SET);
170 regs.cfg.modify(CFG::IFCSEL::CLEAR);
171 }
172
173 pub fn handle_interrupt(&self) {
174 let irqs = self.registers.intstat.extract();
175
176 self.registers.intclr.set(0xFFFF_FFFF);
178 self.registers.regaccintclr.set(0xFFFF_FFFF);
179 self.registers.inten.set(0xFFFF_FFFF);
181 self.registers.regaccinten.set(0xFFFF_FFFF);
182
183 let _offset = self.registers.fifoptr.read(FIFOPTR::FIFOPTR);
184
185 if irqs.is_set(INT::XCMPWR) {
186 let len = (SRAM_ROBASE_OFFSET as usize).min(self.write_len.get());
193
194 self.write_buf.take().map(|buf| {
195 buf[0] = 0x0F;
196
197 for i in 1..len {
198 unsafe {
199 buf[i] = *((0x5000_000F + (i as u32 - 1)) as *mut u8);
200 *((0x5000_000F + (i as u32 - 1)) as *mut u8) = 0x00;
202 }
203 }
204
205 self.i2c_slave_client.get().map(|client| {
206 client.command_complete(buf, len, SlaveTransmissionType::Write);
207 });
208 });
209 }
210
211 if irqs.is_set(INT::XCMPWF) {
212 debug!("Write to the FIFO area, which is not currently supported");
219 }
220 }
221}
222
223impl<'a> I2CSlave<'a> for Ios<'a> {
224 fn set_slave_client(&self, slave_client: &'a dyn i2c::I2CHwSlaveClient) {
225 self.i2c_slave_client.set(slave_client);
226 }
227
228 fn enable(&self) {
229 self.op.set(Operation::I2C);
230
231 self.registers
234 .fifocfg
235 .modify(FIFOCFG::ROBASE.val(SRAM_ROBASE_OFFSET / 8));
236
237 self.registers
240 .fifocfg
241 .modify(FIFOCFG::FIFOBASE.val(SRAM_ROBASE_OFFSET / 8));
242
243 self.registers
246 .fifocfg
247 .modify(FIFOCFG::FIFOMAX.val(0x100 / 8));
248
249 self.registers.fifoctr.modify(FIFOCTR::FIFOCTR.val(0x00));
251 self.registers.fifoptr.modify(FIFOPTR::FIFOSIZ.val(0x00));
252
253 self.registers.fifothr.modify(FIFOTHR::FIFOTHR.val(0x08));
255
256 self.i2c_interface_enable();
257
258 self.registers.intclr.set(0xFFFF_FFFF);
260
261 self.registers.fupd.modify(FUPD::FIFOUPD::SET);
263 self.registers.fifoptr.modify(FIFOPTR::FIFOPTR.val(0x80));
264 self.registers.fupd.modify(FUPD::FIFOUPD::CLEAR);
265 }
266
267 fn disable(&self) {
268 if self.op.get() == Operation::I2C {
269 self.registers.cfg.modify(CFG::IFCEN::CLEAR);
270
271 self.op.set(Operation::None);
272 }
273 }
274
275 fn set_address(&self, addr: u8) -> Result<(), Error> {
276 self.registers
277 .cfg
278 .modify(CFG::I2CADDR.val((addr as u32) << 1));
279
280 Ok(())
281 }
282
283 fn write_receive(
284 &self,
285 data: &'static mut [u8],
286 max_len: usize,
287 ) -> Result<(), (Error, &'static mut [u8])> {
288 self.write_len.set(max_len.min(data.len()));
289 self.write_buf.replace(data);
290
291 Ok(())
292 }
293
294 fn read_send(
295 &self,
296 data: &'static mut [u8],
297 max_len: usize,
298 ) -> Result<(), (Error, &'static mut [u8])> {
299 for (i, d) in data.iter().enumerate() {
300 unsafe {
301 *((0x5000_0000 + 0x7F + (i as u32)) as *mut u8) = *d;
302 }
303 }
304
305 self.read_len.set(max_len.min(data.len()));
306 self.read_buf.replace(data);
307
308 Ok(())
309 }
310
311 fn listen(&self) {
312 self.registers.inten.modify(
313 INT::FSIZE::SET
314 + INT::FOVFL::SET
315 + INT::FUNDFL::SET
316 + INT::FRDERR::SET
317 + INT::GENAD::SET
318 + INT::IOINTW::SET
319 + INT::XCMPRF::SET
320 + INT::XCMPRF::SET
321 + INT::XCMPWF::SET
322 + INT::XCMPWR::SET,
323 );
324 }
325}