~ubuntu-branches/ubuntu/saucy/qemu/saucy-proposed

« back to all changes in this revision

Viewing changes to .pc/patches-arm-1.4.0/0020-omap_i2c-add-vmstate.patch/hw/omap_i2c.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2013-05-28 08:18:30 UTC
  • mfrom: (1.8.2) (10.1.37 sid)
  • Revision ID: package-import@ubuntu.com-20130528081830-87xl2z9fq516a814
Tags: 1.5.0+dfsg-2ubuntu1
* Merge 1.5.0+dfs-2 from debian unstable.  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
    * 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.
  - Dropped patches:
    * 0001-fix-wrong-output-with-info-chardev-for-tcp-socket.patch
  - Kept patches:
    * expose_vms_qemu64cpu.patch - updated
    * gridcentric patch - updated
    * linaro arm patches from qemu-linaro rebasing branch

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
 
 * Copyright (C) 2009 Nokia Corporation
6
 
 *
7
 
 * This program is free software; you can redistribute it and/or
8
 
 * modify it under the terms of the GNU General Public License as
9
 
 * published by the Free Software Foundation; either version 2 of
10
 
 * the License, or (at your option) any later version.
11
 
 *
12
 
 * This program is distributed in the hope that it will be useful,
13
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
 * GNU General Public License for more details.
16
 
 *
17
 
 * You should have received a copy of the GNU General Public License along
18
 
 * with this program; if not, see <http://www.gnu.org/licenses/>.
19
 
 */
20
 
#include "hw.h"
21
 
#include "i2c.h"
22
 
#include "omap.h"
23
 
#include "sysbus.h"
24
 
 
25
 
#define I2C_MAX_FIFO_SIZE (1 << 6)
26
 
#define I2C_FIFO_SIZE_MASK ((I2C_MAX_FIFO_SIZE) - 1)
27
 
 
28
 
typedef struct OMAPI2CState {
29
 
    SysBusDevice busdev;
30
 
    MemoryRegion iomem;
31
 
    qemu_irq irq;
32
 
    qemu_irq drq[2];
33
 
    i2c_bus *bus;
34
 
 
35
 
    uint8_t revision;
36
 
    uint32_t fifosize;
37
 
    void *iclk;
38
 
    void *fclk;
39
 
 
40
 
    uint16_t mask;
41
 
    uint16_t stat;
42
 
    uint16_t we;
43
 
    uint16_t dma;
44
 
    uint16_t count;
45
 
    int count_cur;
46
 
    uint16_t sysc;
47
 
    uint16_t control;
48
 
    uint16_t own_addr[4];
49
 
    uint16_t slave_addr;
50
 
    uint8_t sblock;
51
 
    uint8_t divider;
52
 
    uint16_t times[2];
53
 
    uint16_t test;
54
 
    int fifostart;
55
 
    int fifolen;
56
 
    uint8_t fifo[I2C_MAX_FIFO_SIZE];
57
 
} OMAPI2CState;
58
 
 
59
 
/* I2C controller revision register values */
60
 
#define OMAP1_INTR_REV    0x11
61
 
#define OMAP2_INTR_REV    0x34
62
 
#define OMAP3_INTR_REV    0x3c
63
 
#define OMAP3630_INTR_REV 0x40
64
 
 
65
 
static void omap_i2c_interrupts_update(OMAPI2CState *s)
66
 
{
67
 
    qemu_set_irq(s->irq, s->stat & s->mask);
68
 
    if ((s->dma >> 15) & 1)                                     /* RDMA_EN */
69
 
        qemu_set_irq(s->drq[0], (s->stat >> 3) & 1);            /* RRDY */
70
 
    if ((s->dma >> 7) & 1)                                      /* XDMA_EN */
71
 
        qemu_set_irq(s->drq[1], (s->stat >> 4) & 1);            /* XRDY */
72
 
}
73
 
 
74
 
static void omap_i2c_fifo_run(OMAPI2CState *s)
75
 
