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

« back to all changes in this revision

Viewing changes to debian/patches/linaro/0033-omap_uart-updates.patch

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2014-02-04 12:13:08 UTC
  • mfrom: (10.1.45 sid)
  • Revision ID: package-import@ubuntu.com-20140204121308-1xq92lrfs75agw2g
Tags: 1.7.0+dfsg-3ubuntu1~ppa1
* Merge 1.7.0+dfsg-3 from debian.  Remaining changes:
  - debian/patches/ubuntu:
    * expose-vmx_qemu64cpu.patch
    * linaro (omap3) and arm64 patches
    * ubuntu/target-ppc-add-stubs-for-kvm-breakpoints: fix FTBFS
      on ppc
    * ubuntu/CVE-2013-4377.patch: fix denial of service via virtio
  - debian/qemu-system-x86.modprobe: set kvm_intel nested=1 options
  - debian/control:
    * add arm64 to Architectures
    * add qemu-common and qemu-system-aarch64 packages
  - debian/qemu-system-common.install: add debian/tmp/usr/lib
  - debian/qemu-system-common.preinst: add kvm group
  - debian/qemu-system-common.postinst: remove acl placed by udev,
    and add udevadm trigger.
  - qemu-system-x86.links: add eepro100.rom, remove pxe-virtio,
    pxe-e1000 and pxe-rtl8139.
  - add qemu-system-x86.qemu-kvm.upstart and .default
  - qemu-user-static.postinst-in: remove arm64 binfmt
  - debian/rules:
    * allow parallel build
    * add aarch64 to system_targets and sys_systems
    * add qemu-kvm-spice links
    * install qemu-system-x86.modprobe
  - add debian/qemu-system-common.links for OVMF.fd link
* Remove kvm-img, kvm-nbd, kvm-ifup and kvm-ifdown symlinks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
From a557c2070471841eabdf2f9a4c75068206a0ea68 Mon Sep 17 00:00:00 2001
2
 
From: =?UTF-8?q?Juha=20Riihim=C3=A4ki?= <juha.riihimaki@nokia.com>
3
 
Date: Mon, 18 Feb 2013 16:58:29 +0000
4
 
Subject: [PATCH 33/70] omap_uart updates
5
 
MIME-Version: 1.0
6
 
Content-Type: text/plain; charset=UTF-8
7
 
Content-Transfer-Encoding: 8bit
8
 
 
9
 
- convert to qdev
10
 
- add missing registers
11
 
 
12
 
FIXME this is badly broken due to serial init changing -- PMM
13
 
 
14
 
Signed-off-by: Juha Riihimäki <juha.riihimaki@nokia.com>
15
 
---
16
 
 hw/arm/omap1.c           |  64 ++++++-----
17
 
 hw/arm/omap2.c           |  73 +++++++------
18
 
 hw/char/omap_uart.c      | 275 +++++++++++++++++++++++++++++++++++++----------
19
 
 hw/char/serial.c         |  28 ++++-
20
 
 include/hw/arm/omap.h    |  15 +--
21
 
 include/hw/char/serial.h |   3 +
22
 
 6 files changed, 333 insertions(+), 125 deletions(-)
23
 
 
24
 
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
25
 
index 47511d2..1500841 100644
26
 
--- a/hw/arm/omap1.c
27
 
+++ b/hw/arm/omap1.c
28
 
@@ -3692,9 +3692,6 @@ static void omap1_mpu_reset(void *opaque)
29
 
     omap_dpll_reset(mpu->dpll[0]);
30
 
     omap_dpll_reset(mpu->dpll[1]);
31
 
     omap_dpll_reset(mpu->dpll[2]);
32
 
-    omap_uart_reset(mpu->uart[0]);
33
 
-    omap_uart_reset(mpu->uart[1]);
34
 
-    omap_uart_reset(mpu->uart[2]);
35
 
     omap_mmc_reset(mpu->mmc);
36
 
     omap_mpuio_reset(mpu->mpuio);
37
 
     omap_uwire_reset(mpu->microwire);
38
 
@@ -3938,27 +3935,46 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
39
 
 
40
 
     omap_tcmi_init(system_memory, 0xfffecc00, s);
41
 
 
42
 
-    s->uart[0] = omap_uart_init(0xfffb0000,
43
 
-                                qdev_get_gpio_in(s->ih[1], OMAP_INT_UART1),
44
 
-                    omap_findclk(s, "uart1_ck"),
45
 
-                    omap_findclk(s, "uart1_ck"),
46
 
-                    s->drq[OMAP_DMA_UART1_TX], s->drq[OMAP_DMA_UART1_RX],
47
 
-                    "uart1",
48
 
-                    serial_hds[0]);
49
 
