~ubuntu-branches/ubuntu/trusty/qemu/trusty

« back to all changes in this revision

Viewing changes to .pc/linaro-patches/0019-hw-omap_i2c-non-whitespace-changes-from-overhaul-pat.patch/hw/i2c/omap_i2c.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2013-10-22 22:47:07 UTC
  • mfrom: (1.8.3) (10.1.42 sid)
  • Revision ID: package-import@ubuntu.com-20131022224707-1lya34fw3k3f24tv
Tags: 1.6.0+dfsg-2ubuntu1
* Merge 1.6.0~rc0+dfsg-2exp from debian experimental.  Remaining changes:
  - debian/control
    * update maintainer
    * remove libiscsi, usb-redir, vde, vnc-jpeg, and libssh2-1-dev
      from build-deps
    * enable rbd
    * add qemu-system and qemu-common B/R to qemu-keymaps
    * add D:udev, R:qemu, R:qemu-common and B:qemu-common to
      qemu-system-common
    * qemu-system-arm, qemu-system-ppc, qemu-system-sparc:
      - add qemu-kvm to Provides
      - add qemu-common, qemu-kvm, kvm to B/R
      - remove openbios-sparc from qemu-system-sparc D
      - drop openbios-ppc and openhackware Depends to Suggests (for now)
    * qemu-system-x86:
      - add qemu-common to Breaks/Replaces.
      - add cpu-checker to Recommends.
    * qemu-user: add B/R:qemu-kvm
    * qemu-kvm:
      - add armhf armel powerpc sparc to Architecture
      - C/R/P: qemu-kvm-spice
    * add qemu-common package
    * drop qemu-slof which is not packaged in ubuntu
  - add qemu-system-common.links for tap ifup/down scripts and OVMF link.
  - qemu-system-x86.links:
    * remove pxe rom links which are in kvm-ipxe
    * add symlink for kvm.1 manpage
  - debian/rules
    * add kvm-spice symlink to qemu-kvm
    * call dh_installmodules for qemu-system-x86
    * update dh_installinit to install upstart script
    * run dh_installman (Closes: #709241) (cherrypicked from 1.5.0+dfsg-2)
  - Add qemu-utils.links for kvm-* symlinks.
  - Add qemu-system-x86.qemu-kvm.upstart and .default
  - Add qemu-system-x86.modprobe to set nesting=1
  - Add qemu-system-common.preinst to add kvm group
  - qemu-system-common.postinst: remove bad group acl if there, then have
    udev relabel /dev/kvm.
  - New linaro patches from qemu-linaro rebasing branch
  - Dropped patches:
    * xen-simplify-xen_enabled.patch
    * sparc-linux-user-fix-missing-symbols-in-.rel-.rela.plt-sections.patch
    * main_loop-do-not-set-nonblocking-if-xen_enabled.patch
    * xen_machine_pv-do-not-create-a-dummy-CPU-in-machine-.patch
    * virtio-rng-fix-crash
  - Kept patches:
    * expose_vms_qemu64cpu.patch - updated
    * linaro arm patches from qemu-linaro rebasing branch
  - New patches:
    * fix-pci-add: change CONFIG variable in ifdef to make sure that
      pci_add is defined.
* Add linaro patches
* Add experimental mach-virt patches for arm virtualization.
* qemu-system-common.install: add debian/tmp/usr/lib to install the
  qemu-bridge-helper

Show diffs side-by-side

added added

removed removed

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