{
76
 
    int ack = 1, i;
77
 
 
78
 
    if (!i2c_bus_busy(s->bus))
79
 
        return;
80
 
 
81
 
    if ((s->control >> 2) & 1) {                                /* RM */
82
 
        if ((s->control >> 1) & 1) {                            /* STP */
83
 
            i2c_end_transfer(s->bus);
84
 
            s->control &= ~(1 << 1);                            /* STP */
85
 
            s->count_cur = s->count;
86
 
            s->fifolen = 0;
87
 
        } else if ((s->control >> 9) & 1) {                     /* TRX */
88
 
            while (ack && s->fifolen) {
89
 
                ack = (i2c_send(s->bus, s->fifo[s->fifostart++]) >= 0);
90
 
                s->fifostart &= I2C_FIFO_SIZE_MASK;
91
 
                s->fifolen--;
92
 
            }
93
 
            s->fifolen = 0;
94
 
            s->stat |= 1 << 4;                                  /* XRDY */
95
 
        } else {
96
 
            for (i = 0; i < 4; i++)
97
 
                s->fifo[(s->fifostart + i) & I2C_FIFO_SIZE_MASK] =
98
 
                    i2c_recv(s->bus);
99
 
            s->fifolen = 4;
100
 
            s->stat |= 1 << 3;                                  /* RRDY */
101
 
        }
102
 
    } else {
103
 
        if ((s->control >> 9) & 1) {                            /* TRX */
104
 
            for (; ack && s->count_cur && s->fifolen; s->count_cur--) {
105
 
                ack = (i2c_send(s->bus, s->fifo[s->fifostart++]) >= 0);
106
 
                s->fifostart &= I2C_FIFO_SIZE_MASK;
107
 
                s->fifolen--;
108
 
            }
109
 
            s->stat &= ~0x4410;                     /* XDR | XUDF | XRDY */
110
 
            if (ack && s->count_cur) {              /* send more? */
111
 
                /* we know that FIFO is empty */
112
 
                if (s->revision < OMAP3_INTR_REV)
113
 
                    s->stat |= 1 << 4;              /* XRDY */
114
 
                else {
115
 
                    if (s->count_cur > (s->dma & 0x3f)) /* XTRSH */
116
 
                s->stat |= 1 << 4;                              /* XRDY */
117
 
            else
118
 
                        s->stat |= 1 << 14;         /* XDR */
119
 
            }
120
 
            }
121
 
            if (!s->count_cur)                      /* everything sent? */
122
 
                s->stat |= 1 << 2;                  /* ARDY */
123
 
        } else {                                    /* !TRX */
124
 
            for (; s->count_cur && s->fifolen < s->fifosize; s->count_cur--) {
125
 
                i = i2c_recv(s->bus);
126
 
                if (i < 0) break; /* stop receiving if nothing to receive */
127
 
                s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
128
 
                    (uint8_t)(i & 0xff);
129
 
            }
130
 
            s->stat &= ~((1 << 3) | (1 << 13));            /* RRDY | RDR */
131
 
            if (s->fifolen) {
132
 
                if (s->revision < OMAP3_INTR_REV)
133
 
                    s->stat |= 1 << 3;                     /* RRDY */
134
 
                else {
135
 
                    if (s->fifolen > ((s->dma >> 8) & 0x3f)) /* RTRSH */
136
 
                s->stat |= 1 << 3;                              /* RRDY */
137
 
            else
138
 
                        s->stat |= 1 << 13;                /* RDR */
139
 
                }
140
 
            } else if (!s->count_cur && (s->control & 2))  /* STP */
141
 
                s->stat |= 1 << 2;                         /* ARDY */
142
 
        }
143
 
        if (!s->count_cur) {
144
 
            if ((s->control >> 1) & 1) {                        /* STP */
145
 
                i2c_end_transfer(s->bus);
146
 
                s->control &= ~0x0602;     /* MST | TRX | STP */
147
 
                s->count_cur = s->count;
148
 
            }
149
 
        }
150
 
    }
151
 
 
152
 
    s->stat |= (!ack) << 1;                                     /* NACK */
153
 
    if (!ack)
154
 
        s->control &= ~(1 << 1);                                /* STP */
155
 
}
156
 
 
157
 
static void omap_i2c_reset(DeviceState *dev)
158
 
{
159
 
    OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState,
160
 
                                  SYS_BUS_DEVICE(dev));
161
 
    s->mask = 0;
162
 
    s->stat = 0;
163
 
    s->dma = 0;
164
 
    s->count = 0;
165
 
    s->count_cur = 0;
166
 
    s->we = 0;