-    s->uart[1] = omap_uart_init(0xfffb0800,
50
 
-                                qdev_get_gpio_in(s->ih[1], OMAP_INT_UART2),
51
 
-                    omap_findclk(s, "uart2_ck"),
52
 
-                    omap_findclk(s, "uart2_ck"),
53
 
-                    s->drq[OMAP_DMA_UART2_TX], s->drq[OMAP_DMA_UART2_RX],
54
 
-                    "uart2",
55
 
-                    serial_hds[0] ? serial_hds[1] : NULL);
56
 
-    s->uart[2] = omap_uart_init(0xfffb9800,
57
 
-                                qdev_get_gpio_in(s->ih[0], OMAP_INT_UART3),
58
 
-                    omap_findclk(s, "uart3_ck"),
59
 
-                    omap_findclk(s, "uart3_ck"),
60
 
-                    s->drq[OMAP_DMA_UART3_TX], s->drq[OMAP_DMA_UART3_RX],
61
 
-                    "uart3",
62
 
-                    serial_hds[0] && serial_hds[1] ? serial_hds[2] : NULL);
63
 
+    s->uart[0] = qdev_create(NULL, "omap_uart");
64
 
+    s->uart[0]->id = "uart1";
65
 
+    qdev_prop_set_uint32(s->uart[0], "mmio_size", 0x400);
66
 
+    qdev_prop_set_uint32(s->uart[0], "baudrate",
67
 
+                         omap_clk_getrate(omap_findclk(s, "uart1_ck")) / 16);
68
 
+    qdev_prop_set_chr(s->uart[0], "chardev", serial_hds[0]);
69
 
+    qdev_init_nofail(s->uart[0]);
70
 
+    busdev = SYS_BUS_DEVICE(s->uart[0]);
71
 
+    sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(s->ih[1], OMAP_INT_UART1));
72
 
+    sysbus_connect_irq(busdev, 1, s->drq[OMAP_DMA_UART1_TX]);
73
 
+    sysbus_connect_irq(busdev, 2, s->drq[OMAP_DMA_UART1_RX]);
74
 
+    sysbus_mmio_map(busdev, 0, 0xfffb0000);
75
 
+
76
 
+    s->uart[1] = qdev_create(NULL, "omap_uart");
77
 
+    s->uart[1]->id = "uart2";
78
 
+    qdev_prop_set_uint32(s->uart[1], "mmio_size", 0x400);
79
 
+    qdev_prop_set_uint32(s->uart[1], "baudrate",
80
 
+                         omap_clk_getrate(omap_findclk(s, "uart2_ck")) / 16);
81
 
+    qdev_prop_set_chr(s->uart[1], "chardev",
82
 
+                      serial_hds[0] ? serial_hds[1] : NULL);
83
 
+    qdev_init_nofail(s->uart[1]);
84
 
+    busdev = SYS_BUS_DEVICE(s->uart[1]);
85
 
+    sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(s->ih[1], OMAP_INT_UART2));
86
 
+    sysbus_connect_irq(busdev, 1, s->drq[OMAP_DMA_UART2_TX]);
87
 
+    sysbus_connect_irq(busdev, 2, s->drq[OMAP_DMA_UART2_RX]);
88
 
+    sysbus_mmio_map(busdev, 0, 0xfffb0800);
89
 
+
90
 
+    s->uart[2] = qdev_create(NULL, "omap_uart");
91
 
+    s->uart[2]->id = "uart3";
92
 
+    qdev_prop_set_uint32(s->uart[2], "mmio_size", 0x400);
93
 
+    qdev_prop_set_uint32(s->uart[2], "baudrate",
94
 
+                         omap_clk_getrate(omap_findclk(s, "uart3_ck")) / 16);
95
 
+    qdev_prop_set_chr(s->uart[2], "chardev",
96
 
+                      serial_hds[0] && serial_hds[1] ? serial_hds[2] : NULL);
97
 
+    qdev_init_nofail(s->uart[2]);
98
 
+    busdev = SYS_BUS_DEVICE(s->uart[2]);
99
 
+    sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(s->ih[0], OMAP_INT_UART3));
100
 
+    sysbus_connect_irq(busdev, 1, s->drq[OMAP_DMA_UART3_TX]);
101
 
+    sysbus_connect_irq(busdev, 2, s->drq[OMAP_DMA_UART3_RX]);
102
 
+    sysbus_mmio_map(busdev, 0, 0xfffb9800);
103
 
 
104
 
     s->dpll[0] = omap_dpll_init(system_memory, 0xfffecf00,
105
 
                                 omap_findclk(s, "dpll1"));
