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

« back to all changes in this revision

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