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

« back to all changes in this revision

Viewing changes to .pc/linaro-patches-1.5.0/0040-serial-omap_uart-Add-support-for-fifo-level-regs.patch/hw/char/omap_uart.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 processors UART emulation.
3
 
 *
4
 
 * Copyright (C) 2006-2008 Andrzej Zaborowski  <balrog@zabor.org>
5
 
 * Copyright (C) 2007-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 or
10
 
 * (at your option) version 3 of the License.
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 "sysemu/char.h"
21
 
#include "hw/hw.h"
22
 
#include "hw/arm/omap.h"
23
 
#include "hw/char/serial.h"
24
 
#include "exec/address-spaces.h"
25
 
#include "hw/sysbus.h"
26
 
 
27
 
/* The OMAP UART functionality is similar to the TI16C752; it is
28
 
 * an enhanced version of the 16550A and we piggy-back on the 16550
29
 
 * model.
30
 
 *
31
 
 * Currently unmodelled functionality:
32
 
 *  + We should have a 64 byte FIFO but QEMU's SerialState emulation
33
 
 *    always uses a 16 byte FIFO
34
 
 *  + DMA
35
 
 *  + interrupts based on TCR/TLR values
36
 
 *  + XON/XOFF flow control
37
 
 *  + UASR auto-baudrate-detection
38
 
 */
39
 
 
40
 
struct omap_uart_s {
41
 
    SysBusDevice busdev;
42
 
    MemoryRegion iomem;
43
 
    CharDriverState *chr;
44
 
    SerialState *serial; /* TODO */
45
 
    const MemoryRegionOps *serial_ops;
46
 
    uint32_t mmio_size;
47
 
    uint32_t baudrate;
48
 
    uint32_t revision;
49
 
    qemu_irq tx_drq;
50
 
    qemu_irq rx_drq;
51
 
 
52
 
    /* Register access mode, which affects what registers you see */
53
 
    enum {
54
 
        regs_operational,
55
 
        regs_config_a,
56
 
        regs_config_b
57
 
    } access_mode;
58
 
 
59
 
    uint8_t eblr;
60
 
    uint8_t syscontrol;
61
 
    uint8_t wkup;
62
 
    uint8_t cfps;
63
 
    uint8_t mdr[2];
64
 
    uint8_t scr;
65
 
    uint8_t clksel;
66
 
    uint8_t blr;
67
 
    uint8_t acreg;
68
 
 
69
 
    uint8_t mcr_cache;
70
 
    uint8_t efr;
71
 
    uint8_t tcr;
72
 
    uint8_t tlr;
73
 
    uint8_t xon[2], xoff[2];
74
 
};
75
 
 
76
 
static int tcr_tlr_mode(struct omap_uart_s *s)
77
 
{
78
 
    /* Return true if registers 0x18 and 0x1c are TCR/TLR
79
 
     * (as opposed to SPR/MSR/XOFF)
80
 
     */
81
 
    return (s->efr & 0x10) && (s->mcr_cache & 0x40);
82
 
}
83
 
 
84
 
static void omap_uart_reset(DeviceState *qdev)
85
 
{
86
 
    struct omap_uart_s *s = FROM_SYSBUS(struct omap_uart_s,
87
 
                                        SYS_BUS_DEVICE(qdev));
88
 
    s->eblr = 0x00;
89
 
    s->syscontrol = 0;
90
 
    s->wkup = 0x3f;
91
 
    s->cfps = 0x69;
92
 
    s->clksel = 0;
93
 
    s->blr = 0x40;
94
 
    s->acreg = 0;
95
 
    s->access_mode = regs_operational;
96
 
 
97
 
    s->mcr_cache = 0;
98
 
    s->tcr = 0x0f;
99
 
    s->tlr = 0;
100
 
    s->efr = 0;
101
 
    s->xon[0] = s->xon[1] = 0;
102
 
    s->xoff[0] = s->xoff[1] = 0;
103
 
}
104
 
 
105
 
