2
* TI OMAP processors UART emulation.
4
* Copyright (C) 2006-2008 Andrzej Zaborowski <balrog@zabor.org>
5
* Copyright (C) 2007-2009 Nokia Corporation
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.
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.
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/>.
20
#include "sysemu/char.h"
22
#include "hw/arm/omap.h"
23
#include "hw/char/serial.h"
24
#include "exec/address-spaces.h"
25
#include "hw/sysbus.h"
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
31
* Currently unmodelled functionality:
32
* + We should have a 64 byte FIFO but QEMU's SerialState emulation
33
* always uses a 16 byte FIFO
35
* + interrupts based on TCR/TLR values
36
* + XON/XOFF flow control
37
* + UASR auto-baudrate-detection
44
SerialState *serial; /* TODO */
45
const MemoryRegionOps *serial_ops;
52
/* Register access mode, which affects what registers you see */
73
uint8_t xon[2], xoff[2];
76
static int tcr_tlr_mode(struct omap_uart_s *s)
78
/* Return true if registers 0x18 and 0x1c are TCR/TLR
79
* (as opposed to SPR/MSR/XOFF)
81
return (s->efr & 0x10) && (s->mcr_cache & 0x40);
84
static void omap_uart_reset(DeviceState *qdev)
86
struct omap_uart_s *s = FROM_SYSBUS(struct omap_uart_s,
87
SYS_BUS_DEVICE(qdev));
95
s->access_mode = regs_operational;
101
s->xon[0] = s->xon[1] = 0;
102
s->xoff[0] = s->xoff[1] = 0;
105
static uint64_t omap_uart_read(void *opaque, hwaddr addr,
108
struct omap_uart_s *s = (struct omap_uart_s *) opaque;
114
return s->serial_ops->read(s->serial, addr, size);
116
if (s->access_mode == regs_config_b) {
119
return s->serial_ops->read(s->serial, addr, size);
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.
128
return s->serial_ops->read(s->serial, addr, size) | s->mcr_cache;
130
return s->serial_ops->read(s->serial, addr, size);
133
if (tcr_tlr_mode(s)) {
134
return (addr == 0x18) ? s->tcr : s->tlr;
136
if (s->access_mode == regs_config_b) {
137
return s->xoff[(addr & 7) >> 2];
139
return s->serial_ops->read(s->serial, addr, size);
140
case 0x20: /* MDR1 */
142
case 0x24: /* MDR2 */
144
case 0x28: /* SFLSR */
146
case 0x2c: /* RESUME */
148
case 0x30: /* SFREGL */
150
case 0x34: /* SFREGH */
152
case 0x38: /* UASR/BLR */
153
if (s->access_mode != regs_operational) {
154
return 0; /* FIXME: return correct autodetect value */
157
case 0x3c: /* ACREG */
158
return (s->access_mode != regs_operational) ? 0 : s->acreg;
163
case 0x48: /* EBLR (OMAP2) */
165
case 0x4C: /* OSC_12M_SEL (OMAP1) */
169
case 0x54: /* SYSC (OMAP2) */
170
return s->syscontrol;
171
case 0x58: /* SYSS (OMAP2) */
173
case 0x5c: /* WER (OMAP2) */
175
case 0x60: /* CFPS (OMAP2) */
183
static void omap_uart_write(void *opaque, hwaddr addr,
184
uint64_t value, unsigned size)
186
struct omap_uart_s *s = (struct omap_uart_s *) opaque;
191
s->serial_ops->write(s->serial, addr, value, size);
194
if (s->access_mode == regs_config_b) {
197
s->serial_ops->write(s->serial, addr, value, size);
201
if ((value & 0xff) == 0xbf) {
202
s->access_mode = regs_config_b;
203
} else if (value & 0x80) {
204
s->access_mode = regs_config_a;
206
s->access_mode = regs_operational;
208
s->serial_ops->write(s->serial, addr, value, size);
212
if (s->access_mode == regs_config_b) {
213
s->xon[(addr & 7) >> 2] = value;
216
/* Bits 5 and 6 are handled at this level; they can
217
* only be written if EFR_REG:ENHANCED_EN is set.
220
s->mcr_cache = value & 0x60;
223
s->serial_ops->write(s->serial, addr, value, size);
228
if (tcr_tlr_mode(s)) {
230
s->tcr = value & 0xff;
232
s->tlr = value & 0xff;
234
} else if (s->access_mode == regs_config_b) {
235
s->xoff[(addr & 7) >> 2] = value;
237
s->serial_ops->write(s->serial, addr, value, size);
240
case 0x20: /* MDR1 */
241
s->mdr[0] = value & 0x7f;
243
case 0x24: /* MDR2 */
244
s->mdr[1] = value & 0xff;
246
case 0x28: /* TXFLL */
247
case 0x2c: /* TXFLH */
248
case 0x30: /* RXFLL */
249
case 0x34: /* RXFLH */
253
if (s->access_mode == regs_operational) {
254
s->blr = value & 0xc0;
257
case 0x3c: /* ACREG */
258
if (s->access_mode == regs_operational) {
259
s->acreg = value & 0xff;
263
s->scr = value & 0xff;
268
case 0x48: /* EBLR (OMAP2) */
269
s->eblr = value & 0xff;
271
case 0x4C: /* OSC_12M_SEL (OMAP1) */
272
s->clksel = value & 1;
277
case 0x54: /* SYSC (OMAP2) */
278
s->syscontrol = value & 0x1d;
280
/* TODO: reset s->serial also. */
281
omap_uart_reset(&s->busdev.qdev);
284
case 0x58: /* SYSS (OMAP2) */
287
case 0x5c: /* WER (OMAP2) */
288
s->wkup = value & 0x7f;
290
case 0x60: /* CFPS (OMAP2) */
291
s->cfps = value & 0xff;
298
static const MemoryRegionOps omap_uart_ops = {
299
.read = omap_uart_read,
300
.write = omap_uart_write,
301
.endianness = DEVICE_NATIVE_ENDIAN,
304
static int omap_uart_init(SysBusDevice *busdev)
306
struct omap_uart_s *s = FROM_SYSBUS(struct omap_uart_s, busdev);
308
s->chr = qemu_chr_new(busdev->qdev.id, "null", NULL);
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.
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",
324
sysbus_init_mmio(busdev, &s->iomem);
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()
336
static void omap_uart_class_init(ObjectClass *klass, void *data)
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;
345
static TypeInfo omap_uart_info = {
347
.parent = TYPE_SYS_BUS_DEVICE,
348
.instance_size = sizeof(struct omap_uart_s),
349
.class_init = omap_uart_class_init,
352
static void omap_uart_register_types(void)
354
type_register_static(&omap_uart_info);
357
void omap_uart_attach(DeviceState *qdev, CharDriverState *chr,
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);
366
type_init(omap_uart_register_types)