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
#define TYPE_OMAP_UART "omap_uart"
28
#define OMAP_UART(obj) OBJECT_CHECK(omap_uart_s, (obj), TYPE_OMAP_UART)
30
/* The OMAP UART functionality is similar to the TI16C752 rather than
31
* the 16550A. When the flag below is enabled, the code will however
32
* offer 'only' the basic 16550A emulation. */
33
/* TODO: real functionality for the TI16C752 enhanced features. Note
34
* QEMU's SerialState emulation internally always uses a 16-byte FIFO
35
* whereas we would need a 64-byte FIFO for OMAP. */
36
#define OMAP_UART_16550A
38
typedef struct omap_uart_s {
42
SerialState *serial; /* TODO */
43
const MemoryRegionOps *serial_ops;
60
#ifndef OMAP_UART_16550A
65
uint8_t xon[2], xoff[2];
69
static void omap_uart_reset(DeviceState *qdev)
71
struct omap_uart_s *s = OMAP_UART(qdev);
82
#ifndef OMAP_UART_16550A
87
s->xon[0] = s->xon[1] = 0;
88
s->xoff[0] = s->xoff[1] = 0;
92
static uint64_t omap_uart_read(void *opaque, hwaddr addr,
95
struct omap_uart_s *s = (struct omap_uart_s *) opaque;
101
return s->serial_ops->read(s->serial, addr, size);
103
#ifndef OMAP_UART_16550A
104
if (s->lcr_cache == 0xbf) {
108
return s->serial_ops->read(s->serial, addr, size);
111
#ifndef OMAP_UART_16550A
112
if (s->lcr_cache == 0xbf) {
113
return s->xon[(addr & 7) >> 2];
114
} else if (addr == 0x10) {
115
return s->serial_ops->read(s->serial, addr, size)
116
| (s->mcr_cache & 0xe0);
119
return s->serial_ops->read(s->serial, addr, size);
122
#ifndef OMAP_UART_16550A
123
if ((s->efr & 0x10) && (s->mcr_cache & 0x40)) {
124
return (addr == 0x18) ? s->tcr : s->tlr;
126
if (s->lcr_cache == 0xbf) {
127
return s->xoff[(addr & 7) >> 2];
130
return s->serial_ops->read(s->serial, addr, size);
131
case 0x20: /* MDR1 */
133
case 0x24: /* MDR2 */
135
case 0x28: /* SFLSR */
137
case 0x2c: /* RESUME */
139
case 0x30: /* SFREGL */
141
case 0x34: /* SFREGH */
143
case 0x38: /* UASR/BLR */
144
if ((s->lcr_cache & 0x80)) {
145
return 0; /* FIXME: return correct autodetect value */
148
case 0x3c: /* ACREG */
149
return (s->lcr_cache & 0x80) ? 0 : s->acreg;
154
case 0x48: /* EBLR (OMAP2) */
156
case 0x4C: /* OSC_12M_SEL (OMAP1) */
160
case 0x54: /* SYSC (OMAP2) */
161
return s->syscontrol;
162
case 0x58: /* SYSS (OMAP2) */
164
case 0x5c: /* WER (OMAP2) */
166
case 0x60: /* CFPS (OMAP2) */
174
static void omap_uart_write(void *opaque, hwaddr addr,
175
uint64_t value, unsigned size)
177
struct omap_uart_s *s = (struct omap_uart_s *) opaque;
182
s->serial_ops->write(s->serial, addr, value, size);
185
#ifndef OMAP_UART_16550A
186
if (s->lcr_cache == 0xbf) {
190
s->serial_ops->write(s->serial, addr, value, size);
193
s->lcr_cache = value;
194
s->serial_ops->write(s->serial, addr, value, size);
198
#ifndef OMAP_UART_16550A
199
if (s->lcr_cache == 0xbf) {
200
s->xon[(addr & 7) >> 2] = value;
203
s->mcr_cache = value & 0x7f;
206
s->serial_ops->write(s->serial, addr, value, size);
207
#ifndef OMAP_UART_16550A
213
#ifndef OMAP_UART_16550A
214
if ((s->efr & 0x10) && (s->mcr_cache & 0x40)) {
216
s->tcr = value & 0xff;
218
s->tlr = value & 0xff;
220
} else if (s->lcr_cache == 0xbf) {
221
s->xoff[(addr & 7) >> 2] = value;
224
s->serial_ops->write(s->serial, addr, value, size);
226
case 0x20: /* MDR1 */
227
s->mdr[0] = value & 0x7f;
229
case 0x24: /* MDR2 */
230
s->mdr[1] = value & 0xff;
232
case 0x28: /* TXFLL */
233
case 0x2c: /* TXFLH */
234
case 0x30: /* RXFLL */
235
case 0x34: /* RXFLH */
239
if (!(s->lcr_cache & 0x80)) {
240
s->blr = value & 0xc0;
243
case 0x3c: /* ACREG */
244
if (!(s->lcr_cache & 0x80)) {
245
s->acreg = value & 0xff;
249
s->scr = value & 0xff;
254
case 0x48: /* EBLR (OMAP2) */
255
s->eblr = value & 0xff;
257
case 0x4C: /* OSC_12M_SEL (OMAP1) */
258
s->clksel = value & 1;
263
case 0x54: /* SYSC (OMAP2) */
264
s->syscontrol = value & 0x1d;
266
/* TODO: reset s->serial also. */
267
omap_uart_reset(DEVICE(s));
270
case 0x58: /* SYSS (OMAP2) */
273
case 0x5c: /* WER (OMAP2) */
274
s->wkup = value & 0x7f;
276
case 0x60: /* CFPS (OMAP2) */
277
s->cfps = value & 0xff;
284
static const MemoryRegionOps omap_uart_ops = {
285
.read = omap_uart_read,
286
.write = omap_uart_write,
287
.endianness = DEVICE_NATIVE_ENDIAN,
290
static int omap_uart_init(SysBusDevice *busdev)
292
struct omap_uart_s *s = OMAP_UART(busdev);
295
// XXX looks a bit dubious to grab id like this
296
s->chr = qemu_chr_new(DEVICE(busdev)->id, "null", NULL);
298
/* TODO: DMA support. Current 16550A emulation does not emulate DMA mode
299
* transfers via TXRDY/RXRDY pins. We create DMA irq lines here for
300
* future use nevertheless. */
301
/* Nasty hackery because trying to extend an existing device is
302
* not really supported, and the serial driver isn't even qdev.
304
s->serial = serial_mm_init(NULL, 0, 2, NULL, s->baudrate, s->chr,
305
DEVICE_NATIVE_ENDIAN);
306
s->serial_ops = serial_get_memops(DEVICE_NATIVE_ENDIAN);
307
sysbus_init_irq(busdev, serial_get_irq(s->serial));
308
sysbus_init_irq(busdev, &s->tx_drq);
309
sysbus_init_irq(busdev, &s->rx_drq);
310
memory_region_init_io(&s->iomem, NULL, &omap_uart_ops, s, "omap_uart",
312
sysbus_init_mmio(busdev, &s->iomem);
316
static Property omap_uart_properties[] = {
317
DEFINE_PROP_UINT32("mmio_size", struct omap_uart_s, mmio_size, 0x400),
318
DEFINE_PROP_UINT32("baudrate", struct omap_uart_s, baudrate, 0),
319
DEFINE_PROP_CHR("chardev", struct omap_uart_s, chr),
320
DEFINE_PROP_END_OF_LIST()
323
static void omap_uart_class_init(ObjectClass *klass, void *data)
325
DeviceClass *dc = DEVICE_CLASS(klass);
326
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
327
k->init = omap_uart_init;
328
dc->props = omap_uart_properties;
329
dc->reset = omap_uart_reset;
332
static TypeInfo omap_uart_info = {
334
.parent = TYPE_SYS_BUS_DEVICE,
335
.instance_size = sizeof(struct omap_uart_s),
336
.class_init = omap_uart_class_init,
339
static void omap_uart_register_types(void)
341
type_register_static(&omap_uart_info);
344
void omap_uart_attach(DeviceState *qdev, CharDriverState *chr,
347
struct omap_uart_s *s = OMAP_UART(qdev);
349
s->chr = chr ?: qemu_chr_new(label, "null", NULL);
350
serial_change_char_driver(s->serial, s->chr);
353
type_init(omap_uart_register_types)