static uint64_t omap_uart_read(void *opaque, hwaddr addr,
106
 
                               unsigned size)
107
 
{
108
 
    struct omap_uart_s *s = (struct omap_uart_s *) opaque;
109
 
 
110
 
    switch (addr) {
111
 
    case 0x00:
112
 
    case 0x04:
113
 
    case 0x0c:
114
 
        return s->serial_ops->read(s->serial, addr, size);
115
 
    case 0x08:
116
 
        if (s->access_mode == regs_config_b) {
117
 
            return s->efr;
118
 
        }
119
 
        return s->serial_ops->read(s->serial, addr, size);
120
 
    case 0x10:
121
 
    case 0x14:
122
 
        if (s->access_mode == regs_config_b) {
123
 
            return s->xon[(addr & 7) >> 2];
124
 
        } else if (addr == 0x10) {
125
 
            /* MCR. Bits 5 and 6 are handled by us, the rest by
126
 
             * the underlying serial implementation.
127
 
             */
128
 
            return s->serial_ops->read(s->serial, addr, size) | s->mcr_cache;
129
 
        }
130
 
        return s->serial_ops->read(s->serial, addr, size);
131
 
    case 0x18:
132
 
    case 0x1c:
133
 
        if (tcr_tlr_mode(s)) {
134
 
            return (addr == 0x18) ? s->tcr : s->tlr;
135
 
        }
136
 
        if (s->access_mode == regs_config_b) {
137
 
            return s->xoff[(addr & 7) >> 2];
138
 
        }
139
 
        return s->serial_ops->read(s->serial, addr, size);
140
 
    case 0x20:  /* MDR1 */
141
 
        return s->mdr[0];
142
 
    case 0x24:  /* MDR2 */
143
 
        return s->mdr[1];
144
 
    case 0x28: /* SFLSR */
145
 
        return 0;
146
 
    case 0x2c: /* RESUME */
147
 
        return 0;
148
 
    case 0x30: /* SFREGL */
149
 
        return 0;
150
 
    case 0x34: /* SFREGH */
151
 
        return 0;
152
 
    case 0x38: /* UASR/BLR */
153
 
        if (s->access_mode != regs_operational) {
154
 
            return 0; /* FIXME: return correct autodetect value */
155
 
        }
156
 
        return s->blr;
157
 
    case 0x3c: /* ACREG */
158
 
        return (s->access_mode != regs_operational) ? 0 : s->acreg;
159
 
    case 0x40:  /* SCR */
160
 
        return s->scr;
161
 
    case 0x44:  /* SSR */
162
 
        return 0x0;
163
 
    case 0x48:  /* EBLR (OMAP2) */
164
 
        return s->eblr;
165
 
    case 0x4C:  /* OSC_12M_SEL (OMAP1) */
166
 
        return s->clksel;
167
 
    case 0x50:  /* MVR */
168
 
        return s->revision;
169
 
    case 0x54:  /* SYSC (OMAP2) */
170
 
        return s->syscontrol;
171
 
    case 0x58:  /* SYSS (OMAP2) */
172
 
        return 1;
173
 
    case 0x5c:  /* WER (OMAP2) */
174
 
        return s->wkup;
175
 
    case 0x60:  /* CFPS (OMAP2) */
176
 
        return s->cfps;
177
 
    }
178
 
 
179
 
    OMAP_BAD_REG(addr);
180
 
    return 0;
181
 
}
182
 
 
183
 
static void omap_uart_write(void *opaque, hwaddr addr,
184
 
                            uint64_t value, unsigned size)
185
 
