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,
24 target_phys_addr_t base;
45 static void omap_i2c_interrupts_update(struct omap_i2c_s *s)
47 qemu_set_irq(s->irq, s->stat & s->mask);
48 if ((s->dma >> 15) & 1) /* RDMA_EN */
49 qemu_set_irq(s->drq[0], (s->stat >> 3) & 1); /* RRDY */
50 if ((s->dma >> 7) & 1) /* XDMA_EN */
51 qemu_set_irq(s->drq[1], (s->stat >> 4) & 1); /* XRDY */
54 /* These are only stubs now. */
55 static void omap_i2c_event(i2c_slave *i2c, enum i2c_event event)
57 struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
59 if ((~s->control >> 15) & 1) /* I2C_EN */
65 s->stat |= 1 << 9; /* AAS */
68 s->stat |= 1 << 2; /* ARDY */
71 s->stat |= 1 << 1; /* NACK */
75 omap_i2c_interrupts_update(s);
78 static int omap_i2c_rx(i2c_slave *i2c)
80 struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
83 if ((~s->control >> 15) & 1) /* I2C_EN */
87 ret = s->fifo >> ((-- s->txlen) << 3) & 0xff;
89 s->stat |= 1 << 10; /* XUDF */
90 s->stat |= 1 << 4; /* XRDY */
92 omap_i2c_interrupts_update(s);
96 static int omap_i2c_tx(i2c_slave *i2c, uint8_t data)
98 struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
100 if ((~s->control >> 15) & 1) /* I2C_EN */
104 s->fifo |= data << ((s->rxlen ++) << 3);
106 s->stat |= 1 << 11; /* ROVR */
107 s->stat |= 1 << 3; /* RRDY */
109 omap_i2c_interrupts_update(s);
113 static void omap_i2c_fifo_run(struct omap_i2c_s *s)
117 if (!i2c_bus_busy(s->bus))
120 if ((s->control >> 2) & 1) { /* RM */
121 if ((s->control >> 1) & 1) { /* STP */
122 i2c_end_transfer(s->bus);
123 s->control &= ~(1 << 1); /* STP */
124 s->count_cur = s->count;
125 } else if ((s->control >> 9) & 1) { /* TRX */
126 while (ack && s->txlen)
127 ack = (i2c_send(s->bus,
128 (s->fifo >> ((-- s->txlen) << 3)) &
130 s->stat |= 1 << 4; /* XRDY */
133 s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
134 s->stat |= 1 << 3; /* RRDY */
137 if ((s->control >> 9) & 1) { /* TRX */
138 while (ack && s->count_cur && s->txlen) {
139 ack = (i2c_send(s->bus,
140 (s->fifo >> ((-- s->txlen) << 3)) &
144 if (ack && s->count_cur)
145 s->stat |= 1 << 4; /* XRDY */
147 s->stat |= 1 << 2; /* ARDY */
148 s->control &= ~(1 << 10); /* MST */
151 while (s->count_cur && s->rxlen < 4) {
152 s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
156 s->stat |= 1 << 3; /* RRDY */
159 if ((s->control >> 1) & 1) { /* STP */
160 i2c_end_transfer(s->bus);
161 s->control &= ~(1 << 1); /* STP */
162 s->count_cur = s->count;
164 s->stat |= 1 << 2; /* ARDY */
165 s->control &= ~(1 << 10); /* MST */
170 s->stat |= (!ack) << 1; /* NACK */
172 s->control &= ~(1 << 1); /* STP */
175 void omap_i2c_reset(struct omap_i2c_s *s)
194 static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr)
196 struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
197 int offset = addr - s->base;
201 case 0x00: /* I2C_REV */
202 /* TODO: set a value greater or equal to real hardware */
203 return 0x11; /* REV */
205 case 0x04: /* I2C_IE */
208 case 0x08: /* I2C_STAT */
209 return s->stat | (i2c_bus_busy(s->bus) << 12);
211 case 0x0c: /* I2C_IV */
212 ret = ffs(s->stat & s->mask);
214 s->stat ^= 1 << (ret - 1);
215 omap_i2c_interrupts_update(s);
218 case 0x14: /* I2C_BUF */
221 case 0x18: /* I2C_CNT */
222 return s->count_cur; /* DCOUNT */
224 case 0x1c: /* I2C_DATA */
226 if (s->control & (1 << 14)) { /* BE */
227 ret |= ((s->fifo >> 0) & 0xff) << 8;
228 ret |= ((s->fifo >> 8) & 0xff) << 0;
230 ret |= ((s->fifo >> 8) & 0xff) << 8;
231 ret |= ((s->fifo >> 0) & 0xff) << 0;
234 s->stat |= 1 << 15; /* SBD */
236 } else if (s->rxlen > 1) {
241 /* XXX: remote access (qualifier) error - what's that? */;
243 s->stat |= ~(1 << 3); /* RRDY */
244 if (((s->control >> 10) & 1) && /* MST */
245 ((~s->control >> 9) & 1)) { /* TRX */
246 s->stat |= 1 << 2; /* ARDY */
247 s->control &= ~(1 << 10); /* MST */
250 s->stat &= ~(1 << 11); /* ROVR */
251 omap_i2c_fifo_run(s);
252 omap_i2c_interrupts_update(s);
255 case 0x24: /* I2C_CON */
258 case 0x28: /* I2C_OA */
261 case 0x2c: /* I2C_SA */
264 case 0x30: /* I2C_PSC */
267 case 0x34: /* I2C_SCLL */
270 case 0x38: /* I2C_SCLH */
273 case 0x3c: /* I2C_SYSTEST */
274 if (s->test & (1 << 15)) { /* ST_EN */
278 return s->test & ~0x300f;
285 static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
288 struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
289 int offset = addr - s->base;
293 case 0x00: /* I2C_REV */
294 case 0x08: /* I2C_STAT */
295 case 0x0c: /* I2C_IV */
299 case 0x04: /* I2C_IE */
300 s->mask = value & 0x1f;
303 case 0x14: /* I2C_BUF */
304 s->dma = value & 0x8080;
305 if (value & (1 << 15)) /* RDMA_EN */
306 s->mask &= ~(1 << 3); /* RRDY_IE */
307 if (value & (1 << 7)) /* XDMA_EN */
308 s->mask &= ~(1 << 4); /* XRDY_IE */
311 case 0x18: /* I2C_CNT */
312 s->count = value; /* DCOUNT */
315 case 0x1c: /* I2C_DATA */
317 /* XXX: remote access (qualifier) error - what's that? */
322 if (s->control & (1 << 14)) { /* BE */
323 s->fifo |= ((value >> 8) & 0xff) << 8;
324 s->fifo |= ((value >> 0) & 0xff) << 0;
326 s->fifo |= ((value >> 0) & 0xff) << 8;
327 s->fifo |= ((value >> 8) & 0xff) << 0;
329 s->stat &= ~(1 << 10); /* XUDF */
331 s->stat &= ~(1 << 4); /* XRDY */
332 omap_i2c_fifo_run(s);
333 omap_i2c_interrupts_update(s);
336 case 0x24: /* I2C_CON */
337 s->control = value & 0xcf07;
338 if (~value & (1 << 15)) { /* I2C_EN */
342 if (~value & (1 << 10)) { /* MST */
343 printf("%s: I^2C slave mode not supported\n", __FUNCTION__);
346 if (value & (1 << 9)) { /* XA */
347 printf("%s: 10-bit addressing mode not supported\n", __FUNCTION__);
350 if (value & (1 << 0)) { /* STT */
351 nack = !!i2c_start_transfer(s->bus, s->addr[1], /* SA */
352 (~value >> 9) & 1); /* TRX */
353 s->stat |= nack << 1; /* NACK */
354 s->control &= ~(1 << 0); /* STT */
356 s->control &= ~(1 << 1); /* STP */
358 omap_i2c_fifo_run(s);
359 omap_i2c_interrupts_update(s);
363 case 0x28: /* I2C_OA */
364 s->addr[0] = value & 0x3ff;
365 i2c_set_slave_address(&s->slave, value & 0x7f);
368 case 0x2c: /* I2C_SA */
369 s->addr[1] = value & 0x3ff;
372 case 0x30: /* I2C_PSC */
376 case 0x34: /* I2C_SCLL */
380 case 0x38: /* I2C_SCLH */
384 case 0x3c: /* I2C_SYSTEST */
385 s->test = value & 0xf00f;
386 if (value & (1 << 15)) /* ST_EN */
387 printf("%s: System Test not supported\n", __FUNCTION__);
396 static CPUReadMemoryFunc *omap_i2c_readfn[] = {
397 omap_badwidth_read16,
399 omap_badwidth_read16,
402 static CPUWriteMemoryFunc *omap_i2c_writefn[] = {
403 omap_badwidth_write16,
405 omap_i2c_write, /* TODO: Only the last fifo write can be 8 bit. */
408 struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base,
409 qemu_irq irq, qemu_irq *dma, omap_clk clk)
412 struct omap_i2c_s *s = (struct omap_i2c_s *)
413 qemu_mallocz(sizeof(struct omap_i2c_s));
419 s->slave.event = omap_i2c_event;
420 s->slave.recv = omap_i2c_rx;
421 s->slave.send = omap_i2c_tx;
422 s->bus = i2c_init_bus();
425 iomemtype = cpu_register_io_memory(0, omap_i2c_readfn,
426 omap_i2c_writefn, s);
427 cpu_register_physical_memory(s->base, 0x800, iomemtype);
432 i2c_bus *omap_i2c_bus(struct omap_i2c_s *s)