2
* Arm PrimeCell PL011 UART
4
* Copyright (c) 2006 CodeSourcery.
5
* Written by Paul Brook
7
* This code is licensed under the GPL.
11
#include "qemu-char.h"
22
uint32_t read_fifo[16];
32
const unsigned char *id;
35
#define PL011_INT_TX 0x20
36
#define PL011_INT_RX 0x10
38
#define PL011_FLAG_TXFE 0x80
39
#define PL011_FLAG_RXFF 0x40
40
#define PL011_FLAG_TXFF 0x20
41
#define PL011_FLAG_RXFE 0x10
43
static const unsigned char pl011_id_arm[8] =
44
{ 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
45
static const unsigned char pl011_id_luminary[8] =
46
{ 0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 };
48
static void pl011_update(pl011_state *s)
52
flags = s->int_level & s->int_enabled;
53
qemu_set_irq(s->irq, flags != 0);
56
static uint32_t pl011_read(void *opaque, target_phys_addr_t offset)
58
pl011_state *s = (pl011_state *)opaque;
61
if (offset >= 0xfe0 && offset < 0x1000) {
62
return s->id[(offset - 0xfe0) >> 2];
64
switch (offset >> 2) {
66
s->flags &= ~PL011_FLAG_RXFF;
67
c = s->read_fifo[s->read_pos];
68
if (s->read_count > 0) {
70
if (++s->read_pos == 16)
73
if (s->read_count == 0) {
74
s->flags |= PL011_FLAG_RXFE;
76
if (s->read_count == s->read_trigger - 1)
77
s->int_level &= ~ PL011_INT_RX;
79
qemu_chr_accept_input(s->chr);
85
case 8: /* UARTILPR */
87
case 9: /* UARTIBRD */
89
case 10: /* UARTFBRD */
91
case 11: /* UARTLCR_H */
95
case 13: /* UARTIFLS */
97
case 14: /* UARTIMSC */
98
return s->int_enabled;
99
case 15: /* UARTRIS */
101
case 16: /* UARTMIS */
102
return s->int_level & s->int_enabled;
103
case 18: /* UARTDMACR */
106
hw_error("pl011_read: Bad offset %x\n", (int)offset);
111
static void pl011_set_read_trigger(pl011_state *s)
114
/* The docs say the RX interrupt is triggered when the FIFO exceeds
115
the threshold. However linux only reads the FIFO in response to an
116
interrupt. Triggering the interrupt when the FIFO is non-empty seems
117
to make things work. */
119
s->read_trigger = (s->ifl >> 1) & 0x1c;
125
static void pl011_write(void *opaque, target_phys_addr_t offset,
128
pl011_state *s = (pl011_state *)opaque;
131
switch (offset >> 2) {
133
/* ??? Check if transmitter is enabled. */
136
qemu_chr_fe_write(s->chr, &ch, 1);
137
s->int_level |= PL011_INT_TX;
144
/* Writes to Flag register are ignored. */
146
case 8: /* UARTUARTILPR */
149
case 9: /* UARTIBRD */
152
case 10: /* UARTFBRD */
155
case 11: /* UARTLCR_H */
157
pl011_set_read_trigger(s);
159
case 12: /* UARTCR */
160
/* ??? Need to implement the enable and loopback bits. */
163
case 13: /* UARTIFS */
165
pl011_set_read_trigger(s);
167
case 14: /* UARTIMSC */
168
s->int_enabled = value;
171
case 17: /* UARTICR */
172
s->int_level &= ~value;
175
case 18: /* UARTDMACR */
178
hw_error("PL011: DMA not implemented\n");
181
hw_error("pl011_write: Bad offset %x\n", (int)offset);
185
static int pl011_can_receive(void *opaque)
187
pl011_state *s = (pl011_state *)opaque;
190
return s->read_count < 16;
192
return s->read_count < 1;
195
static void pl011_put_fifo(void *opaque, uint32_t value)
197
pl011_state *s = (pl011_state *)opaque;
200
slot = s->read_pos + s->read_count;
203
s->read_fifo[slot] = value;
205
s->flags &= ~PL011_FLAG_RXFE;
206
if (s->cr & 0x10 || s->read_count == 16) {
207
s->flags |= PL011_FLAG_RXFF;
209
if (s->read_count == s->read_trigger) {
210
s->int_level |= PL011_INT_RX;
215
static void pl011_receive(void *opaque, const uint8_t *buf, int size)
217
pl011_put_fifo(opaque, *buf);
220
static void pl011_event(void *opaque, int event)
222
if (event == CHR_EVENT_BREAK)
223
pl011_put_fifo(opaque, 0x400);
226
static CPUReadMemoryFunc * const pl011_readfn[] = {
232
static CPUWriteMemoryFunc * const pl011_writefn[] = {
238
static const VMStateDescription vmstate_pl011 = {
241
.minimum_version_id = 1,
242
.minimum_version_id_old = 1,
243
.fields = (VMStateField[]) {
244
VMSTATE_UINT32(readbuff, pl011_state),
245
VMSTATE_UINT32(flags, pl011_state),
246
VMSTATE_UINT32(lcr, pl011_state),
247
VMSTATE_UINT32(cr, pl011_state),
248
VMSTATE_UINT32(dmacr, pl011_state),
249
VMSTATE_UINT32(int_enabled, pl011_state),
250
VMSTATE_UINT32(int_level, pl011_state),
251
VMSTATE_UINT32_ARRAY(read_fifo, pl011_state, 16),
252
VMSTATE_UINT32(ilpr, pl011_state),
253
VMSTATE_UINT32(ibrd, pl011_state),
254
VMSTATE_UINT32(fbrd, pl011_state),
255
VMSTATE_UINT32(ifl, pl011_state),
256
VMSTATE_INT32(read_pos, pl011_state),
257
VMSTATE_INT32(read_count, pl011_state),
258
VMSTATE_INT32(read_trigger, pl011_state),
259
VMSTATE_END_OF_LIST()
263
static int pl011_init(SysBusDevice *dev, const unsigned char *id)
266
pl011_state *s = FROM_SYSBUS(pl011_state, dev);
268
iomemtype = cpu_register_io_memory(pl011_readfn,
270
DEVICE_NATIVE_ENDIAN);
271
sysbus_init_mmio(dev, 0x1000,iomemtype);
272
sysbus_init_irq(dev, &s->irq);
274
s->chr = qdev_init_chardev(&dev->qdev);
281
qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
284
vmstate_register(&dev->qdev, -1, &vmstate_pl011, s);
288
static int pl011_init_arm(SysBusDevice *dev)
290
return pl011_init(dev, pl011_id_arm);
293
static int pl011_init_luminary(SysBusDevice *dev)
295
return pl011_init(dev, pl011_id_luminary);
298
static void pl011_register_devices(void)
300
sysbus_register_dev("pl011", sizeof(pl011_state),
302
sysbus_register_dev("pl011_luminary", sizeof(pl011_state),
303
pl011_init_luminary);
306
device_init(pl011_register_devices)