{
186
 
    struct omap_uart_s *s = (struct omap_uart_s *) opaque;
187
 
 
188
 
    switch (addr) {
189
 
    case 0x00:
190
 
    case 0x04:
191
 
        s->serial_ops->write(s->serial, addr, value, size);
192
 
        break;
193
 
    case 0x08:
194
 
        if (s->access_mode == regs_config_b) {
195
 
            s->efr = value;
196
 
        } else {
197
 
            s->serial_ops->write(s->serial, addr, value, size);
198
 
        }
199
 
        break;
200
 
    case 0x0c:
201
 
        if ((value & 0xff) == 0xbf) {
202
 
            s->access_mode = regs_config_b;
203
 
        } else if (value & 0x80) {
204
 
            s->access_mode = regs_config_a;
205
 
        } else {
206
 
            s->access_mode = regs_operational;
207
 
        }
208
 
        s->serial_ops->write(s->serial, addr, value, size);
209
 
        break;
210
 
    case 0x10:
211
 
    case 0x14:
212
 
        if (s->access_mode == regs_config_b) {
213
 
            s->xon[(addr & 7) >> 2] = value;
214
 
        } else {
215
 
            if (addr == 0x10) {
216
 
                /* Bits 5 and 6 are handled at this level; they can
217
 
                 * only be written if EFR_REG:ENHANCED_EN is set.
218
 
                 */
219
 
                if (s->efr & 0x10) {
220
 
                    s->mcr_cache = value & 0x60;
221
 
                }
222
 
            }
223
 
            s->serial_ops->write(s->serial, addr, value, size);
224
 
        }
225
 
        break;
226
 
    case 0x18:
227
 
    case 0x1c:
228
 
        if (tcr_tlr_mode(s)) {
229
 
            if (addr == 0x18) {
230
 
                s->tcr = value & 0xff;
231
 
            } else {
232
 
                s->tlr = value & 0xff;
233
 
            }
234
 
        } else if (s->access_mode == regs_config_b) {
235
 
            s->xoff[(addr & 7) >> 2] = value;
236
 
        } else {
237
 
            s->serial_ops->write(s->serial, addr, value, size);
238
 
        }
239
 
        break;
240
 
    case 0x20:  /* MDR1 */
241
 
        s->mdr[0] = value & 0x7f;
242
 
        break;
243
 
    case 0x24:  /* MDR2 */
244
 
        s->mdr[1] = value & 0xff;
245
 
        break;
246
 
    case 0x28: /* TXFLL */
247
 
    case 0x2c: /* TXFLH */
248
 
    case 0x30: /* RXFLL */
249
 
    case 0x34: /* RXFLH */
250
 
        /* ignored */
251
 
        break;
252
 
    case 0x38: /* BLR */
253
 
        if (s->access_mode == regs_operational) {
254
 
            s->blr = value & 0xc0;
255
 
        }
256
 
        break;
257
 
    case 0x3c: /* ACREG */
258
 
        if (s->access_mode == regs_operational) {
259
 
            s->acreg = value & 0xff;
260
 
        }
261
 
        break;
262
 
    case 0x40:  /* SCR */
263
 
        s->scr = value & 0xff;
264
 
        break;
265
 
    case 0x44:  /* SSR */
266
 
        OMAP_RO_REG(addr);
267
 
        break;
268
 
    case 0x48:  /* EBLR (OMAP2) */
269
 
        s->eblr = value & 0xff;
270
 
        break;
271
 
    case 0x4C:  /* OSC_12M_SEL (OMAP1) */
272
 
        s->clksel = value & 1;
273
 
        break;
274
 
    case 0x50:  /* MVR */
275
 
        OMAP_RO_REG(addr);
276
 
        break;
277
 
    case 0x54:  /* SYSC (OMAP2) */
278
 
        s->syscontrol = value & 0x1d;
279
 
        if (value & 2) {
280
 
            /* TODO: reset s->serial also. */
281
 
            omap_uart_reset(&s->busdev.qdev);
282
 
        }
283
 
        break;
284
 
    case 0x58:  /* SYSS (OMAP2) */
285
 
        OMAP_RO_REG(addr);
286
 
        break;
287
 
    case 0x5c:  /* WER (OMAP2) */
288
 
        s->wkup = value & 0x7f;
289
 
        break;
290
 
    case 0x60:  /* CFPS (OMAP2) */
291
 
        s->cfps = value & 0xff;
292
 
        break;
293
 
    default:
294
 
        OMAP_BAD_REG(addr);
295
 
    }
296
 
}
297
 
 
298
 