167
 
    s->sysc = 0;
168
 
    s->fifolen = 0;
169
 
    s->fifostart = 0;
170
 
    s->control = 0;
171
 
    s->own_addr[0] = 0;
172
 
    s->own_addr[1] = 0;
173
 
    s->own_addr[2] = 0;
174
 
    s->own_addr[3] = 0;
175
 
    s->slave_addr = 0;
176
 
    s->sblock = 0;
177
 
    s->divider = 0;
178
 
    s->times[0] = 0;
179
 
    s->times[1] = 0;
180
 
    s->test = 0;
181
 
    
182
 
    i2c_end_transfer(s->bus);
183
 
}
184
 
 
185
 
static uint32_t omap_i2c_read(void *opaque, hwaddr addr)
186
 
{
187
 
    OMAPI2CState *s = opaque;
188
 
    int offset = addr & OMAP_MPUI_REG_MASK;
189
 
    uint16_t ret;
190
 
 
191
 
    switch (offset) {
192
 
    case 0x00:  /* I2C_REV */
193
 
        return s->revision;                                     /* REV */
194
 
 
195
 
    case 0x04:  /* I2C_IE */
196
 
        return s->mask;
197
 
 
198
 
    case 0x08:  /* I2C_STAT */
199
 
        return s->stat | (i2c_bus_busy(s->bus) << 12);
200
 
 
201
 
    case 0x0c: /* I2C_IV / I2C_WE */
202
 
        if (s->revision >= OMAP3_INTR_REV)
203
 
            return s->we;
204
 
        if (s->revision >= OMAP2_INTR_REV)
205
 
            break;
206
 
        ret = ffs(s->stat & s->mask);
207
 
        if (ret)
208
 
            s->stat ^= 1 << (ret - 1);
209
 
        omap_i2c_interrupts_update(s);
210
 
        return ret;
211
 
 
212
 
    case 0x10:  /* I2C_SYSS */
213
 
        return (s->control >> 15) & 1;                          /* I2C_EN */
214
 
 
215
 
    case 0x14:  /* I2C_BUF */
216
 
        return s->dma;
217
 
 
218
 
    case 0x18:  /* I2C_CNT */
219
 
        return s->count_cur;                                    /* DCOUNT */
220
 
 
221
 
    case 0x1c:  /* I2C_DATA */
222
 
        ret = 0;
223
 
        if (s->fifolen) {
224
 
            if (s->revision < OMAP3_INTR_REV) {
225
 
                if (s->control & (1 << 14)) /* BE */
226
 
                    ret = (((uint16_t)s->fifo[s->fifostart]) << 8) 
227
 
                        | s->fifo[(s->fifostart + 1) & I2C_FIFO_SIZE_MASK];
228
 
                else
229
 
                    ret = (((uint16_t)s->fifo[(s->fifostart + 1) & I2C_FIFO_SIZE_MASK]) << 8) 
230
 
                        | s->fifo[s->fifostart];
231
 
                s->fifostart = (s->fifostart + 2) & I2C_FIFO_SIZE_MASK;
232
 
                if (s->fifolen == 1) {
233
 
                    s->stat |= 1 << 15;                                 /* SBD */
234
 
                    s->fifolen = 0;
235
 
                } else
236
 
                    s->fifolen -= 2;
237
 
                if (!s->fifolen) {
238
 
                    s->stat &= ~(1 << 3); /* RRDY */
239
 
                    s->stat |= 1 << 2;    /* ARDY */
240
 
                }
241
 
            } else {
242
 
                s->stat &= ~(1 << 7); /* AERR */
243
 
                ret = s->fifo[s->fifostart++];
244
 
                s->fifostart &= I2C_FIFO_SIZE_MASK;
245
 
                if (--s->fifolen) {
246
 
                    if (s->fifolen <= ((s->dma >> 8) & 0x3f)) {
247
 
                        s->stat &= ~(1 << 3);                           /* RRDY */
248
 
                        s->stat |= 1 << 13;   /* RDR */
249
 
                    }
250
 
                } else {
251
 
                    s->stat &= ~((1 << 3) | (1 << 13)); /* RRDY | RDR */
252
 
                    s->stat |= 1 << 2;                          /* ARDY */
253
 
                }
254
 
            }
255
 
            s->stat &= ~(1 << 11);                                      /* ROVR */
256
 
        } else if (s->revision >= OMAP3_INTR_REV)
257
 
            s->stat |= (1 << 7); /* AERR */
258
 
        omap_i2c_fifo_run(s);
259
 
        omap_i2c_interrupts_update(s);
260
 
        return ret;
261
 
 
262
 
    case 0x20:  /* I2C_SYSC */
263
 
        return s->sysc;
264
 
 
265
 
    case 0x24:  /* I2C_CON */
266
 
        return s->control;
267
 
 
268
 
    case 0x28: /* I2C_OA / I2C_OA0 */
269
 
        return s->own_addr[0];
270
 
 
271
 
    case 0x2c:  /* I2C_SA */
272
 
        return s->slave_addr;
273
 
 
274
 
    case 0x30:  /* I2C_PSC */
275
 
        return s->divider;
276
 
 
277
 
    case 0x34:  /* I2C_SCLL */
278
 
        return s->times[0];
279
 
 
280
 
    case 0x38:  /* I2C_SCLH */
281
 
        return s->times[1];
282
 
 
283
 
    case 0x3c:  /* I2C_SYSTEST */
284
 
        if (s->test & (1 << 15)) {                              /* ST_EN */
285
 
            s->test ^= 0xa;
286
 
            return s->test;
287
 
        }
288
 
        return s->test & ~0x300f;
289
 
    case 0x40: /* I2C_BUFSTAT */
290
 
        if (s->revision >= OMAP3_INTR_REV) {
291
 
            switch (s->fifosize) {
292
 
            case 8:  ret = 0x0000; break;
293
 
            case 16: ret = 0x4000; break;
294
 
            case 32: ret = 0x8000; break;
295
 
            case 64: ret = 0xc000; break;
296
 
            default: ret = 0x0000; break;
297
 
            }
298
 
            ret |= ((s->fifolen) & 0x3f) << 8;  /* RXSTAT */
299
 
            ret |= (s->count_cur) & 0x3f;       /* TXSTAT */
300
 
            return ret;
301
 
        }
302
 
        break;
303
 
    case 0x44: /* I2C_OA1 */
304
 
    case 0x48: /* I2C_OA2 */
305
 
    case 0x4c: /* I2C_OA3 */
306
 
        if (s->revision >= OMAP3_INTR_REV)
307
 
            return s->own_addr[(addr >> 2) & 3];
308
 
        break;
309
 
    case 0x50: /* I2C_ACTOA */
310
 
        if (s->revision >= OMAP3_INTR_REV)
311
 
            return 0; /* TODO: determine accessed slave own address */
312
 
        break;
313
 
    case 0x54: /* I2C_SBLOCK */
314
 
        if (s->revision >= OMAP3_INTR_REV)
315
 
            return s->sblock;
316
 
        break;
317
 
    default:
318
 
        break;
319
 
    }
320
 
 
321
 
    OMAP_BAD_REG(addr);
322
 
    return 0;
323
 
}
324
 
 
325
 
