Revision a7d518a6 hw/pl011.c
b/hw/pl011.c | ||
---|---|---|
7 | 7 |
* This code is licenced under the GPL. |
8 | 8 |
*/ |
9 | 9 |
|
10 |
#include "hw.h"
|
|
10 |
#include "sysbus.h"
|
|
11 | 11 |
#include "qemu-char.h" |
12 |
#include "primecell.h" |
|
13 | 12 |
|
14 | 13 |
typedef struct { |
14 |
SysBusDevice busdev; |
|
15 | 15 |
uint32_t readbuff; |
16 | 16 |
uint32_t flags; |
17 | 17 |
uint32_t lcr; |
... | ... | |
29 | 29 |
int read_trigger; |
30 | 30 |
CharDriverState *chr; |
31 | 31 |
qemu_irq irq; |
32 |
enum pl011_type type;
|
|
32 |
const unsigned char *id;
|
|
33 | 33 |
} pl011_state; |
34 | 34 |
|
35 | 35 |
#define PL011_INT_TX 0x20 |
... | ... | |
40 | 40 |
#define PL011_FLAG_TXFF 0x20 |
41 | 41 |
#define PL011_FLAG_RXFE 0x10 |
42 | 42 |
|
43 |
static const unsigned char pl011_id[2][8] = {
|
|
44 |
{ 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 }, /* PL011_ARM */
|
|
45 |
{ 0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 }, /* PL011_LUMINARY */
|
|
46 |
}; |
|
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 };
|
|
47 | 47 |
|
48 | 48 |
static void pl011_update(pl011_state *s) |
49 | 49 |
{ |
... | ... | |
59 | 59 |
uint32_t c; |
60 | 60 |
|
61 | 61 |
if (offset >= 0xfe0 && offset < 0x1000) { |
62 |
return pl011_id[s->type][(offset - 0xfe0) >> 2];
|
|
62 |
return s->id[(offset - 0xfe0) >> 2];
|
|
63 | 63 |
} |
64 | 64 |
switch (offset >> 2) { |
65 | 65 |
case 0: /* UARTDR */ |
... | ... | |
286 | 286 |
return 0; |
287 | 287 |
} |
288 | 288 |
|
289 |
void pl011_init(uint32_t base, qemu_irq irq, |
|
290 |
CharDriverState *chr, enum pl011_type type) |
|
289 |
static void pl011_init(SysBusDevice *dev, const unsigned char *id) |
|
291 | 290 |
{ |
292 | 291 |
int iomemtype; |
293 |
pl011_state *s; |
|
292 |
pl011_state *s = FROM_SYSBUS(pl011_state, dev);
|
|
294 | 293 |
|
295 |
s = (pl011_state *)qemu_mallocz(sizeof(pl011_state)); |
|
296 | 294 |
iomemtype = cpu_register_io_memory(0, pl011_readfn, |
297 | 295 |
pl011_writefn, s); |
298 |
cpu_register_physical_memory(base, 0x00001000, iomemtype); |
|
299 |
s->irq = irq; |
|
300 |
s->type = type; |
|
301 |
s->chr = chr; |
|
296 |
sysbus_init_mmio(dev, 0x1000,iomemtype); |
|
297 |
sysbus_init_irq(dev, &s->irq); |
|
298 |
s->id = id; |
|
299 |
s->chr = qdev_init_chardev(&dev->qdev); |
|
300 |
|
|
302 | 301 |
s->read_trigger = 1; |
303 | 302 |
s->ifl = 0x12; |
304 | 303 |
s->cr = 0x300; |
305 | 304 |
s->flags = 0x90; |
306 |
if (chr){
|
|
307 |
qemu_chr_add_handlers(chr, pl011_can_receive, pl011_receive, |
|
305 |
if (s->chr) {
|
|
306 |
qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
|
|
308 | 307 |
pl011_event, s); |
309 | 308 |
} |
310 | 309 |
register_savevm("pl011_uart", -1, 1, pl011_save, pl011_load, s); |
311 | 310 |
} |
311 |
|
|
312 |
static void pl011_init_arm(SysBusDevice *dev) |
|
313 |
{ |
|
314 |
pl011_init(dev, pl011_id_arm); |
|
315 |
} |
|
316 |
|
|
317 |
static void pl011_init_luminary(SysBusDevice *dev) |
|
318 |
{ |
|
319 |
pl011_init(dev, pl011_id_luminary); |
|
320 |
} |
|
321 |
|
|
322 |
static void pl011_register_devices(void) |
|
323 |
{ |
|
324 |
sysbus_register_dev("pl011", sizeof(pl011_state), |
|
325 |
pl011_init_arm); |
|
326 |
sysbus_register_dev("pl011_luminary", sizeof(pl011_state), |
|
327 |
pl011_init_luminary); |
|
328 |
} |
|
329 |
|
|
330 |
device_init(pl011_register_devices) |
Also available in: Unified diff