static const MemoryRegionOps omap_uart_ops = {
299
 
    .read = omap_uart_read,
300
 
    .write = omap_uart_write,
301
 
    .endianness = DEVICE_NATIVE_ENDIAN,
302
 
};
303
 
 
304
 
static int omap_uart_init(SysBusDevice *busdev)
305
 
{
306
 
    struct omap_uart_s *s = FROM_SYSBUS(struct omap_uart_s, busdev);
307
 
    if (!s->chr) {
308
 
        s->chr = qemu_chr_new(busdev->qdev.id, "null", NULL);
309
 
    }
310
 
    /* TODO: DMA support. Current 16550A emulation does not emulate DMA mode
311
 
     * transfers via TXRDY/RXRDY pins. We create DMA irq lines here for
312
 
     * future use nevertheless. */
313
 
    /* Nasty hackery because trying to extend an existing device is
314
 
     * not really supported, and the serial driver isn't even qdev.
315
 
     */
316
 
    s->serial = serial_mm_init(NULL, 0, 2, NULL, s->baudrate, s->chr,
317
 
                               DEVICE_NATIVE_ENDIAN);
318
 
    s->serial_ops = serial_get_memops(DEVICE_NATIVE_ENDIAN);
319
 
    sysbus_init_irq(busdev, serial_get_irq(s->serial));
320
 
    sysbus_init_irq(busdev, &s->tx_drq);
321
 
    sysbus_init_irq(busdev, &s->rx_drq);
322
 
    memory_region_init_io(&s->iomem, &omap_uart_ops, s, "omap_uart",
323
 
                          s->mmio_size);
324
 
    sysbus_init_mmio(busdev, &s->iomem);
325
 
    return 0;
326
 
}
327
 
 
328
 
static Property omap_uart_properties[] = {
329
 
    DEFINE_PROP_UINT32("revision", struct omap_uart_s, revision, 0x30),
330
 
    DEFINE_PROP_UINT32("mmio_size", struct omap_uart_s, mmio_size, 0x400),
331
 
    DEFINE_PROP_UINT32("baudrate", struct omap_uart_s, baudrate, 0),
332
 
    DEFINE_PROP_CHR("chardev", struct omap_uart_s, chr),
333
 
    DEFINE_PROP_END_OF_LIST()
334
 
};
335
 
 
336
 
static void omap_uart_class_init(ObjectClass *klass, void *data)
337
 
{
338
 
    DeviceClass *dc = DEVICE_CLASS(klass);
339
 
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
340
 
    k->init = omap_uart_init;
341
 
    dc->props = omap_uart_properties;
342
 
    dc->reset = omap_uart_reset;
343
 
}
344
 
 
345
 
static TypeInfo omap_uart_info = {
346
 
    .name = "omap_uart",
347
 
    .parent = TYPE_SYS_BUS_DEVICE,
348
 
    .instance_size = sizeof(struct omap_uart_s),
349
 
    .class_init = omap_uart_class_init,
350
 
};
351
 
 
352
 
static void omap_uart_register_types(void)
353
 
{
354
 
    type_register_static(&omap_uart_info);
355
 
}
356
 
 
357
 
void omap_uart_attach(DeviceState *qdev, CharDriverState *chr,
358
 
                      const char *label)
359
 
{
360
 
    struct omap_uart_s *s = FROM_SYSBUS(struct omap_uart_s,
361
 
                                        SYS_BUS_DEVICE(qdev));
362
 
    s->chr = chr ?: qemu_chr_new(label, "null", NULL);
363
 
    serial_change_char_driver(s->serial, s->chr);
364
 
}
365
 
 
366
 
type_init(omap_uart_register_types)