static void omap_i2c_write(void *opaque, hwaddr addr,
326
 
                uint32_t value)
327
 
{
328
 
    OMAPI2CState *s = opaque;
329
 
    int offset = addr & OMAP_MPUI_REG_MASK;
330
 
    int nack;
331
 
 
332
 
    switch (offset) {
333
 
    case 0x00:  /* I2C_REV */
334
 
    case 0x10:  /* I2C_SYSS */
335
 
    case 0x40: /* I2C_BUFSTAT */
336
 
    case 0x50: /* I2C_ACTOA */
337
 
        OMAP_RO_REG(addr);
338
 
        break;
339
 
    case 0x04:  /* I2C_IE */
340
 
        if (s->revision >= OMAP3_INTR_REV)
341
 
            s->mask = value & 0x63ff;
342
 
        else
343
 
            s->mask = value & (s->revision < OMAP2_INTR_REV ? 0x1f : 0x3f);
344
 
        omap_i2c_interrupts_update(s);
345
 
        break;
346
 
    case 0x08:  /* I2C_STAT */
347
 
        if (s->revision < OMAP2_INTR_REV)
348
 
            OMAP_RO_REG(addr);
349
 
        else {
350
 
            /* RRDY and XRDY are reset by hardware. (in all versions???) */
351
 
            s->stat &= ~(value & (s->revision < OMAP3_INTR_REV ? 0x27 : 0x63e7));
352
 
            omap_i2c_interrupts_update(s);
353
 
        }
354
 
        break;
355
 
 
356
 
    case 0x0c: /* I2C_IV / I2C_WE */
357
 
        if (s->revision < OMAP3_INTR_REV)
358
 
            OMAP_RO_REG(addr);
359
 
        else
360
 
            s->we = value & 0x636f;
361
 
        break;
362
 
 
363
 
    case 0x14:  /* I2C_BUF */
364
 
        if (s->revision < OMAP3_INTR_REV)
365
 
            s->dma = value & 0x8080;
366
 
        else {
367
 
            s->dma = value & 0xbfbf;
368
 
            if ((value & (1 << 14))    /* RXFIFO_CLR */
369
 
                || (value & (1 << 6))) /* TXFIFO_CLR */
370
 
                s->fifolen = 0;
371
 
        }
372
 
        if (value & (1 << 15))                                  /* RDMA_EN */
373
 
            s->mask &= ~(1 << 3);                               /* RRDY_IE */
374
 
        if (value & (1 << 7))                                   /* XDMA_EN */
375
 
            s->mask &= ~(1 << 4);                               /* XRDY_IE */
376
 
        break;
377
 
 
378
 
    case 0x18:  /* I2C_CNT */
379
 
        s->count = value;                                       /* DCOUNT */
380
 
        break;
381
 
 
382
 
    case 0x1c:  /* I2C_DATA */
383
 
        if (s->revision < OMAP3_INTR_REV) {
384
 
            if (s->fifolen > 2) {
385
 
                /* XXX: remote access (qualifier) error - what's that?  */
386
 
                break;
387
 
            }
388
 
            if (s->control & (1 << 14)) {                               /* BE */
389
 
                s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
390
 
                    (uint8_t)((value >> 8) & 0xff);
391
 
                s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
392
 
                    (uint8_t)(value & 0xff);
393
 
            } else {
394
 
                s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
395
 
                    (uint8_t)(value & 0xff);
396
 
                s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
397
 
                    (uint8_t)((value >> 8) & 0xff);
398
 
            }
399
 
        } else {
400
 
            if (s->fifolen < s->fifosize) {
401
 
                s->stat &= ~(1 << 7); /* AERR */
402
 
                s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
403
 
                    (uint8_t)(value & 0xff);
404
 
            } else
405
 
                s->stat |= (1 << 7); /* AERR */
406
 
        }
407
 
        s->stat &= ~(1 << 10);                                  /* XUDF */
408
 
        omap_i2c_fifo_run(s);
409
 
        omap_i2c_interrupts_update(s);
410
 
        break;
411
 
 
412
 
    case 0x20:  /* I2C_SYSC */
413
 
        if (s->revision < OMAP2_INTR_REV) {
414
 
            OMAP_BAD_REG(addr);
415
 
            break;
416
 
        }
417
 
 
418
 
        if (value & 2)
419
 
            omap_i2c_reset(&s->busdev.qdev);
420
 
        else if (s->revision >= OMAP3_INTR_REV)
421
 
            s->sysc = value & 0x031d;
422
 
        break;
423
 
 
424
 
    case 0x24:  /* I2C_CON */
425
 
        s->control = value & (s->revision < OMAP3_INTR_REV ? 0xcf87 : 0xbff3);
426
 
        if (~value & (1 << 15)) {                               /* I2C_EN */
427
 
            if (s->revision < OMAP2_INTR_REV)
428
 
                omap_i2c_reset(&s->busdev.qdev);
429
 
            break;
430
 
        }
431
 
        if (s->revision >= OMAP3_INTR_REV && ((value >> 12) & 3) > 1) { /* OPMODE */
432
 
            fprintf(stderr,
433
 
                    "%s: only FS and HS modes are supported\n",
434
 
                    __FUNCTION__);
435
 
            break;
436
 
        }
437
 
        if ((value & (1 << 10))) { /* MST */
438
 
            if (value & 1) { /* STT */
439
 
                nack = !!i2c_start_transfer(s->bus, s->slave_addr, /*SA*/
440
 
                                            (~value >> 9) & 1);                 /* TRX */
441
 
                s->stat |= nack << 1;                           /* NACK */
442
 
                s->control &= ~(1 << 0);                                /* STT */
443
 
                s->fifolen = 0;
444
 
                if (nack)
445
 
                    s->control &= ~(1 << 1);                    /* STP */
446
 
                else {
447
 
                    s->count_cur = s->count;
448
 
                    omap_i2c_fifo_run(s);
449
 
                }
450
 
                omap_i2c_interrupts_update(s);
451
 
            } else if (value & 2) { /* STP, but not STT */
452
 
                i2c_end_transfer(s->bus);
453
 
                s->control &= ~0x0602;     /* MST | TRX | STP */
454
 
                s->count_cur = s->count;
455
 
            }
456
 
        }
457
 
        break;
458
 
    case 0x28: /* I2C_OA / I2C_OA0 */
459
 
        s->own_addr[0] = value & (s->revision < OMAP3_INTR_REV
460
 
                                  ? 0x3ff : 0xe3ff);
461
 
        /*i2c_set_slave_address(&s->slave[0],
462
 
          value & (s->revision >= OMAP3_INTR_REV
463
 
          && (s->control & 0x80)
464
 
          ? 0x3ff: 0x7f));*/
465
 
        break;
466
 
 
467
 
    case 0x2c:  /* I2C_SA */
468
 
        s->slave_addr = value & 0x3ff;
469
 
        break;
470
 
 
471
 
    case 0x30:  /* I2C_PSC */
472
 
        s->divider = value;
473
 
        break;
474
 
 
475
 
    case 0x34:  /* I2C_SCLL */
476
 
        s->times[0] = value & (s->revision < OMAP3_INTR_REV ? 0xff : 0xffff);
477
 
        break;
478
 
 
479
 
    case 0x38:  /* I2C_SCLH */
480
 
        s->times[1] = value & (s->revision < OMAP3_INTR_REV ? 0xff : 0xffff);
481
 
        break;
482
 
 
483
 
    case 0x3c:  /* I2C_SYSTEST */
484
 
        value &= s->revision < OMAP3_INTR_REV ? 0xf805 : 0xf815;
485
 
        if ((value & (1 << 15))) { /* ST_EN */
486
 
            fprintf(stderr, "%s: System Test not supported\n",
487
 
                    __FUNCTION__);
488
 
            s->test = (s->test & 0x0a) | value;
489
 
        } else
490
 
            s->test = (s->test & 0x1f) | (value & 0xf800);
491
 
        if (value & (1 << 11))                                  /* SBB */
492
 
            if (s->revision >= OMAP2_INTR_REV) {
493
 
                s->stat |= 0x3f;
494
 
                if (s->revision >= OMAP3_INTR_REV)
495
 
                    s->stat |= 0x600;
496
 
                omap_i2c_interrupts_update(s);
497
 
            }
498
 
        break;
499
 
 
500
 
    case 0x44: /* I2C_OA1 */
501
 
    case 0x48: /* I2C_OA2 */
502
 
    case 0x4c: /* I2C_OA3 */
503
 
        if (s->revision < OMAP3_INTR_REV)
504
 
            OMAP_BAD_REG(addr);
505
 
        else {
506
 
            addr = (addr >> 2) & 3;
507
 
            s->own_addr[addr] = value & 0x3ff;
508
 
            /*i2c_set_slave_address(&s->slave[addr],
509
 
              value & ((s->control & (0x80 >> addr))
510
 
              ? 0x3ff: 0x7f));*/
511
 
        }
512
 
        break;
513
 
    case 0x54: /* I2C_SBLOCK */
514
 
        if (s->revision < OMAP3_INTR_REV)
515
 
            OMAP_BAD_REG(addr);
516
 
        else {
517
 
            s->sblock = value & 0x0f;
518
 
        }
519
 
        break;
520
 
    default:
521
 
        OMAP_BAD_REG(addr);
522
 
            break;
523
 
    }
524
 
}
525
 
 
526
 
