1 /*
2 * Arm PrimeCell PL011 UART
3 *
4 * Copyright (c) 2006 CodeSourcery.
5 * Written by Paul Brook
6 *
7 * This code is licensed under the GPL.
8 */
9
10 /*
11 * QEMU interface:
12 * + sysbus MMIO region 0: device registers
13 * + sysbus IRQ 0: UARTINTR (combined interrupt line)
14 * + sysbus IRQ 1: UARTRXINTR (receive FIFO interrupt line)
15 * + sysbus IRQ 2: UARTTXINTR (transmit FIFO interrupt line)
16 * + sysbus IRQ 3: UARTRTINTR (receive timeout interrupt line)
17 * + sysbus IRQ 4: UARTMSINTR (momem status interrupt line)
18 * + sysbus IRQ 5: UARTEINTR (error interrupt line)
19 */
20
21 #include "qemu/osdep.h"
22 #include "qapi/error.h"
23 #include "hw/char/pl011.h"
24 #include "hw/irq.h"
25 #include "hw/sysbus.h"
26 #include "hw/qdev-clock.h"
27 #include "hw/qdev-properties.h"
28 #include "hw/qdev-properties-system.h"
29 #include "migration/vmstate.h"
30 #include "chardev/char-fe.h"
31 #include "chardev/char-serial.h"
32 #include "qemu/log.h"
33 #include "qemu/module.h"
34 #include "trace.h"
35
pl011_create(hwaddr addr,qemu_irq irq,Chardev * chr)36 DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr)
37 {
38 DeviceState *dev;
39 SysBusDevice *s;
40
41 dev = qdev_new("pl011");
42 s = SYS_BUS_DEVICE(dev);
43 qdev_prop_set_chr(dev, "chardev", chr);
44 sysbus_realize_and_unref(s, &error_fatal);
45 sysbus_mmio_map(s, 0, addr);
46 sysbus_connect_irq(s, 0, irq);
47
48 return dev;
49 }
50
51 /* Flag Register, UARTFR */
52 #define PL011_FLAG_RI 0x100
53 #define PL011_FLAG_TXFE 0x80
54 #define PL011_FLAG_RXFF 0x40
55 #define PL011_FLAG_TXFF 0x20
56 #define PL011_FLAG_RXFE 0x10
57 #define PL011_FLAG_DCD 0x04
58 #define PL011_FLAG_DSR 0x02
59 #define PL011_FLAG_CTS 0x01
60
61 /* Data Register, UARTDR */
62 #define DR_BE (1 << 10)
63
64 /* Interrupt status bits in UARTRIS, UARTMIS, UARTIMSC */
65 #define INT_OE (1 << 10)
66 #define INT_BE (1 << 9)
67 #define INT_PE (1 << 8)
68 #define INT_FE (1 << 7)
69 #define INT_RT (1 << 6)
70 #define INT_TX (1 << 5)
71 #define INT_RX (1 << 4)
72 #define INT_DSR (1 << 3)
73 #define INT_DCD (1 << 2)
74 #define INT_CTS (1 << 1)
75 #define INT_RI (1 << 0)
76 #define INT_E (INT_OE | INT_BE | INT_PE | INT_FE)
77 #define INT_MS (INT_RI | INT_DSR | INT_DCD | INT_CTS)
78
79 /* Line Control Register, UARTLCR_H */
80 #define LCR_FEN (1 << 4)
81 #define LCR_BRK (1 << 0)
82
83 /* Control Register, UARTCR */
84 #define CR_OUT2 (1 << 13)
85 #define CR_OUT1 (1 << 12)
86 #define CR_RTS (1 << 11)
87 #define CR_DTR (1 << 10)
88 #define CR_LBE (1 << 7)
89
90 /* Integer Baud Rate Divider, UARTIBRD */
91 #define IBRD_MASK 0xffff
92
93 /* Fractional Baud Rate Divider, UARTFBRD */
94 #define FBRD_MASK 0x3f
95
96 static const unsigned char pl011_id_arm[8] =
97 { 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
98 static const unsigned char pl011_id_luminary[8] =
99 { 0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 };
100
pl011_regname(hwaddr offset)101 static const char *pl011_regname(hwaddr offset)
102 {
103 static const char *const rname[] = {
104 [0] = "DR", [1] = "RSR", [6] = "FR", [8] = "ILPR", [9] = "IBRD",
105 [10] = "FBRD", [11] = "LCRH", [12] = "CR", [13] = "IFLS", [14] = "IMSC",
106 [15] = "RIS", [16] = "MIS", [17] = "ICR", [18] = "DMACR",
107 };
108 unsigned idx = offset >> 2;
109
110 if (idx < ARRAY_SIZE(rname) && rname[idx]) {
111 return rname[idx];
112 }
113 if (idx >= 0x3f8 && idx <= 0x400) {
114 return "ID";
115 }
116 return "UNKN";
117 }
118
119 /* Which bits in the interrupt status matter for each outbound IRQ line ? */
120 static const uint32_t irqmask[] = {
121 INT_E | INT_MS | INT_RT | INT_TX | INT_RX, /* combined IRQ */
122 INT_RX,
123 INT_TX,
124 INT_RT,
125 INT_MS,
126 INT_E,
127 };
128
pl011_update(PL011State * s)129 static void pl011_update(PL011State *s)
130 {
131 uint32_t flags;
132 int i;
133
134 flags = s->int_level & s->int_enabled;
135 trace_pl011_irq_state(flags != 0);
136 for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
137 qemu_set_irq(s->irq[i], (flags & irqmask[i]) != 0);
138 }
139 }
140
pl011_is_fifo_enabled(PL011State * s)141 static bool pl011_is_fifo_enabled(PL011State *s)
142 {
143 return (s->lcr & LCR_FEN) != 0;
144 }
145
pl011_get_fifo_depth(PL011State * s)146 static inline unsigned pl011_get_fifo_depth(PL011State *s)
147 {
148 /* Note: FIFO depth is expected to be power-of-2 */
149 return pl011_is_fifo_enabled(s) ? PL011_FIFO_DEPTH : 1;
150 }
151
pl011_reset_fifo(PL011State * s)152 static inline void pl011_reset_fifo(PL011State *s)
153 {
154 s->read_count = 0;
155 s->read_pos = 0;
156
157 /* Reset FIFO flags */
158 s->flags &= ~(PL011_FLAG_RXFF | PL011_FLAG_TXFF);
159 s->flags |= PL011_FLAG_RXFE | PL011_FLAG_TXFE;
160 }
161
pl011_read(void * opaque,hwaddr offset,unsigned size)162 static uint64_t pl011_read(void *opaque, hwaddr offset,
163 unsigned size)
164 {
165 PL011State *s = (PL011State *)opaque;
166 uint32_t c;
167 uint64_t r;
168
169 switch (offset >> 2) {
170 case 0: /* UARTDR */
171 s->flags &= ~PL011_FLAG_RXFF;
172 c = s->read_fifo[s->read_pos];
173 if (s->read_count > 0) {
174 s->read_count--;
175 s->read_pos = (s->read_pos + 1) & (pl011_get_fifo_depth(s) - 1);
176 }
177 if (s->read_count == 0) {
178 s->flags |= PL011_FLAG_RXFE;
179 }
180 if (s->read_count == s->read_trigger - 1)
181 s->int_level &= ~ INT_RX;
182 trace_pl011_read_fifo(s->read_count);
183 s->rsr = c >> 8;
184 pl011_update(s);
185 qemu_chr_fe_accept_input(&s->chr);
186 r = c;
187 break;
188 case 1: /* UARTRSR */
189 r = s->rsr;
190 break;
191 case 6: /* UARTFR */
192 r = s->flags;
193 break;
194 case 8: /* UARTILPR */
195 r = s->ilpr;
196 break;
197 case 9: /* UARTIBRD */
198 r = s->ibrd;
199 break;
200 case 10: /* UARTFBRD */
201 r = s->fbrd;
202 break;
203 case 11: /* UARTLCR_H */
204 r = s->lcr;
205 break;
206 case 12: /* UARTCR */
207 r = s->cr;
208 break;
209 case 13: /* UARTIFLS */
210 r = s->ifl;
211 break;
212 case 14: /* UARTIMSC */
213 r = s->int_enabled;
214 break;
215 case 15: /* UARTRIS */
216 r = s->int_level;
217 break;
218 case 16: /* UARTMIS */
219 r = s->int_level & s->int_enabled;
220 break;
221 case 18: /* UARTDMACR */
222 r = s->dmacr;
223 break;
224 case 0x3f8 ... 0x400:
225 r = s->id[(offset - 0xfe0) >> 2];
226 break;
227 default:
228 qemu_log_mask(LOG_GUEST_ERROR,
229 "pl011_read: Bad offset 0x%x\n", (int)offset);
230 r = 0;
231 break;
232 }
233
234 trace_pl011_read(offset, r, pl011_regname(offset));
235 return r;
236 }
237
pl011_set_read_trigger(PL011State * s)238 static void pl011_set_read_trigger(PL011State *s)
239 {
240 #if 0
241 /* The docs say the RX interrupt is triggered when the FIFO exceeds
242 the threshold. However linux only reads the FIFO in response to an
243 interrupt. Triggering the interrupt when the FIFO is non-empty seems
244 to make things work. */
245 if (s->lcr & LCR_FEN)
246 s->read_trigger = (s->ifl >> 1) & 0x1c;
247 else
248 #endif
249 s->read_trigger = 1;
250 }
251
pl011_get_baudrate(const PL011State * s)252 static unsigned int pl011_get_baudrate(const PL011State *s)
253 {
254 uint64_t clk;
255
256 if (s->ibrd == 0) {
257 return 0;
258 }
259
260 clk = clock_get_hz(s->clk);
261 return (clk / ((s->ibrd << 6) + s->fbrd)) << 2;
262 }
263
pl011_trace_baudrate_change(const PL011State * s)264 static void pl011_trace_baudrate_change(const PL011State *s)
265 {
266 trace_pl011_baudrate_change(pl011_get_baudrate(s),
267 clock_get_hz(s->clk),
268 s->ibrd, s->fbrd);
269 }
270
pl011_loopback_enabled(PL011State * s)271 static bool pl011_loopback_enabled(PL011State *s)
272 {
273 return !!(s->cr & CR_LBE);
274 }
275
pl011_loopback_mdmctrl(PL011State * s)276 static void pl011_loopback_mdmctrl(PL011State *s)
277 {
278 uint32_t cr, fr, il;
279
280 if (!pl011_loopback_enabled(s)) {
281 return;
282 }
283
284 /*
285 * Loopback software-driven modem control outputs to modem status inputs:
286 * FR.RI <= CR.Out2
287 * FR.DCD <= CR.Out1
288 * FR.CTS <= CR.RTS
289 * FR.DSR <= CR.DTR
290 *
291 * The loopback happens immediately even if this call is triggered
292 * by setting only CR.LBE.
293 *
294 * CTS/RTS updates due to enabled hardware flow controls are not
295 * dealt with here.
296 */
297 cr = s->cr;
298 fr = s->flags & ~(PL011_FLAG_RI | PL011_FLAG_DCD |
299 PL011_FLAG_DSR | PL011_FLAG_CTS);
300 fr |= (cr & CR_OUT2) ? PL011_FLAG_RI : 0;
301 fr |= (cr & CR_OUT1) ? PL011_FLAG_DCD : 0;
302 fr |= (cr & CR_RTS) ? PL011_FLAG_CTS : 0;
303 fr |= (cr & CR_DTR) ? PL011_FLAG_DSR : 0;
304
305 /* Change interrupts based on updated FR */
306 il = s->int_level & ~(INT_DSR | INT_DCD | INT_CTS | INT_RI);
307 il |= (fr & PL011_FLAG_DSR) ? INT_DSR : 0;
308 il |= (fr & PL011_FLAG_DCD) ? INT_DCD : 0;
309 il |= (fr & PL011_FLAG_CTS) ? INT_CTS : 0;
310 il |= (fr & PL011_FLAG_RI) ? INT_RI : 0;
311
312 s->flags = fr;
313 s->int_level = il;
314 pl011_update(s);
315 }
316
317 static void pl011_put_fifo(void *opaque, uint32_t value);
318
pl011_loopback_tx(PL011State * s,uint32_t value)319 static void pl011_loopback_tx(PL011State *s, uint32_t value)
320 {
321 if (!pl011_loopback_enabled(s)) {
322 return;
323 }
324
325 /*
326 * Caveat:
327 *
328 * In real hardware, TX loopback happens at the serial-bit level
329 * and then reassembled by the RX logics back into bytes and placed
330 * into the RX fifo. That is, loopback happens after TX fifo.
331 *
332 * Because the real hardware TX fifo is time-drained at the frame
333 * rate governed by the configured serial format, some loopback
334 * bytes in TX fifo may still be able to get into the RX fifo
335 * that could be full at times while being drained at software
336 * pace.
337 *
338 * In such scenario, the RX draining pace is the major factor
339 * deciding which loopback bytes get into the RX fifo, unless
340 * hardware flow-control is enabled.
341 *
342 * For simplicity, the above described is not emulated.
343 */
344 pl011_put_fifo(s, value);
345 }
346
pl011_loopback_break(PL011State * s,int brk_enable)347 static void pl011_loopback_break(PL011State *s, int brk_enable)
348 {
349 if (brk_enable) {
350 pl011_loopback_tx(s, DR_BE);
351 }
352 }
353
pl011_write(void * opaque,hwaddr offset,uint64_t value,unsigned size)354 static void pl011_write(void *opaque, hwaddr offset,
355 uint64_t value, unsigned size)
356 {
357 PL011State *s = (PL011State *)opaque;
358 unsigned char ch;
359
360 trace_pl011_write(offset, value, pl011_regname(offset));
361
362 switch (offset >> 2) {
363 case 0: /* UARTDR */
364 /* ??? Check if transmitter is enabled. */
365 ch = value;
366 /* XXX this blocks entire thread. Rewrite to use
367 * qemu_chr_fe_write and background I/O callbacks */
368 qemu_chr_fe_write_all(&s->chr, &ch, 1);
369 pl011_loopback_tx(s, ch);
370 s->int_level |= INT_TX;
371 pl011_update(s);
372 break;
373 case 1: /* UARTRSR/UARTECR */
374 s->rsr = 0;
375 break;
376 case 6: /* UARTFR */
377 /* Writes to Flag register are ignored. */
378 break;
379 case 8: /* UARTILPR */
380 s->ilpr = value;
381 break;
382 case 9: /* UARTIBRD */
383 s->ibrd = value & IBRD_MASK;
384 pl011_trace_baudrate_change(s);
385 break;
386 case 10: /* UARTFBRD */
387 s->fbrd = value & FBRD_MASK;
388 pl011_trace_baudrate_change(s);
389 break;
390 case 11: /* UARTLCR_H */
391 /* Reset the FIFO state on FIFO enable or disable */
392 if ((s->lcr ^ value) & LCR_FEN) {
393 pl011_reset_fifo(s);
394 }
395 if ((s->lcr ^ value) & LCR_BRK) {
396 int break_enable = value & LCR_BRK;
397 qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
398 &break_enable);
399 pl011_loopback_break(s, break_enable);
400 }
401 s->lcr = value;
402 pl011_set_read_trigger(s);
403 break;
404 case 12: /* UARTCR */
405 /* ??? Need to implement the enable bit. */
406 s->cr = value;
407 pl011_loopback_mdmctrl(s);
408 break;
409 case 13: /* UARTIFS */
410 s->ifl = value;
411 pl011_set_read_trigger(s);
412 break;
413 case 14: /* UARTIMSC */
414 s->int_enabled = value;
415 pl011_update(s);
416 break;
417 case 17: /* UARTICR */
418 s->int_level &= ~value;
419 pl011_update(s);
420 break;
421 case 18: /* UARTDMACR */
422 s->dmacr = value;
423 if (value & 3) {
424 qemu_log_mask(LOG_UNIMP, "pl011: DMA not implemented\n");
425 }
426 break;
427 default:
428 qemu_log_mask(LOG_GUEST_ERROR,
429 "pl011_write: Bad offset 0x%x\n", (int)offset);
430 }
431 }
432
pl011_can_receive(void * opaque)433 static int pl011_can_receive(void *opaque)
434 {
435 PL011State *s = (PL011State *)opaque;
436 int r;
437
438 r = s->read_count < pl011_get_fifo_depth(s);
439 trace_pl011_can_receive(s->lcr, s->read_count, r);
440 return r;
441 }
442
pl011_put_fifo(void * opaque,uint32_t value)443 static void pl011_put_fifo(void *opaque, uint32_t value)
444 {
445 PL011State *s = (PL011State *)opaque;
446 int slot;
447 unsigned pipe_depth;
448
449 pipe_depth = pl011_get_fifo_depth(s);
450 slot = (s->read_pos + s->read_count) & (pipe_depth - 1);
451 s->read_fifo[slot] = value;
452 s->read_count++;
453 s->flags &= ~PL011_FLAG_RXFE;
454 trace_pl011_put_fifo(value, s->read_count);
455 if (s->read_count == pipe_depth) {
456 trace_pl011_put_fifo_full();
457 s->flags |= PL011_FLAG_RXFF;
458 }
459 if (s->read_count == s->read_trigger) {
460 s->int_level |= INT_RX;
461 pl011_update(s);
462 }
463 }
464
pl011_receive(void * opaque,const uint8_t * buf,int size)465 static void pl011_receive(void *opaque, const uint8_t *buf, int size)
466 {
467 /*
468 * In loopback mode, the RX input signal is internally disconnected
469 * from the entire receiving logics; thus, all inputs are ignored,
470 * and BREAK detection on RX input signal is also not performed.
471 */
472 if (pl011_loopback_enabled(opaque)) {
473 return;
474 }
475
476 pl011_put_fifo(opaque, *buf);
477 }
478
pl011_event(void * opaque,QEMUChrEvent event)479 static void pl011_event(void *opaque, QEMUChrEvent event)
480 {
481 if (event == CHR_EVENT_BREAK && !pl011_loopback_enabled(opaque)) {
482 pl011_put_fifo(opaque, DR_BE);
483 }
484 }
485
pl011_clock_update(void * opaque,ClockEvent event)486 static void pl011_clock_update(void *opaque, ClockEvent event)
487 {
488 PL011State *s = PL011(opaque);
489
490 pl011_trace_baudrate_change(s);
491 }
492
493 static const MemoryRegionOps pl011_ops = {
494 .read = pl011_read,
495 .write = pl011_write,
496 .endianness = DEVICE_NATIVE_ENDIAN,
497 .impl.min_access_size = 4,
498 .impl.max_access_size = 4,
499 };
500
pl011_clock_needed(void * opaque)501 static bool pl011_clock_needed(void *opaque)
502 {
503 PL011State *s = PL011(opaque);
504
505 return s->migrate_clk;
506 }
507
508 static const VMStateDescription vmstate_pl011_clock = {
509 .name = "pl011/clock",
510 .version_id = 1,
511 .minimum_version_id = 1,
512 .needed = pl011_clock_needed,
513 .fields = (const VMStateField[]) {
514 VMSTATE_CLOCK(clk, PL011State),
515 VMSTATE_END_OF_LIST()
516 }
517 };
518
pl011_post_load(void * opaque,int version_id)519 static int pl011_post_load(void *opaque, int version_id)
520 {
521 PL011State* s = opaque;
522
523 /* Sanity-check input state */
524 if (s->read_pos >= ARRAY_SIZE(s->read_fifo) ||
525 s->read_count > ARRAY_SIZE(s->read_fifo)) {
526 return -1;
527 }
528
529 if (!pl011_is_fifo_enabled(s) && s->read_count > 0 && s->read_pos > 0) {
530 /*
531 * Older versions of PL011 didn't ensure that the single
532 * character in the FIFO in FIFO-disabled mode is in
533 * element 0 of the array; convert to follow the current
534 * code's assumptions.
535 */
536 s->read_fifo[0] = s->read_fifo[s->read_pos];
537 s->read_pos = 0;
538 }
539
540 s->ibrd &= IBRD_MASK;
541 s->fbrd &= FBRD_MASK;
542
543 return 0;
544 }
545
546 static const VMStateDescription vmstate_pl011 = {
547 .name = "pl011",
548 .version_id = 2,
549 .minimum_version_id = 2,
550 .post_load = pl011_post_load,
551 .fields = (const VMStateField[]) {
552 VMSTATE_UINT32(readbuff, PL011State),
553 VMSTATE_UINT32(flags, PL011State),
554 VMSTATE_UINT32(lcr, PL011State),
555 VMSTATE_UINT32(rsr, PL011State),
556 VMSTATE_UINT32(cr, PL011State),
557 VMSTATE_UINT32(dmacr, PL011State),
558 VMSTATE_UINT32(int_enabled, PL011State),
559 VMSTATE_UINT32(int_level, PL011State),
560 VMSTATE_UINT32_ARRAY(read_fifo, PL011State, PL011_FIFO_DEPTH),
561 VMSTATE_UINT32(ilpr, PL011State),
562 VMSTATE_UINT32(ibrd, PL011State),
563 VMSTATE_UINT32(fbrd, PL011State),
564 VMSTATE_UINT32(ifl, PL011State),
565 VMSTATE_INT32(read_pos, PL011State),
566 VMSTATE_INT32(read_count, PL011State),
567 VMSTATE_INT32(read_trigger, PL011State),
568 VMSTATE_END_OF_LIST()
569 },
570 .subsections = (const VMStateDescription * const []) {
571 &vmstate_pl011_clock,
572 NULL
573 }
574 };
575
576 static Property pl011_properties[] = {
577 DEFINE_PROP_CHR("chardev", PL011State, chr),
578 DEFINE_PROP_BOOL("migrate-clk", PL011State, migrate_clk, true),
579 DEFINE_PROP_END_OF_LIST(),
580 };
581
pl011_init(Object * obj)582 static void pl011_init(Object *obj)
583 {
584 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
585 PL011State *s = PL011(obj);
586 int i;
587
588 memory_region_init_io(&s->iomem, OBJECT(s), &pl011_ops, s, "pl011", 0x1000);
589 sysbus_init_mmio(sbd, &s->iomem);
590 for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
591 sysbus_init_irq(sbd, &s->irq[i]);
592 }
593
594 s->clk = qdev_init_clock_in(DEVICE(obj), "clk", pl011_clock_update, s,
595 ClockUpdate);
596
597 s->id = pl011_id_arm;
598 }
599
pl011_realize(DeviceState * dev,Error ** errp)600 static void pl011_realize(DeviceState *dev, Error **errp)
601 {
602 PL011State *s = PL011(dev);
603
604 qemu_chr_fe_set_handlers(&s->chr, pl011_can_receive, pl011_receive,
605 pl011_event, NULL, s, NULL, true);
606 }
607
pl011_reset(DeviceState * dev)608 static void pl011_reset(DeviceState *dev)
609 {
610 PL011State *s = PL011(dev);
611
612 s->lcr = 0;
613 s->rsr = 0;
614 s->dmacr = 0;
615 s->int_enabled = 0;
616 s->int_level = 0;
617 s->ilpr = 0;
618 s->ibrd = 0;
619 s->fbrd = 0;
620 s->read_trigger = 1;
621 s->ifl = 0x12;
622 s->cr = 0x300;
623 s->flags = 0;
624 pl011_reset_fifo(s);
625 }
626
pl011_class_init(ObjectClass * oc,void * data)627 static void pl011_class_init(ObjectClass *oc, void *data)
628 {
629 DeviceClass *dc = DEVICE_CLASS(oc);
630
631 dc->realize = pl011_realize;
632 dc->reset = pl011_reset;
633 dc->vmsd = &vmstate_pl011;
634 device_class_set_props(dc, pl011_properties);
635 }
636
637 static const TypeInfo pl011_arm_info = {
638 .name = TYPE_PL011,
639 .parent = TYPE_SYS_BUS_DEVICE,
640 .instance_size = sizeof(PL011State),
641 .instance_init = pl011_init,
642 .class_init = pl011_class_init,
643 };
644
pl011_luminary_init(Object * obj)645 static void pl011_luminary_init(Object *obj)
646 {
647 PL011State *s = PL011(obj);
648
649 s->id = pl011_id_luminary;
650 }
651
652 static const TypeInfo pl011_luminary_info = {
653 .name = TYPE_PL011_LUMINARY,
654 .parent = TYPE_PL011,
655 .instance_init = pl011_luminary_init,
656 };
657
pl011_register_types(void)658 static void pl011_register_types(void)
659 {
660 type_register_static(&pl011_arm_info);
661 type_register_static(&pl011_luminary_info);
662 }
663
664 type_init(pl011_register_types)
665