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