]>
git.proxmox.com Git - mirror_qemu.git/blob - hw/omap_i2c.c
2 * TI OMAP on-chip I2C controller. Only "new I2C" mode supported.
4 * Copyright (C) 2007 Andrzej Zaborowski <balrog@zabor.org>
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
)