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,
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
)