106
 
diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
107
 
index f867ff2..667abb9 100644
108
 
--- a/hw/arm/omap2.c
109
 
+++ b/hw/arm/omap2.c
110
 
@@ -2216,9 +2216,6 @@ static void omap2_mpu_reset(void *opaque)
111
 
     omap_sdrc_reset(mpu->sdrc);
112
 
     omap_gpmc_reset(mpu->gpmc);
113
 
     omap_dss_reset(mpu->dss);
114
 
-    omap_uart_reset(mpu->uart[0]);
115
 
-    omap_uart_reset(mpu->uart[1]);
116
 
-    omap_uart_reset(mpu->uart[2]);
117
 
     omap_mmc_reset(mpu->mmc);
118
 
     cpu_reset(CPU(mpu->cpu));
119
 
 }
120
 
@@ -2308,33 +2305,49 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
121
 
     soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sram),
122
 
                          OMAP2_SRAM_BASE, s->sram_size);
123
 
 
124
 
-    s->uart[0] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 19),
125
 
-                                 qdev_get_gpio_in(s->ih[0],
126
 
-                                                  OMAP_INT_24XX_UART1_IRQ),
127
 
-                    omap_findclk(s, "uart1_fclk"),
128
 
-                    omap_findclk(s, "uart1_iclk"),
129
 
-                    s->drq[OMAP24XX_DMA_UART1_TX],
130
 
-                    s->drq[OMAP24XX_DMA_UART1_RX],
131
 
-                    "uart1",
132
 
-                    serial_hds[0]);
133
 
-    s->uart[1] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 20),
134
 
-                                 qdev_get_gpio_in(s->ih[0],
135
 
-                                                  OMAP_INT_24XX_UART2_IRQ),
136
 
-                    omap_findclk(s, "uart2_fclk"),
137
 
-                    omap_findclk(s, "uart2_iclk"),
138
 
-                    s->drq[OMAP24XX_DMA_UART2_TX],
139
 
-                    s->drq[OMAP24XX_DMA_UART2_RX],
140
 
-                    "uart2",
141
 
-                    serial_hds[0] ? serial_hds[1] : NULL);
142
 
-    s->uart[2] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 21),
143
 
-                                 qdev_get_gpio_in(s->ih[0],
144
 
-                                                  OMAP_INT_24XX_UART3_IRQ),
145
 
-                    omap_findclk(s, "uart3_fclk"),
146
 
-                    omap_findclk(s, "uart3_iclk"),
147
 
-                    s->drq[OMAP24XX_DMA_UART3_TX],
148
 
-                    s->drq[OMAP24XX_DMA_UART3_RX],
149
 
-                    "uart3",
150
 
-                    serial_hds[0] && serial_hds[1] ? serial_hds[2] : NULL);
151
 
+    s->uart[0] = qdev_create(NULL, "omap_uart");
152
 
+    s->uart[0]->id = "uart1";
153
 
+    qdev_prop_set_uint32(s->uart[0], "mmio_size", 0x1000);
154
 
+    qdev_prop_set_uint32(s->uart[0], "baudrate",
155
 
+                         omap_clk_getrate(omap_findclk(s, "uart1_fclk")) / 16);
156
 
+    qdev_prop_set_chr(s->uart[0], "chardev", serial_hds[0]);
157
 
+    qdev_init_nofail(s->uart[0]);
158
 
+    busdev = SYS_BUS_DEVICE(s->uart[0]);
159
 
+    sysbus_connect_irq(busdev, 0,
160
 
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_UART1_IRQ));
161
 
+    sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_UART1_TX]);
162
 
+    sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_UART1_RX]);
163
 
+    sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4ta(s->l4, 19), 0));
164
 
+
165
 
+    s->uart[1] = qdev_create(NULL, "omap_uart");
166
 
+    s->uart[1]->id = "uart2";
167
 
+    qdev_prop_set_uint32(s->uart[1], "mmio_size", 0x1000);
168
 
+    qdev_prop_set_uint32(s->uart[1], "baudrate",
169
 
+                         omap_clk_getrate(omap_findclk(s, "uart2_fclk")) / 16);
170
 
+    qdev_prop_set_chr(s->uart[1], "chardev",
171
 
+                      serial_hds[0] ? serial_hds[1] : NULL);
172
 
+    qdev_init_nofail(s->uart[1]);
173
 
+    busdev = SYS_BUS_DEVICE(s->uart[1]);
174
 
+    sysbus_connect_irq(busdev, 0,
175
 
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_UART2_IRQ));
176
 
+    sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_UART2_TX]);
177
 
+    sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_UART2_RX]);
178
 
+    sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4ta(s->l4, 20), 0));
179
 