static void omap_i2c_writeb(void *opaque, hwaddr addr,
527
 
                uint32_t value)
528
 
{
529
 
    OMAPI2CState *s = opaque;
530
 
    int offset = addr & OMAP_MPUI_REG_MASK;
531
 
 
532
 
    switch (offset) {
533
 
    case 0x1c:  /* I2C_DATA */
534
 
        if (s->revision < OMAP3_INTR_REV && s->fifolen > 2) {
535
 
            /* XXX: remote access (qualifier) error - what's that?  */
536
 
            break;
537
 
        }
538
 
        if (s->fifolen < s->fifosize) {
539
 
            s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
540
 
                (uint8_t)(value & 0xff);
541
 
            if (s->revision >= OMAP3_INTR_REV)
542
 
                s->stat &= ~(1 << 7); /* AERR */
543
 
            s->stat &= ~(1 << 10);                                      /* XUDF */
544
 
            omap_i2c_fifo_run(s);
545
 
        } else if (s->revision >= OMAP3_INTR_REV)
546
 
            s->stat |= (1 << 7);      /* AERR */
547
 
        omap_i2c_interrupts_update(s);
548
 
        break;
549
 
    default:
550
 
        OMAP_BAD_REG(addr);
551
 
            break;
552
 
    }
553
 
}
554
 
 
555
 
