2 * TI OMAP on-chip I2C controller. Only "new I2C" mode supported.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
26 target_phys_addr_t base;
47 static void omap_i2c_interrupts_update(struct omap_i2c_s *s)
49 qemu_set_irq(s->irq, s->stat & s->mask);
50 if ((s->dma >> 15) & 1) /* RDMA_EN */
51 qemu_set_irq(s->drq[0], (s->stat >> 3) & 1); /* RRDY */
52 if ((s->dma >> 7) & 1) /* XDMA_EN */
53 qemu_set_irq(s->drq[1], (s->stat >> 4) & 1); /* XRDY */
56 /* These are only stubs now. */
57 static void omap_i2c_event(i2c_slave *i2c, enum i2c_event event)
59 struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
61 if ((~s->control >> 15) & 1) /* I2C_EN */
67 s->stat |= 1 << 9; /* AAS */
70 s->stat |= 1 << 2; /* ARDY */
73 s->stat |= 1 << 1; /* NACK */
77 omap_i2c_interrupts_update(s);
80 static int omap_i2c_rx(i2c_slave *i2c)
82 struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
85 if ((~s->control >> 15) & 1) /* I2C_EN */
89 ret = s->fifo >> ((-- s->txlen) << 3) & 0xff;
91 s->stat |= 1 << 10; /* XUDF */
92 s->stat |= 1 << 4; /* XRDY */
94 omap_i2c_interrupts_update(s);
98 static int omap_i2c_tx(i2c_slave *i2c, uint8_t data)
100 struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
102 if ((~s->control >> 15) & 1) /* I2C_EN */
106 s->fifo |= data << ((s->rxlen ++) << 3);
108 s->stat |= 1 << 11; /* ROVR */
109 s->stat |= 1 << 3; /* RRDY */
111 omap_i2c_interrupts_update(s);
115 static void omap_i2c_fifo_run(struct omap_i2c_s *s)
119 if (!i2c_bus_busy(s->bus))
122 if ((s->control >> 2) & 1) { /* RM */
123 if ((s->control >> 1) & 1) { /* STP */
124 i2c_end_transfer(s->bus);
125 s->control &= ~(1 << 1); /* STP */
126 s->count_cur = s->count;
127 } else if ((s->control >> 9) & 1) { /* TRX */
128 while (ack && s->txlen)
129 ack = (i2c_send(s->bus,
130 (s->fifo >> ((-- s->txlen) << 3)) &
132 s->stat |= 1 << 4; /* XRDY */
135 s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
136 s->stat |= 1 << 3; /* RRDY */
139 if ((s->control >> 9) & 1) { /* TRX */
140 while (ack && s->count_cur && s->txlen) {
141 ack = (i2c_send(s->bus,
142 (s->fifo >> ((-- s->txlen) << 3)) &
146 if (ack && s->count_cur)
147 s->stat |= 1 << 4; /* XRDY */
149 s->stat |= 1 << 2; /* ARDY */
150 s->control &= ~(1 << 10); /* MST */
153 while (s->count_cur && s->rxlen < 4) {
154 s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
158 s->stat |= 1 << 3; /* RRDY */
161 if ((s->control >> 1) & 1) { /* STP */
162 i2c_end_transfer(s->bus);
163 s->control &= ~(1 << 1); /* STP */
164 s->count_cur = s->count;
166 s->stat |= 1 << 2; /* ARDY */
167 s->control &= ~(1 << 10); /* MST */
172 s->stat |= (!ack) << 1; /* NACK */
174 s->control &= ~(1 << 1); /* STP */
177 void omap_i2c_reset(struct omap_i2c_s *s)
196 static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr)
198 struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
199 int offset = addr & OMAP_MPUI_REG_MASK;
203 case 0x00: /* I2C_REV */
204 /* TODO: set a value greater or equal to real hardware */
205 return 0x11; /* REV */
207 case 0x04: /* I2C_IE */
210 case 0x08: /* I2C_STAT */
211 return s->stat | (i2c_bus_busy(s->bus) << 12);
213 case 0x0c: /* I2C_IV */
214 ret = ffs(s->stat & s->mask);
216 s->stat ^= 1 << (ret - 1);
217 omap_i2c_interrupts_update(s);
220 case 0x14: /* I2C_BUF */
223 case 0x18: /* I2C_CNT */
224 return s->count_cur; /* DCOUNT */
226 case 0x1c: /* I2C_DATA */
228 if (s->control & (1 << 14)) { /* BE */
229 ret |= ((s->fifo >> 0) & 0xff) << 8;
230 ret |= ((s->fifo >> 8) & 0xff) << 0;
232 ret |= ((s->fifo >> 8) & 0xff) << 8;
233 ret |= ((s->fifo >> 0) & 0xff) << 0;
236 s->stat |= 1 << 15; /* SBD */
238 } else if (s->rxlen > 1) {
243 /* XXX: remote access (qualifier) error - what's that? */;
245 s->stat |= ~(1 << 3); /* RRDY */
246 if (((s->control >> 10) & 1) && /* MST */
247 ((~s->control >> 9) & 1)) { /* TRX */
248 s->stat |= 1 << 2; /* ARDY */
249 s->control &= ~(1 << 10); /* MST */
252 s->stat &= ~(1 << 11); /* ROVR */
253 omap_i2c_fifo_run(s);
254 omap_i2c_interrupts_update(s);
257 case 0x24: /* I2C_CON */
260 case 0x28: /* I2C_OA */
263 case 0x2c: /* I2C_SA */
266 case 0x30: /* I2C_PSC */
269 case 0x34: /* I2C_SCLL */
272 case 0x38: /* I2C_SCLH */
275 case 0x3c: /* I2C_SYSTEST */
276 if (s->test & (1 << 15)) { /* ST_EN */
280 return s->test & ~0x300f;
287 static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
290 struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
291 int offset = addr & OMAP_MPUI_REG_MASK;
295 case 0x00: /* I2C_REV */
296 case 0x08: /* I2C_STAT */
297 case 0x0c: /* I2C_IV */
301 case 0x04: /* I2C_IE */
302 s->mask = value & 0x1f;
305 case 0x14: /* I2C_BUF */
306 s->dma = value & 0x8080;
307 if (value & (1 << 15)) /* RDMA_EN */
308 s->mask &= ~(1 << 3); /* RRDY_IE */
309 if (value & (1 << 7)) /* XDMA_EN */
310 s->mask &= ~(1 << 4); /* XRDY_IE */
313 case 0x18: /* I2C_CNT */
314 s->count = value; /* DCOUNT */
317 case 0x1c: /* I2C_DATA */
319 /* XXX: remote access (qualifier) error - what's that? */
324 if (s->control & (1 << 14)) { /* BE */
325 s->fifo |= ((value >> 8) & 0xff) << 8;
326 s->fifo |= ((value >> 0) & 0xff) << 0;
328 s->fifo |= ((value >> 0) & 0xff) << 8;
329 s->fifo |= ((value >> 8) & 0xff) << 0;
331 s->stat &= ~(1 << 10); /* XUDF */
333 s->stat &= ~(1 << 4); /* XRDY */
334 omap_i2c_fifo_run(s);
335 omap_i2c_interrupts_update(s);
338 case 0x24: /* I2C_CON */
339 s->control = value & 0xcf07;
340 if (~value & (1 << 15)) { /* I2C_EN */
344 if (~value & (1 << 10)) { /* MST */
345 printf("%s: I^2C slave mode not supported\n", __FUNCTION__);
348 if (value & (1 << 9)) { /* XA */
349 printf("%s: 10-bit addressing mode not supported\n", __FUNCTION__);
352 if (value & (1 << 0)) { /* STT */
353 nack = !!i2c_start_transfer(s->bus, s->addr[1], /* SA */
354 (~value >> 9) & 1); /* TRX */
355 s->stat |= nack << 1; /* NACK */
356 s->control &= ~(1 << 0); /* STT */
358 s->control &= ~(1 << 1); /* STP */
360 omap_i2c_fifo_run(s);
361 omap_i2c_interrupts_update(s);
365 case 0x28: /* I2C_OA */
366 s->addr[0] = value & 0x3ff;
367 i2c_set_slave_address(&s->slave, value & 0x7f);
370 case 0x2c: /* I2C_SA */
371 s->addr[1] = value & 0x3ff;
374 case 0x30: /* I2C_PSC */
378 case 0x34: /* I2C_SCLL */
382 case 0x38: /* I2C_SCLH */
386 case 0x3c: /* I2C_SYSTEST */
387 s->test = value & 0xf00f;
388 if (value & (1 << 15)) /* ST_EN */
389 printf("%s: System Test not supported\n", __FUNCTION__);
398 static CPUReadMemoryFunc *omap_i2c_readfn[] = {
399 omap_badwidth_read16,
401 omap_badwidth_read16,
404 static CPUWriteMemoryFunc *omap_i2c_writefn[] = {
405 omap_badwidth_write16,
407 omap_i2c_write, /* TODO: Only the last fifo write can be 8 bit. */
410 struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base,
411 qemu_irq irq, qemu_irq *dma, omap_clk clk)
414 struct omap_i2c_s *s = (struct omap_i2c_s *)
415 qemu_mallocz(sizeof(struct omap_i2c_s));
421 s->slave.event = omap_i2c_event;
422 s->slave.recv = omap_i2c_rx;
423 s->slave.send = omap_i2c_tx;
424 s->bus = i2c_init_bus();
427 iomemtype = cpu_register_io_memory(0, omap_i2c_readfn,
428 omap_i2c_writefn, s);
429 cpu_register_physical_memory(s->base, 0x800, iomemtype);
434 i2c_bus *omap_i2c_bus(struct omap_i2c_s *s)