+
180
 
+    s->uart[2] = qdev_create(NULL, "omap_uart");
181
 
+    s->uart[2]->id = "uart3";
182
 
+    qdev_prop_set_uint32(s->uart[2], "mmio_size", 0x1000);
183
 
+    qdev_prop_set_uint32(s->uart[2], "baudrate",
184
 
+                         omap_clk_getrate(omap_findclk(s, "uart3_fclk")) / 16);
185
 
+    qdev_prop_set_chr(s->uart[2], "chardev",
186
 
+                      serial_hds[0] && serial_hds[1] ? serial_hds[2] : NULL);
187
 
+    qdev_init_nofail(s->uart[2]);
188
 
+    busdev = SYS_BUS_DEVICE(s->uart[2]);
189
 
+    sysbus_connect_irq(busdev, 0,
190
 
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_UART3_IRQ));
191
 
+    sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_UART3_TX]);
192
 
+    sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_UART3_RX]);
193
 
+    sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4ta(s->l4, 21), 0));
194
 
 
195
 
     s->gptimer[0] = omap_gp_timer_init(omap_l4ta(s->l4, 7),
196
 
                     qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER1),
197
 
diff --git a/hw/char/omap_uart.c b/hw/char/omap_uart.c
198
 
index 61d893b..2bffed4 100644
199
 
--- a/hw/char/omap_uart.c
200
 
+++ b/hw/char/omap_uart.c
201
 
@@ -22,16 +22,31 @@
202
 
 #include "hw/arm/omap.h"
203
 
 #include "hw/char/serial.h"
204
 
 #include "exec/address-spaces.h"
205
 
+#include "hw/sysbus.h"
206
 
 
207
 
-/* UARTs */
208
 