static const MemoryRegionOps omap_i2c_ops = {
556
 
    .old_mmio = {
557
 
        .read = {
558
 
            omap_badwidth_read16,
559
 
            omap_i2c_read,
560
 
            omap_badwidth_read16,
561
 
        },
562
 
        .write = {
563
 
            omap_i2c_writeb, /* Only the last fifo write can be 8 bit.  */
564
 
            omap_i2c_write,
565
 
            omap_badwidth_write16,
566
 
        },
567
 
    },
568
 
    .endianness = DEVICE_NATIVE_ENDIAN,
569
 
};
570
 
 
571
 
static int omap_i2c_init(SysBusDevice *dev)
572
 
{
573
 
    OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, dev);
574
 
 
575
 
    if (!s->fclk) {
576
 
        hw_error("omap_i2c: fclk not connected\n");
577
 
    }
578
 
    if (s->revision >= OMAP2_INTR_REV && !s->iclk) {
579
 
        /* Note that OMAP1 doesn't have a separate interface clock */
580
 
        hw_error("omap_i2c: iclk not connected\n");
581
 
    }
582
 
    sysbus_init_irq(dev, &s->irq);
583
 
    sysbus_init_irq(dev, &s->drq[0]);
584
 
    sysbus_init_irq(dev, &s->drq[1]);
