xref: /qemu/hw/i2c/omap_i2c.c (revision 53ed424e)
1*53ed424eSPaolo Bonzini /*
2*53ed424eSPaolo Bonzini  * TI OMAP on-chip I2C controller.  Only "new I2C" mode supported.
3*53ed424eSPaolo Bonzini  *
4*53ed424eSPaolo Bonzini  * Copyright (C) 2007 Andrzej Zaborowski  <balrog@zabor.org>
5*53ed424eSPaolo Bonzini  *
6*53ed424eSPaolo Bonzini  * This program is free software; you can redistribute it and/or
7*53ed424eSPaolo Bonzini  * modify it under the terms of the GNU General Public License as
8*53ed424eSPaolo Bonzini  * published by the Free Software Foundation; either version 2 of
9*53ed424eSPaolo Bonzini  * the License, or (at your option) any later version.
10*53ed424eSPaolo Bonzini  *
11*53ed424eSPaolo Bonzini  * This program is distributed in the hope that it will be useful,
12*53ed424eSPaolo Bonzini  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*53ed424eSPaolo Bonzini  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*53ed424eSPaolo Bonzini  * GNU General Public License for more details.
15*53ed424eSPaolo Bonzini  *
16*53ed424eSPaolo Bonzini  * You should have received a copy of the GNU General Public License along
17*53ed424eSPaolo Bonzini  * with this program; if not, see <http://www.gnu.org/licenses/>.
18*53ed424eSPaolo Bonzini  */
19*53ed424eSPaolo Bonzini #include "hw/hw.h"
20*53ed424eSPaolo Bonzini #include "hw/i2c/i2c.h"
21*53ed424eSPaolo Bonzini #include "hw/arm/omap.h"
22*53ed424eSPaolo Bonzini #include "hw/sysbus.h"
23*53ed424eSPaolo Bonzini 
24*53ed424eSPaolo Bonzini 
25*53ed424eSPaolo Bonzini typedef struct OMAPI2CState {
26*53ed424eSPaolo Bonzini     SysBusDevice busdev;
27*53ed424eSPaolo Bonzini     MemoryRegion iomem;
28*53ed424eSPaolo Bonzini     qemu_irq irq;
29*53ed424eSPaolo Bonzini     qemu_irq drq[2];
30*53ed424eSPaolo Bonzini     i2c_bus *bus;
31*53ed424eSPaolo Bonzini 
32*53ed424eSPaolo Bonzini     uint8_t revision;
33*53ed424eSPaolo Bonzini     void *iclk;
34*53ed424eSPaolo Bonzini     void *fclk;
35*53ed424eSPaolo Bonzini 
36*53ed424eSPaolo Bonzini     uint8_t mask;
37*53ed424eSPaolo Bonzini     uint16_t stat;
38*53ed424eSPaolo Bonzini     uint16_t dma;
39*53ed424eSPaolo Bonzini     uint16_t count;
40*53ed424eSPaolo Bonzini     int count_cur;
41*53ed424eSPaolo Bonzini     uint32_t fifo;
42*53ed424eSPaolo Bonzini     int rxlen;
43*53ed424eSPaolo Bonzini     int txlen;
44*53ed424eSPaolo Bonzini     uint16_t control;
45*53ed424eSPaolo Bonzini     uint16_t addr[2];
46*53ed424eSPaolo Bonzini     uint8_t divider;
47*53ed424eSPaolo Bonzini     uint8_t times[2];
48*53ed424eSPaolo Bonzini     uint16_t test;
49*53ed424eSPaolo Bonzini } OMAPI2CState;
50*53ed424eSPaolo Bonzini 
51*53ed424eSPaolo Bonzini #define OMAP2_INTR_REV	0x34
52*53ed424eSPaolo Bonzini #define OMAP2_GC_REV	0x34
53*53ed424eSPaolo Bonzini 
54*53ed424eSPaolo Bonzini static void omap_i2c_interrupts_update(OMAPI2CState *s)
55*53ed424eSPaolo Bonzini {
56*53ed424eSPaolo Bonzini     qemu_set_irq(s->irq, s->stat & s->mask);
57*53ed424eSPaolo Bonzini     if ((s->dma >> 15) & 1)					/* RDMA_EN */
58*53ed424eSPaolo Bonzini         qemu_set_irq(s->drq[0], (s->stat >> 3) & 1);		/* RRDY */
59*53ed424eSPaolo Bonzini     if ((s->dma >> 7) & 1)					/* XDMA_EN */
60*53ed424eSPaolo Bonzini         qemu_set_irq(s->drq[1], (s->stat >> 4) & 1);		/* XRDY */
61*53ed424eSPaolo Bonzini }
62*53ed424eSPaolo Bonzini 
63*53ed424eSPaolo Bonzini static void omap_i2c_fifo_run(OMAPI2CState *s)
64*53ed424eSPaolo Bonzini {
65*53ed424eSPaolo Bonzini     int ack = 1;
66*53ed424eSPaolo Bonzini 
67*53ed424eSPaolo Bonzini     if (!i2c_bus_busy(s->bus))
68*53ed424eSPaolo Bonzini         return;
69*53ed424eSPaolo Bonzini 
70*53ed424eSPaolo Bonzini     if ((s->control >> 2) & 1) {				/* RM */
71*53ed424eSPaolo Bonzini         if ((s->control >> 1) & 1) {				/* STP */
72*53ed424eSPaolo Bonzini             i2c_end_transfer(s->bus);
73*53ed424eSPaolo Bonzini             s->control &= ~(1 << 1);				/* STP */
74*53ed424eSPaolo Bonzini             s->count_cur = s->count;
75*53ed424eSPaolo Bonzini             s->txlen = 0;
76*53ed424eSPaolo Bonzini         } else if ((s->control >> 9) & 1) {			/* TRX */
77*53ed424eSPaolo Bonzini             while (ack && s->txlen)
78*53ed424eSPaolo Bonzini                 ack = (i2c_send(s->bus,
79*53ed424eSPaolo Bonzini                                         (s->fifo >> ((-- s->txlen) << 3)) &
80*53ed424eSPaolo Bonzini                                         0xff) >= 0);
81*53ed424eSPaolo Bonzini             s->stat |= 1 << 4;					/* XRDY */
82*53ed424eSPaolo Bonzini         } else {
83*53ed424eSPaolo Bonzini             while (s->rxlen < 4)
84*53ed424eSPaolo Bonzini                 s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
85*53ed424eSPaolo Bonzini             s->stat |= 1 << 3;					/* RRDY */
86*53ed424eSPaolo Bonzini         }
87*53ed424eSPaolo Bonzini     } else {
88*53ed424eSPaolo Bonzini         if ((s->control >> 9) & 1) {				/* TRX */
89*53ed424eSPaolo Bonzini             while (ack && s->count_cur && s->txlen) {
90*53ed424eSPaolo Bonzini                 ack = (i2c_send(s->bus,
91*53ed424eSPaolo Bonzini                                         (s->fifo >> ((-- s->txlen) << 3)) &
92*53ed424eSPaolo Bonzini                                         0xff) >= 0);
93*53ed424eSPaolo Bonzini                 s->count_cur --;
94*53ed424eSPaolo Bonzini             }
95*53ed424eSPaolo Bonzini             if (ack && s->count_cur)
96*53ed424eSPaolo Bonzini                 s->stat |= 1 << 4;				/* XRDY */
97*53ed424eSPaolo Bonzini             else
98*53ed424eSPaolo Bonzini                 s->stat &= ~(1 << 4);				/* XRDY */
99*53ed424eSPaolo Bonzini             if (!s->count_cur) {
100*53ed424eSPaolo Bonzini                 s->stat |= 1 << 2;				/* ARDY */
101*53ed424eSPaolo Bonzini                 s->control &= ~(1 << 10);			/* MST */
102*53ed424eSPaolo Bonzini             }
103*53ed424eSPaolo Bonzini         } else {
104*53ed424eSPaolo Bonzini             while (s->count_cur && s->rxlen < 4) {
105*53ed424eSPaolo Bonzini                 s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
106*53ed424eSPaolo Bonzini                 s->count_cur --;
107*53ed424eSPaolo Bonzini             }
108*53ed424eSPaolo Bonzini             if (s->rxlen)
109*53ed424eSPaolo Bonzini                 s->stat |= 1 << 3;				/* RRDY */
110*53ed424eSPaolo Bonzini             else
111*53ed424eSPaolo Bonzini                 s->stat &= ~(1 << 3);				/* RRDY */
112*53ed424eSPaolo Bonzini         }
113*53ed424eSPaolo Bonzini         if (!s->count_cur) {
114*53ed424eSPaolo Bonzini             if ((s->control >> 1) & 1) {			/* STP */
115*53ed424eSPaolo Bonzini                 i2c_end_transfer(s->bus);
116*53ed424eSPaolo Bonzini                 s->control &= ~(1 << 1);			/* STP */
117*53ed424eSPaolo Bonzini                 s->count_cur = s->count;
118*53ed424eSPaolo Bonzini                 s->txlen = 0;
119*53ed424eSPaolo Bonzini             } else {
120*53ed424eSPaolo Bonzini                 s->stat |= 1 << 2;				/* ARDY */
121*53ed424eSPaolo Bonzini                 s->control &= ~(1 << 10);			/* MST */
122*53ed424eSPaolo Bonzini             }
123*53ed424eSPaolo Bonzini         }
124*53ed424eSPaolo Bonzini     }
125*53ed424eSPaolo Bonzini 
126*53ed424eSPaolo Bonzini     s->stat |= (!ack) << 1;					/* NACK */
127*53ed424eSPaolo Bonzini     if (!ack)
128*53ed424eSPaolo Bonzini         s->control &= ~(1 << 1);				/* STP */
129*53ed424eSPaolo Bonzini }
130*53ed424eSPaolo Bonzini 
131*53ed424eSPaolo Bonzini static void omap_i2c_reset(DeviceState *dev)
132*53ed424eSPaolo Bonzini {
133*53ed424eSPaolo Bonzini     OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState,
134*53ed424eSPaolo Bonzini                                   SYS_BUS_DEVICE(dev));
135*53ed424eSPaolo Bonzini     s->mask = 0;
136*53ed424eSPaolo Bonzini     s->stat = 0;
137*53ed424eSPaolo Bonzini     s->dma = 0;
138*53ed424eSPaolo Bonzini     s->count = 0;
139*53ed424eSPaolo Bonzini     s->count_cur = 0;
140*53ed424eSPaolo Bonzini     s->fifo = 0;
141*53ed424eSPaolo Bonzini     s->rxlen = 0;
142*53ed424eSPaolo Bonzini     s->txlen = 0;
143*53ed424eSPaolo Bonzini     s->control = 0;
144*53ed424eSPaolo Bonzini     s->addr[0] = 0;
145*53ed424eSPaolo Bonzini     s->addr[1] = 0;
146*53ed424eSPaolo Bonzini     s->divider = 0;
147*53ed424eSPaolo Bonzini     s->times[0] = 0;
148*53ed424eSPaolo Bonzini     s->times[1] = 0;
149*53ed424eSPaolo Bonzini     s->test = 0;
150*53ed424eSPaolo Bonzini }
151*53ed424eSPaolo Bonzini 
152*53ed424eSPaolo Bonzini static uint32_t omap_i2c_read(void *opaque, hwaddr addr)
153*53ed424eSPaolo Bonzini {
154*53ed424eSPaolo Bonzini     OMAPI2CState *s = opaque;
155*53ed424eSPaolo Bonzini     int offset = addr & OMAP_MPUI_REG_MASK;
156*53ed424eSPaolo Bonzini     uint16_t ret;
157*53ed424eSPaolo Bonzini 
158*53ed424eSPaolo Bonzini     switch (offset) {
159*53ed424eSPaolo Bonzini     case 0x00:	/* I2C_REV */
160*53ed424eSPaolo Bonzini         return s->revision;					/* REV */
161*53ed424eSPaolo Bonzini 
162*53ed424eSPaolo Bonzini     case 0x04:	/* I2C_IE */
163*53ed424eSPaolo Bonzini         return s->mask;
164*53ed424eSPaolo Bonzini 
165*53ed424eSPaolo Bonzini     case 0x08:	/* I2C_STAT */
166*53ed424eSPaolo Bonzini         return s->stat | (i2c_bus_busy(s->bus) << 12);
167*53ed424eSPaolo Bonzini 
168*53ed424eSPaolo Bonzini     case 0x0c:	/* I2C_IV */
169*53ed424eSPaolo Bonzini         if (s->revision >= OMAP2_INTR_REV)
170*53ed424eSPaolo Bonzini             break;
171*53ed424eSPaolo Bonzini         ret = ffs(s->stat & s->mask);
172*53ed424eSPaolo Bonzini         if (ret)
173*53ed424eSPaolo Bonzini             s->stat ^= 1 << (ret - 1);
174*53ed424eSPaolo Bonzini         omap_i2c_interrupts_update(s);
175*53ed424eSPaolo Bonzini         return ret;
176*53ed424eSPaolo Bonzini 
177*53ed424eSPaolo Bonzini     case 0x10:	/* I2C_SYSS */
178*53ed424eSPaolo Bonzini         return (s->control >> 15) & 1;				/* I2C_EN */
179*53ed424eSPaolo Bonzini 
180*53ed424eSPaolo Bonzini     case 0x14:	/* I2C_BUF */
181*53ed424eSPaolo Bonzini         return s->dma;
182*53ed424eSPaolo Bonzini 
183*53ed424eSPaolo Bonzini     case 0x18:	/* I2C_CNT */
184*53ed424eSPaolo Bonzini         return s->count_cur;					/* DCOUNT */
185*53ed424eSPaolo Bonzini 
186*53ed424eSPaolo Bonzini     case 0x1c:	/* I2C_DATA */
187*53ed424eSPaolo Bonzini         ret = 0;
188*53ed424eSPaolo Bonzini         if (s->control & (1 << 14)) {				/* BE */
189*53ed424eSPaolo Bonzini             ret |= ((s->fifo >> 0) & 0xff) << 8;
190*53ed424eSPaolo Bonzini             ret |= ((s->fifo >> 8) & 0xff) << 0;
191*53ed424eSPaolo Bonzini         } else {
192*53ed424eSPaolo Bonzini             ret |= ((s->fifo >> 8) & 0xff) << 8;
193*53ed424eSPaolo Bonzini             ret |= ((s->fifo >> 0) & 0xff) << 0;
194*53ed424eSPaolo Bonzini         }
195*53ed424eSPaolo Bonzini         if (s->rxlen == 1) {
196*53ed424eSPaolo Bonzini             s->stat |= 1 << 15;					/* SBD */
197*53ed424eSPaolo Bonzini             s->rxlen = 0;
198*53ed424eSPaolo Bonzini         } else if (s->rxlen > 1) {
199*53ed424eSPaolo Bonzini             if (s->rxlen > 2)
200*53ed424eSPaolo Bonzini                 s->fifo >>= 16;
201*53ed424eSPaolo Bonzini             s->rxlen -= 2;
202*53ed424eSPaolo Bonzini         } else {
203*53ed424eSPaolo Bonzini             /* XXX: remote access (qualifier) error - what's that?  */
204*53ed424eSPaolo Bonzini         }
205*53ed424eSPaolo Bonzini         if (!s->rxlen) {
206*53ed424eSPaolo Bonzini             s->stat &= ~(1 << 3);				/* RRDY */
207*53ed424eSPaolo Bonzini             if (((s->control >> 10) & 1) &&			/* MST */
208*53ed424eSPaolo Bonzini                             ((~s->control >> 9) & 1)) {		/* TRX */
209*53ed424eSPaolo Bonzini                 s->stat |= 1 << 2;				/* ARDY */
210*53ed424eSPaolo Bonzini                 s->control &= ~(1 << 10);			/* MST */
211*53ed424eSPaolo Bonzini             }
212*53ed424eSPaolo Bonzini         }
213*53ed424eSPaolo Bonzini         s->stat &= ~(1 << 11);					/* ROVR */
214*53ed424eSPaolo Bonzini         omap_i2c_fifo_run(s);
215*53ed424eSPaolo Bonzini         omap_i2c_interrupts_update(s);
216*53ed424eSPaolo Bonzini         return ret;
217*53ed424eSPaolo Bonzini 
218*53ed424eSPaolo Bonzini     case 0x20:	/* I2C_SYSC */
219*53ed424eSPaolo Bonzini         return 0;
220*53ed424eSPaolo Bonzini 
221*53ed424eSPaolo Bonzini     case 0x24:	/* I2C_CON */
222*53ed424eSPaolo Bonzini         return s->control;
223*53ed424eSPaolo Bonzini 
224*53ed424eSPaolo Bonzini     case 0x28:	/* I2C_OA */
225*53ed424eSPaolo Bonzini         return s->addr[0];
226*53ed424eSPaolo Bonzini 
227*53ed424eSPaolo Bonzini     case 0x2c:	/* I2C_SA */
228*53ed424eSPaolo Bonzini         return s->addr[1];
229*53ed424eSPaolo Bonzini 
230*53ed424eSPaolo Bonzini     case 0x30:	/* I2C_PSC */
231*53ed424eSPaolo Bonzini         return s->divider;
232*53ed424eSPaolo Bonzini 
233*53ed424eSPaolo Bonzini     case 0x34:	/* I2C_SCLL */
234*53ed424eSPaolo Bonzini         return s->times[0];
235*53ed424eSPaolo Bonzini 
236*53ed424eSPaolo Bonzini     case 0x38:	/* I2C_SCLH */
237*53ed424eSPaolo Bonzini         return s->times[1];
238*53ed424eSPaolo Bonzini 
239*53ed424eSPaolo Bonzini     case 0x3c:	/* I2C_SYSTEST */
240*53ed424eSPaolo Bonzini         if (s->test & (1 << 15)) {				/* ST_EN */
241*53ed424eSPaolo Bonzini             s->test ^= 0xa;
242*53ed424eSPaolo Bonzini             return s->test;
243*53ed424eSPaolo Bonzini         } else
244*53ed424eSPaolo Bonzini             return s->test & ~0x300f;
245*53ed424eSPaolo Bonzini     }
246*53ed424eSPaolo Bonzini 
247*53ed424eSPaolo Bonzini     OMAP_BAD_REG(addr);
248*53ed424eSPaolo Bonzini     return 0;
249*53ed424eSPaolo Bonzini }
250*53ed424eSPaolo Bonzini 
251*53ed424eSPaolo Bonzini static void omap_i2c_write(void *opaque, hwaddr addr,
252*53ed424eSPaolo Bonzini                 uint32_t value)
253*53ed424eSPaolo Bonzini {
254*53ed424eSPaolo Bonzini     OMAPI2CState *s = opaque;
255*53ed424eSPaolo Bonzini     int offset = addr & OMAP_MPUI_REG_MASK;
256*53ed424eSPaolo Bonzini     int nack;
257*53ed424eSPaolo Bonzini 
258*53ed424eSPaolo Bonzini     switch (offset) {
259*53ed424eSPaolo Bonzini     case 0x00:	/* I2C_REV */
260*53ed424eSPaolo Bonzini     case 0x0c:	/* I2C_IV */
261*53ed424eSPaolo Bonzini     case 0x10:	/* I2C_SYSS */
262*53ed424eSPaolo Bonzini         OMAP_RO_REG(addr);
263*53ed424eSPaolo Bonzini         return;
264*53ed424eSPaolo Bonzini 
265*53ed424eSPaolo Bonzini     case 0x04:	/* I2C_IE */
266*53ed424eSPaolo Bonzini         s->mask = value & (s->revision < OMAP2_GC_REV ? 0x1f : 0x3f);
267*53ed424eSPaolo Bonzini         break;
268*53ed424eSPaolo Bonzini 
269*53ed424eSPaolo Bonzini     case 0x08:	/* I2C_STAT */
270*53ed424eSPaolo Bonzini         if (s->revision < OMAP2_INTR_REV) {
271*53ed424eSPaolo Bonzini             OMAP_RO_REG(addr);
272*53ed424eSPaolo Bonzini             return;
273*53ed424eSPaolo Bonzini         }
274*53ed424eSPaolo Bonzini 
275*53ed424eSPaolo Bonzini         /* RRDY and XRDY are reset by hardware. (in all versions???) */
276*53ed424eSPaolo Bonzini         s->stat &= ~(value & 0x27);
277*53ed424eSPaolo Bonzini         omap_i2c_interrupts_update(s);
278*53ed424eSPaolo Bonzini         break;
279*53ed424eSPaolo Bonzini 
280*53ed424eSPaolo Bonzini     case 0x14:	/* I2C_BUF */
281*53ed424eSPaolo Bonzini         s->dma = value & 0x8080;
282*53ed424eSPaolo Bonzini         if (value & (1 << 15))					/* RDMA_EN */
283*53ed424eSPaolo Bonzini             s->mask &= ~(1 << 3);				/* RRDY_IE */
284*53ed424eSPaolo Bonzini         if (value & (1 << 7))					/* XDMA_EN */
285*53ed424eSPaolo Bonzini             s->mask &= ~(1 << 4);				/* XRDY_IE */
286*53ed424eSPaolo Bonzini         break;
287*53ed424eSPaolo Bonzini 
288*53ed424eSPaolo Bonzini     case 0x18:	/* I2C_CNT */
289*53ed424eSPaolo Bonzini         s->count = value;					/* DCOUNT */
290*53ed424eSPaolo Bonzini         break;
291*53ed424eSPaolo Bonzini 
292*53ed424eSPaolo Bonzini     case 0x1c:	/* I2C_DATA */
293*53ed424eSPaolo Bonzini         if (s->txlen > 2) {
294*53ed424eSPaolo Bonzini             /* XXX: remote access (qualifier) error - what's that?  */
295*53ed424eSPaolo Bonzini             break;
296*53ed424eSPaolo Bonzini         }
297*53ed424eSPaolo Bonzini         s->fifo <<= 16;
298*53ed424eSPaolo Bonzini         s->txlen += 2;
299*53ed424eSPaolo Bonzini         if (s->control & (1 << 14)) {				/* BE */
300*53ed424eSPaolo Bonzini             s->fifo |= ((value >> 8) & 0xff) << 8;
301*53ed424eSPaolo Bonzini             s->fifo |= ((value >> 0) & 0xff) << 0;
302*53ed424eSPaolo Bonzini         } else {
303*53ed424eSPaolo Bonzini             s->fifo |= ((value >> 0) & 0xff) << 8;
304*53ed424eSPaolo Bonzini             s->fifo |= ((value >> 8) & 0xff) << 0;
305*53ed424eSPaolo Bonzini         }
306*53ed424eSPaolo Bonzini         s->stat &= ~(1 << 10);					/* XUDF */
307*53ed424eSPaolo Bonzini         if (s->txlen > 2)
308*53ed424eSPaolo Bonzini             s->stat &= ~(1 << 4);				/* XRDY */
309*53ed424eSPaolo Bonzini         omap_i2c_fifo_run(s);
310*53ed424eSPaolo Bonzini         omap_i2c_interrupts_update(s);
311*53ed424eSPaolo Bonzini         break;
312*53ed424eSPaolo Bonzini 
313*53ed424eSPaolo Bonzini     case 0x20:	/* I2C_SYSC */
314*53ed424eSPaolo Bonzini         if (s->revision < OMAP2_INTR_REV) {
315*53ed424eSPaolo Bonzini             OMAP_BAD_REG(addr);
316*53ed424eSPaolo Bonzini             return;
317*53ed424eSPaolo Bonzini         }
318*53ed424eSPaolo Bonzini 
319*53ed424eSPaolo Bonzini         if (value & 2)
320*53ed424eSPaolo Bonzini             omap_i2c_reset(&s->busdev.qdev);
321*53ed424eSPaolo Bonzini         break;
322*53ed424eSPaolo Bonzini 
323*53ed424eSPaolo Bonzini     case 0x24:	/* I2C_CON */
324*53ed424eSPaolo Bonzini         s->control = value & 0xcf87;
325*53ed424eSPaolo Bonzini         if (~value & (1 << 15)) {				/* I2C_EN */
326*53ed424eSPaolo Bonzini             if (s->revision < OMAP2_INTR_REV)
327*53ed424eSPaolo Bonzini                 omap_i2c_reset(&s->busdev.qdev);
328*53ed424eSPaolo Bonzini             break;
329*53ed424eSPaolo Bonzini         }
330*53ed424eSPaolo Bonzini         if ((value & (1 << 15)) && !(value & (1 << 10))) {	/* MST */
331*53ed424eSPaolo Bonzini             fprintf(stderr, "%s: I^2C slave mode not supported\n",
332*53ed424eSPaolo Bonzini                             __FUNCTION__);
333*53ed424eSPaolo Bonzini             break;
334*53ed424eSPaolo Bonzini         }
335*53ed424eSPaolo Bonzini         if ((value & (1 << 15)) && value & (1 << 8)) {		/* XA */
336*53ed424eSPaolo Bonzini             fprintf(stderr, "%s: 10-bit addressing mode not supported\n",
337*53ed424eSPaolo Bonzini                             __FUNCTION__);
338*53ed424eSPaolo Bonzini             break;
339*53ed424eSPaolo Bonzini         }
340*53ed424eSPaolo Bonzini         if ((value & (1 << 15)) && value & (1 << 0)) {		/* STT */
341*53ed424eSPaolo Bonzini             nack = !!i2c_start_transfer(s->bus, s->addr[1],	/* SA */
342*53ed424eSPaolo Bonzini                             (~value >> 9) & 1);			/* TRX */
343*53ed424eSPaolo Bonzini             s->stat |= nack << 1;				/* NACK */
344*53ed424eSPaolo Bonzini             s->control &= ~(1 << 0);				/* STT */
345*53ed424eSPaolo Bonzini             s->fifo = 0;
346*53ed424eSPaolo Bonzini             if (nack)
347*53ed424eSPaolo Bonzini                 s->control &= ~(1 << 1);			/* STP */
348*53ed424eSPaolo Bonzini             else {
349*53ed424eSPaolo Bonzini                 s->count_cur = s->count;
350*53ed424eSPaolo Bonzini                 omap_i2c_fifo_run(s);
351*53ed424eSPaolo Bonzini             }
352*53ed424eSPaolo Bonzini             omap_i2c_interrupts_update(s);
353*53ed424eSPaolo Bonzini         }
354*53ed424eSPaolo Bonzini         break;
355*53ed424eSPaolo Bonzini 
356*53ed424eSPaolo Bonzini     case 0x28:	/* I2C_OA */
357*53ed424eSPaolo Bonzini         s->addr[0] = value & 0x3ff;
358*53ed424eSPaolo Bonzini         break;
359*53ed424eSPaolo Bonzini 
360*53ed424eSPaolo Bonzini     case 0x2c:	/* I2C_SA */
361*53ed424eSPaolo Bonzini         s->addr[1] = value & 0x3ff;
362*53ed424eSPaolo Bonzini         break;
363*53ed424eSPaolo Bonzini 
364*53ed424eSPaolo Bonzini     case 0x30:	/* I2C_PSC */
365*53ed424eSPaolo Bonzini         s->divider = value;
366*53ed424eSPaolo Bonzini         break;
367*53ed424eSPaolo Bonzini 
368*53ed424eSPaolo Bonzini     case 0x34:	/* I2C_SCLL */
369*53ed424eSPaolo Bonzini         s->times[0] = value;
370*53ed424eSPaolo Bonzini         break;
371*53ed424eSPaolo Bonzini 
372*53ed424eSPaolo Bonzini     case 0x38:	/* I2C_SCLH */
373*53ed424eSPaolo Bonzini         s->times[1] = value;
374*53ed424eSPaolo Bonzini         break;
375*53ed424eSPaolo Bonzini 
376*53ed424eSPaolo Bonzini     case 0x3c:	/* I2C_SYSTEST */
377*53ed424eSPaolo Bonzini         s->test = value & 0xf80f;
378*53ed424eSPaolo Bonzini         if (value & (1 << 11))					/* SBB */
379*53ed424eSPaolo Bonzini             if (s->revision >= OMAP2_INTR_REV) {
380*53ed424eSPaolo Bonzini                 s->stat |= 0x3f;
381*53ed424eSPaolo Bonzini                 omap_i2c_interrupts_update(s);
382*53ed424eSPaolo Bonzini             }
383*53ed424eSPaolo Bonzini         if (value & (1 << 15))					/* ST_EN */
384*53ed424eSPaolo Bonzini             fprintf(stderr, "%s: System Test not supported\n", __FUNCTION__);
385*53ed424eSPaolo Bonzini         break;
386*53ed424eSPaolo Bonzini 
387*53ed424eSPaolo Bonzini     default:
388*53ed424eSPaolo Bonzini         OMAP_BAD_REG(addr);
389*53ed424eSPaolo Bonzini         return;
390*53ed424eSPaolo Bonzini     }
391*53ed424eSPaolo Bonzini }
392*53ed424eSPaolo Bonzini 
393*53ed424eSPaolo Bonzini static void omap_i2c_writeb(void *opaque, hwaddr addr,
394*53ed424eSPaolo Bonzini                 uint32_t value)
395*53ed424eSPaolo Bonzini {
396*53ed424eSPaolo Bonzini     OMAPI2CState *s = opaque;
397*53ed424eSPaolo Bonzini     int offset = addr & OMAP_MPUI_REG_MASK;
398*53ed424eSPaolo Bonzini 
399*53ed424eSPaolo Bonzini     switch (offset) {
400*53ed424eSPaolo Bonzini     case 0x1c:	/* I2C_DATA */
401*53ed424eSPaolo Bonzini         if (s->txlen > 2) {
402*53ed424eSPaolo Bonzini             /* XXX: remote access (qualifier) error - what's that?  */
403*53ed424eSPaolo Bonzini             break;
404*53ed424eSPaolo Bonzini         }
405*53ed424eSPaolo Bonzini         s->fifo <<= 8;
406*53ed424eSPaolo Bonzini         s->txlen += 1;
407*53ed424eSPaolo Bonzini         s->fifo |= value & 0xff;
408*53ed424eSPaolo Bonzini         s->stat &= ~(1 << 10);					/* XUDF */
409*53ed424eSPaolo Bonzini         if (s->txlen > 2)
410*53ed424eSPaolo Bonzini             s->stat &= ~(1 << 4);				/* XRDY */
411*53ed424eSPaolo Bonzini         omap_i2c_fifo_run(s);
412*53ed424eSPaolo Bonzini         omap_i2c_interrupts_update(s);
413*53ed424eSPaolo Bonzini         break;
414*53ed424eSPaolo Bonzini 
415*53ed424eSPaolo Bonzini     default:
416*53ed424eSPaolo Bonzini         OMAP_BAD_REG(addr);
417*53ed424eSPaolo Bonzini         return;
418*53ed424eSPaolo Bonzini     }
419*53ed424eSPaolo Bonzini }
420*53ed424eSPaolo Bonzini 
421*53ed424eSPaolo Bonzini static const MemoryRegionOps omap_i2c_ops = {
422*53ed424eSPaolo Bonzini     .old_mmio = {
423*53ed424eSPaolo Bonzini         .read = {
424*53ed424eSPaolo Bonzini             omap_badwidth_read16,
425*53ed424eSPaolo Bonzini             omap_i2c_read,
426*53ed424eSPaolo Bonzini             omap_badwidth_read16,
427*53ed424eSPaolo Bonzini         },
428*53ed424eSPaolo Bonzini         .write = {
429*53ed424eSPaolo Bonzini             omap_i2c_writeb, /* Only the last fifo write can be 8 bit.  */
430*53ed424eSPaolo Bonzini             omap_i2c_write,
431*53ed424eSPaolo Bonzini             omap_badwidth_write16,
432*53ed424eSPaolo Bonzini         },
433*53ed424eSPaolo Bonzini     },
434*53ed424eSPaolo Bonzini     .endianness = DEVICE_NATIVE_ENDIAN,
435*53ed424eSPaolo Bonzini };
436*53ed424eSPaolo Bonzini 
437*53ed424eSPaolo Bonzini static int omap_i2c_init(SysBusDevice *dev)
438*53ed424eSPaolo Bonzini {
439*53ed424eSPaolo Bonzini     OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, dev);
440*53ed424eSPaolo Bonzini 
441*53ed424eSPaolo Bonzini     if (!s->fclk) {
442*53ed424eSPaolo Bonzini         hw_error("omap_i2c: fclk not connected\n");
443*53ed424eSPaolo Bonzini     }
444*53ed424eSPaolo Bonzini     if (s->revision >= OMAP2_INTR_REV && !s->iclk) {
445*53ed424eSPaolo Bonzini         /* Note that OMAP1 doesn't have a separate interface clock */
446*53ed424eSPaolo Bonzini         hw_error("omap_i2c: iclk not connected\n");
447*53ed424eSPaolo Bonzini     }
448*53ed424eSPaolo Bonzini     sysbus_init_irq(dev, &s->irq);
449*53ed424eSPaolo Bonzini     sysbus_init_irq(dev, &s->drq[0]);
450*53ed424eSPaolo Bonzini     sysbus_init_irq(dev, &s->drq[1]);
451*53ed424eSPaolo Bonzini     memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap.i2c",
452*53ed424eSPaolo Bonzini                           (s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
453*53ed424eSPaolo Bonzini     sysbus_init_mmio(dev, &s->iomem);
454*53ed424eSPaolo Bonzini     s->bus = i2c_init_bus(&dev->qdev, NULL);
455*53ed424eSPaolo Bonzini     return 0;
456*53ed424eSPaolo Bonzini }
457*53ed424eSPaolo Bonzini 
458*53ed424eSPaolo Bonzini static Property omap_i2c_properties[] = {
459*53ed424eSPaolo Bonzini     DEFINE_PROP_UINT8("revision", OMAPI2CState, revision, 0),
460*53ed424eSPaolo Bonzini     DEFINE_PROP_PTR("iclk", OMAPI2CState, iclk),
461*53ed424eSPaolo Bonzini     DEFINE_PROP_PTR("fclk", OMAPI2CState, fclk),
462*53ed424eSPaolo Bonzini     DEFINE_PROP_END_OF_LIST(),
463*53ed424eSPaolo Bonzini };
464*53ed424eSPaolo Bonzini 
465*53ed424eSPaolo Bonzini static void omap_i2c_class_init(ObjectClass *klass, void *data)
466*53ed424eSPaolo Bonzini {
467*53ed424eSPaolo Bonzini     DeviceClass *dc = DEVICE_CLASS(klass);
468*53ed424eSPaolo Bonzini     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
469*53ed424eSPaolo Bonzini     k->init = omap_i2c_init;
470*53ed424eSPaolo Bonzini     dc->props = omap_i2c_properties;
471*53ed424eSPaolo Bonzini     dc->reset = omap_i2c_reset;
472*53ed424eSPaolo Bonzini }
473*53ed424eSPaolo Bonzini 
474*53ed424eSPaolo Bonzini static const TypeInfo omap_i2c_info = {
475*53ed424eSPaolo Bonzini     .name = "omap_i2c",
476*53ed424eSPaolo Bonzini     .parent = TYPE_SYS_BUS_DEVICE,
477*53ed424eSPaolo Bonzini     .instance_size = sizeof(OMAPI2CState),
478*53ed424eSPaolo Bonzini     .class_init = omap_i2c_class_init,
479*53ed424eSPaolo Bonzini };
480*53ed424eSPaolo Bonzini 
481*53ed424eSPaolo Bonzini static void omap_i2c_register_types(void)
482*53ed424eSPaolo Bonzini {
483*53ed424eSPaolo Bonzini     type_register_static(&omap_i2c_info);
484*53ed424eSPaolo Bonzini }
485*53ed424eSPaolo Bonzini 
486*53ed424eSPaolo Bonzini i2c_bus *omap_i2c_bus(DeviceState *omap_i2c)
487*53ed424eSPaolo Bonzini {
488*53ed424eSPaolo Bonzini     OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, SYS_BUS_DEVICE(omap_i2c));
489*53ed424eSPaolo Bonzini     return s->bus;
490*53ed424eSPaolo Bonzini }
491*53ed424eSPaolo Bonzini 
492*53ed424eSPaolo Bonzini type_init(omap_i2c_register_types)
493