-struct omap_uart_s {
209
 
+#define TYPE_OMAP_UART "omap_uart"
210
 
+#define OMAP_UART(obj) OBJECT_CHECK(omap_uart_s, (obj), TYPE_OMAP_UART)
211
 
+
212
 
+/* The OMAP UART functionality is similar to the TI16C752 rather than
213
 
+ * the 16550A. When the flag below is enabled, the code will however
214
 
+ * offer 'only' the basic 16550A emulation. */
215
 
+/* TODO: real functionality for the TI16C752 enhanced features. Note
216
 
+ * QEMU's SerialState emulation internally always uses a 16-byte FIFO
217
 
+ * whereas we would need a 64-byte FIFO for OMAP. */
218
 
+#define OMAP_UART_16550A
219
 
+
220
 
+typedef struct omap_uart_s {
221
 
+    SysBusDevice busdev;
222
 
     MemoryRegion iomem;
223
 
-    hwaddr base;
224
 
+    CharDriverState *chr;
225
 
     SerialState *serial; /* TODO */
226
 
-    struct omap_target_agent_s *ta;
227
 
-    omap_clk fclk;
228
 
-    qemu_irq irq;
229
 
+    const MemoryRegionOps *serial_ops;
230
 
+    uint32_t mmio_size;
231
 
+    uint32_t baudrate;
232
 
+    qemu_irq tx_drq;
233
 
+    qemu_irq rx_drq;
234
 
 
235
 
+    uint8_t lcr_cache;
236
 
     uint8_t eblr;
237
 
     uint8_t syscontrol;
238
 
     uint8_t wkup;
239
 
@@ -39,33 +54,39 @@ struct omap_uart_s {
240
 
     uint8_t mdr[2];
241
 
     uint8_t scr;
242
 
     uint8_t clksel;
243
 
-};
244
 
+    uint8_t blr;
245
 
+    uint8_t acreg;
246
 
 
247
 
-void omap_uart_reset(struct omap_uart_s *s)
248
 
+#ifndef OMAP_UART_16550A
249
 
+    uint8_t mcr_cache;
250
 
+    uint8_t efr;
251
 
+    uint8_t tcr;
252
 
+    uint8_t tlr;
253
 
+    uint8_t xon[2], xoff[2];
254
 
+#endif
255
 
+} omap_uart_s;
256
 
+
257
 
+static void omap_uart_reset(DeviceState *qdev)
258
 
 {
259
 
+    struct omap_uart_s *s = OMAP_UART(qdev);
260
 
+
261
 
     s->eblr = 0x00;
262
 
     s->syscontrol = 0;
263
 
     s->wkup = 0x3f;
264
 
     s->cfps = 0x69;
265
 
     s->clksel = 0;
266
 
-}
267
 
+    s->blr = 0x40;
268
 
+    s->acreg = 0;
269
 
+    s->lcr_cache = 0;
270
 
 
271
 
-struct omap_uart_s *omap_uart_init(hwaddr base,
272
 
-                qemu_irq irq, omap_clk fclk, omap_clk iclk,
273
 
-                qemu_irq txdma, qemu_irq rxdma,
274
 
-                const char *label, CharDriverState *chr)
275
 
-{
276
 
-    struct omap_uart_s *s = (struct omap_uart_s *)
277
 
-            g_malloc0(sizeof(struct omap_uart_s));
278
 
-
279
 
-    s->base = base;
280
 
-    s->fclk = fclk;
281
 
-    s->irq = irq;
282
 
-    s->serial = serial_mm_init(get_system_memory(), base, 2, irq,
283
 
-                               omap_clk_getrate(fclk)/16,
284
 
-                               chr ?: qemu_chr_new(label, "null", NULL),
285
 
-                               DEVICE_NATIVE_ENDIAN);
286
 
-    return s;
287
 
+#ifndef OMAP_UART_16550A
288
 
+    s->mcr_cache = 0;
289
 
+    s->tcr = 0x0f;
290
 
+    s->tlr = 0;
291
 
+    s->efr = 0;
292
 
+    s->xon[0] = s->xon[1] = 0;
293
 
+    s->xoff[0] = s->xoff[1] = 0;
294
 
+#endif
295
 
 }
296
 
 
297
 
 static uint64_t omap_uart_read(void *opaque, hwaddr addr,
298
 
@@ -73,15 +94,59 @@ static uint64_t omap_uart_read(void *opaque, hwaddr addr,
299
 
 {
300
 
     struct omap_uart_s *s = (struct omap_uart_s *) opaque;
301
 
 
302
 
-    if (size == 4) {
303
 
-        return omap_badwidth_read8(opaque, addr);
304
 
-    }
305
 
-
306
 
     switch (addr) {
307
 
+    case 0x00:
308
 
+    case 0x04:
309
 
+    case 0x0c:
310
 
+        return s->serial_ops->read(s->serial, addr, size);
311
 
+    case 0x08:
312
 
+#ifndef OMAP_UART_16550A
313
 
+        if (s->lcr_cache == 0xbf) {
314
 
+            return s->efr;
315
 
+        }
316
 
+#endif
317
 
+        return s->serial_ops->read(s->serial, addr, size);
318
 
+    case 0x10:
319
 
+    case 0x14:
320
 
+#ifndef OMAP_UART_16550A
321
 
+        if (s->lcr_cache == 0xbf) {
322
 
+            return s->xon[(addr & 7) >> 2];
323
 
+        } else if (addr == 0x10) {
324
 
+            return s->serial_ops->read(s->serial, addr, size)
325
 
+                   | (s->mcr_cache & 0xe0);
326
 
+        }
327
 
+#endif
328
 
+        return s->serial_ops->read(s->serial, addr, size);
329
 
+    case 0x18:
330
 
+    case 0x1c:
331
 
+#ifndef OMAP_UART_16550A
332
 
+        if ((s->efr & 0x10) && (s->mcr_cache & 0x40)) {
333
 
+            return (addr == 0x18) ? s->tcr : s->tlr;
334
 
+        }
335
 
+        if (s->lcr_cache == 0xbf) {
336
 
+            return s->xoff[(addr & 7) >> 2];
337
 
+        }
338
 
+#endif
339
 
+        return s->serial_ops->read(s->serial, addr, size);
340
 
     case 0x20: /* MDR1 */
341
 
         return s->mdr[0];
342
 
     case 0x24: /* MDR2 */
343
 
         return s->mdr[1];
344
 
+    case 0x28: /* SFLSR */
345
 
+        return 0;
346
 
+    case 0x2c: /* RESUME */
347
 
+        return 0;
348
 
+    case 0x30: /* SFREGL */
349
 
+        return 0;
350
 
+    case 0x34: /* SFREGH */
351
 
+        return 0;
352
 
+    case 0x38: /* UASR/BLR */
353
 
+        if ((s->lcr_cache & 0x80)) {
354
 
+            return 0; /* FIXME: return correct autodetect value */
355
 
+        }
356
 
+        return s->blr;
357
 
+    case 0x3c: /* ACREG */
358
 
+        return (s->lcr_cache & 0x80) ? 0 : s->acreg;
359
 
     case 0x40: /* SCR */
360
 
         return s->scr;
361
 
     case 0x44: /* SSR */
362
 
@@ -111,35 +176,99 @@ static void omap_uart_write(void *opaque, hwaddr addr,
363
 
 {
364
 
     struct omap_uart_s *s = (struct omap_uart_s *) opaque;
365
 
 
366
 
-    if (size == 4) {
367
 
-        return omap_badwidth_write8(opaque, addr, value);
368
 
-    }
369
 
-
370
 
     switch (addr) {
371
 
+    case 0x00:
372
 
+    case 0x04:
373
 
+        s->serial_ops->write(s->serial, addr, value, size);
374
 
+        break;
375
 
+    case 0x08:
376
 
+#ifndef OMAP_UART_16550A
377
 
+        if (s->lcr_cache == 0xbf) {
378
 
+            s->efr = value;
379
 
+        } else
380
 
+#endif
381
 
+        s->serial_ops->write(s->serial, addr, value, size);
382
 
+        break;
383
 
+    case 0x0c:
384
 
+        s->lcr_cache = value;
385
 
+        s->serial_ops->write(s->serial, addr, value, size);
386
 
+        break;
387
 
+    case 0x10:
388
 
+    case 0x14:
389
 
+#ifndef OMAP_UART_16550A
390
 
+        if (s->lcr_cache == 0xbf) {
391
 
+            s->xon[(addr & 7) >> 2] = value;
392
 
+        } else {
393
 
+            if (addr == 0x10) {
394
 
+                s->mcr_cache = value & 0x7f;
395
 
+            }
396
 
+#endif
397
 
+        s->serial_ops->write(s->serial, addr, value, size);
398
 
+#ifndef OMAP_UART_16550A
399
 
+        }
400
 
+#endif
401
 
+        break;
402
 
+    case 0x18:
403
 
+    case 0x1c:
404
 
+#ifndef OMAP_UART_16550A
405
 
+        if ((s->efr & 0x10) && (s->mcr_cache & 0x40)) {
406
 
+            if (addr == 0x18) {
407
 
+                s->tcr = value & 0xff;
408
 
+            } else {
409
 
+                s->tlr = value & 0xff;
410
 
+            }
411
 
+        } else if (s->lcr_cache == 0xbf) {
412
 
+            s->xoff[(addr & 7) >> 2] = value;
413
 
+        } else
414
 
+#endif
415
 
+        s->serial_ops->write(s->serial, addr, value, size);
416
 
+        break;
417
 
     case 0x20: /* MDR1 */
418
 
         s->mdr[0] = value & 0x7f;
419
 
         break;
420
 
     case 0x24: /* MDR2 */
421
 
         s->mdr[1] = value & 0xff;
422
 
         break;
423
 
+    case 0x28: /* TXFLL */
424
 
+    case 0x2c: /* TXFLH */
425
 
+    case 0x30: /* RXFLL */
426
 
+    case 0x34: /* RXFLH */
427
 
+        /* ignored */
428
 
+        break;
429
 
+    case 0x38: /* BLR */
430
 
+        if (!(s->lcr_cache & 0x80)) {
431
 
+            s->blr = value & 0xc0;
432
 
+        }
433
 
+        break;
434
 
+    case 0x3c: /* ACREG */
435
 
+        if (!(s->lcr_cache & 0x80)) {
436
 
+            s->acreg = value & 0xff;
437
 
+        }
438
 
+        break;
439
 
     case 0x40: /* SCR */
440
 
         s->scr = value & 0xff;
441
 
         break;
442
 
+    case 0x44: /* SSR */
443
 
+        OMAP_RO_REG(addr);
444
 
+        break;
445
 
     case 0x48: /* EBLR (OMAP2) */
446
 
         s->eblr = value & 0xff;
447
 
         break;
448
 
     case 0x4C: /* OSC_12M_SEL (OMAP1) */
449
 
         s->clksel = value & 1;
450
 
         break;
451
 
-    case 0x44: /* SSR */
452
 
     case 0x50: /* MVR */
453
 
-    case 0x58: /* SYSS (OMAP2) */
454
 
         OMAP_RO_REG(addr);
455
 
         break;
456
 
     case 0x54: /* SYSC (OMAP2) */
457
 
         s->syscontrol = value & 0x1d;
458
 
-        if (value & 2)
459
 
-            omap_uart_reset(s);
460
 
+        if (value & 2) {
461
 
+            /* TODO: reset s->serial also. */
462
 
+            omap_uart_reset(DEVICE(s));
463
 
+        }
464
 
+        break;
465
 
+    case 0x58: /* SYSS (OMAP2) */
466
 
+        OMAP_RO_REG(addr);
467
 
         break;
468
 
     case 0x5c: /* WER (OMAP2) */
469
 
         s->wkup = value & 0x7f;
470
 
@@ -158,31 +287,67 @@ static const MemoryRegionOps omap_uart_ops = {
471
 
     .endianness = DEVICE_NATIVE_ENDIAN,
472
 
 };
473
 
 
474
 
-struct omap_uart_s *omap2_uart_init(MemoryRegion *sysmem,
475
 
-                struct omap_target_agent_s *ta,
476
 
-                qemu_irq irq, omap_clk fclk, omap_clk iclk,
477
 
-                qemu_irq txdma, qemu_irq rxdma,
478
 
-                const char *label, CharDriverState *chr)
479
 
+static int omap_uart_init(SysBusDevice *busdev)
480
 
 {
481
 
-    hwaddr base = omap_l4_attach(ta, 0, NULL);
482
 
-    struct omap_uart_s *s = omap_uart_init(base, irq,
483
 
-                    fclk, iclk, txdma, rxdma, label, chr);
484
 
+    struct omap_uart_s *s = OMAP_UART(busdev);
485
 
+
486
 
+    if (!s->chr) {
487
 
+        // XXX looks a bit dubious to grab id like this
488
 
+        s->chr = qemu_chr_new(DEVICE(busdev)->id, "null", NULL);
489
 
+    }
490
 
+    /* TODO: DMA support. Current 16550A emulation does not emulate DMA mode
491
 
+     * transfers via TXRDY/RXRDY pins. We create DMA irq lines here for
492
 
+     * future use nevertheless. */
493
 
+    /* Nasty hackery because trying to extend an existing device is
494
 
+     * not really supported, and the serial driver isn't even qdev.
495
 
+     */
496
 
+    s->serial = serial_mm_init(NULL, 0, 2, NULL, s->baudrate, s->chr,
497
 
+                               DEVICE_NATIVE_ENDIAN);
498
 
+    s->serial_ops = serial_get_memops(DEVICE_NATIVE_ENDIAN);
499
 
+    sysbus_init_irq(busdev, serial_get_irq(s->serial));
500
 
+    sysbus_init_irq(busdev, &s->tx_drq);
501
 
+    sysbus_init_irq(busdev, &s->rx_drq);
502
 
+    memory_region_init_io(&s->iomem, NULL, &omap_uart_ops, s, "omap_uart",
503
 
+                          s->mmio_size);
504
 
+    sysbus_init_mmio(busdev, &s->iomem);
505
 
+    return 0;
506
 
+}
507
 
 
508
 
-    memory_region_init_io(&s->iomem, NULL, &omap_uart_ops, s, "omap.uart", 0x100);
509
 
+static Property omap_uart_properties[] = {
510
 
+    DEFINE_PROP_UINT32("mmio_size", struct omap_uart_s, mmio_size, 0x400),
511
 
+    DEFINE_PROP_UINT32("baudrate", struct omap_uart_s, baudrate, 0),
512
 
+    DEFINE_PROP_CHR("chardev", struct omap_uart_s, chr),
513
 
+    DEFINE_PROP_END_OF_LIST()
514
 
+};
515
 
 
516
 
-    s->ta = ta;
517
 
+static void omap_uart_class_init(ObjectClass *klass, void *data)
518
 
+{
519
 
+    DeviceClass *dc = DEVICE_CLASS(klass);
520
 
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
521
 
+    k->init = omap_uart_init;
522
 
+    dc->props = omap_uart_properties;
523
 
+    dc->reset = omap_uart_reset;
524
 
+}
525
 
 
526
 
-    memory_region_add_subregion(sysmem, base + 0x20, &s->iomem);
527
 
+static TypeInfo omap_uart_info = {
528
 
+    .name = "omap_uart",
529
 
+    .parent = TYPE_SYS_BUS_DEVICE,
530
 
+    .instance_size = sizeof(struct omap_uart_s),
531
 
+    .class_init = omap_uart_class_init,
532
 
+};
533
 
 
534
 
-    return s;
535
 
+static void omap_uart_register_types(void)
536
 
+{
537
 
+    type_register_static(&omap_uart_info);
538
 
 }
539
 
 
540
 
-void omap_uart_attach(struct omap_uart_s *s, CharDriverState *chr,
541
 
+void omap_uart_attach(DeviceState *qdev, CharDriverState *chr,
542
 
                       const char *label)
543
 
 {
544
 
-    /* TODO: Should reuse or destroy current s->serial */
545
 
-    s->serial = serial_mm_init(get_system_memory(), s->base, 2, s->irq,
546
 
-                               omap_clk_getrate(s->fclk) / 16,
547
 
-                               chr ?: qemu_chr_new(label, "null", NULL),
548
 
-                               DEVICE_NATIVE_ENDIAN);
549
 
+    struct omap_uart_s *s = OMAP_UART(qdev);
550
 
+
551
 
+    s->chr = chr ?: qemu_chr_new(label, "null", NULL);
552
 
+    serial_change_char_driver(s->serial, s->chr);
553
 
 }
554
 
+
555
 
+type_init(omap_uart_register_types)
556
 
diff --git a/hw/char/serial.c b/hw/char/serial.c
557
 
index 27dab7d..ab78c1e 100644
558
 
--- a/hw/char/serial.c
559
 
+++ b/hw/char/serial.c
560
 
@@ -767,10 +767,32 @@ SerialState *serial_mm_init(MemoryRegion *address_space,
561
 
     }
562
 
     vmstate_register(NULL, base, &vmstate_serial, s);
563
 
 
564
 
-    memory_region_init_io(&s->io, NULL, &serial_mm_ops[end], s,
565
 
-                          "serial", 8 << it_shift);
566
 
-    memory_region_add_subregion(address_space, base, &s->io);
567
 
+    if (address_space) {
568
 
+        memory_region_init_io(&s->io, NULL, &serial_mm_ops[end], s,
569
 
+                              "serial", 8 << it_shift);
570
 
+        memory_region_add_subregion(address_space, base, &s->io);
571
 
+    }
572
 
 
573
 
     serial_update_msl(s);
574
 
     return s;
575
 
 }
576
 
+
577
 
+void serial_change_char_driver(SerialState *s, CharDriverState *chr)
578
 
+{
579
 
+    /* TODO this is somewhat guesswork, and pretty ugly anyhow */
580
 
+    qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
581
 
+    s->chr = chr;
582
 
+    qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
583
 
+                          serial_event, s);
584
 
+    serial_update_msl(s);
585
 
+}
586
 
+
587
 
+const MemoryRegionOps *serial_get_memops(enum device_endian end)
588
 
+{
589
 
+    return &serial_mm_ops[end];
590
 
+}
591
 
+
592
 
+qemu_irq *serial_get_irq(SerialState *s)
593
 
+{
594
 
+    return &s->irq;
595
 
+}
596
 
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
597
 
index e408771..9d0a0b7 100644
598
 
--- a/include/hw/arm/omap.h
599
 
+++ b/include/hw/arm/omap.h
600
 
@@ -871,18 +871,7 @@ struct omap_synctimer_s *omap_synctimer_init(struct omap_target_agent_s *ta,
601
 
                 struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk);
602
 
 void omap_synctimer_reset(struct omap_synctimer_s *s);
603
 
 
604
 
-struct omap_uart_s;
605
 
-struct omap_uart_s *omap_uart_init(hwaddr base,
606
 
-                qemu_irq irq, omap_clk fclk, omap_clk iclk,
607
 
-                qemu_irq txdma, qemu_irq rxdma,
608
 
-                const char *label, CharDriverState *chr);
609
 
-struct omap_uart_s *omap2_uart_init(MemoryRegion *sysmem,
610
 
-                struct omap_target_agent_s *ta,
611
 
-                qemu_irq irq, omap_clk fclk, omap_clk iclk,
612
 
-                qemu_irq txdma, qemu_irq rxdma,
613
 
-                const char *label, CharDriverState *chr);
614
 
-void omap_uart_reset(struct omap_uart_s *s);
615
 
-void omap_uart_attach(struct omap_uart_s *s, CharDriverState *chr,
616
 
+void omap_uart_attach(DeviceState *qdev, CharDriverState *chr,
617
 
                       const char *label);
618
 
 
619
 
 struct omap_mpuio_s;
620
 
@@ -1048,7 +1037,7 @@ struct omap_mpu_state_s {
621
 
     unsigned long sram_size;
622
 
 
623
 
     /* MPUI-TIPB peripherals */
624
 
-    struct omap_uart_s *uart[3];
625
 
+    DeviceState *uart[4];
626
 
 
627
 
     DeviceState *gpio;
628
 
 
629
 
diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h
630
 
index 85f58ac..bc6e493 100644
631
 
--- a/include/hw/char/serial.h
632
 
+++ b/include/hw/char/serial.h
633
 
@@ -81,6 +81,9 @@ extern const MemoryRegionOps serial_io_ops;
634
 
 void serial_realize_core(SerialState *s, Error **errp);
635
 
 void serial_exit_core(SerialState *s);
636
 
 void serial_set_frequency(SerialState *s, uint32_t frequency);
637
 
+void serial_change_char_driver(SerialState *s, CharDriverState *chr);
638
 
+const MemoryRegionOps *serial_get_memops(enum device_endian end);
639
 
+qemu_irq *serial_get_irq(SerialState *s);
640
 
 
641
 
 /* legacy pre qom */
642
 
 SerialState *serial_init(int base, qemu_irq irq, int baudbase,
643
 
1.8.5.2
644