585
 
    memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap.i2c",
586
 
                          (s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
587
 
    sysbus_init_mmio(dev, &s->iomem);
588
 
    s->bus = i2c_init_bus(&dev->qdev, NULL);
589
 
    return 0;
590
 
}
591
 
 
592
 
static Property omap_i2c_properties[] = {
593
 
    DEFINE_PROP_UINT8("revision", OMAPI2CState, revision, 0),
594
 
    DEFINE_PROP_UINT32("fifo-size", OMAPI2CState, fifosize, 4),
595
 
    DEFINE_PROP_PTR("iclk", OMAPI2CState, iclk),
596
 
    DEFINE_PROP_PTR("fclk", OMAPI2CState, fclk),
597
 
    DEFINE_PROP_END_OF_LIST(),
598
 
};
599
 
 
600
 
static void omap_i2c_class_init(ObjectClass *klass, void *data)
601
 
{
602
 
    DeviceClass *dc = DEVICE_CLASS(klass);
603
 
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
604
 
    k->init = omap_i2c_init;
605
 
    dc->props = omap_i2c_properties;
606
 
    dc->reset = omap_i2c_reset;
607
 
}
608
 
 
609
 
static const TypeInfo omap_i2c_info = {
610
 
    .name = "omap_i2c",
611
 
    .parent = TYPE_SYS_BUS_DEVICE,
612
 
    .instance_size = sizeof(OMAPI2CState),
613
 
    .class_init = omap_i2c_class_init,
614
 
};
615
 
 
616
 
static void omap_i2c_register_types(void)
617
 
{
618
 
    type_register_static(&omap_i2c_info);
619
 
}
620
 
 
621
 
i2c_bus *omap_i2c_bus(DeviceState *omap_i2c)
622
 
{
623
 
    OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, SYS_BUS_DEVICE(omap_i2c));
624
 
    return s->bus;
625
 
}
626
 
 
627
 
type_init(omap_i2c_register_types)