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_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
pl011_regname(hwaddr offset)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
pl011_update(PL011State * s)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
pl011_loopback_enabled(PL011State * s)143 static bool pl011_loopback_enabled(PL011State *s)
144 {
145 return !!(s->cr & CR_LBE);
146 }
147
pl011_is_fifo_enabled(PL011State * s)148 static bool pl011_is_fifo_enabled(PL011State *s)
149 {
150 return (s->lcr & LCR_FEN) != 0;
151 }
152
pl011_get_fifo_depth(PL011State * s)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
pl011_reset_rx_fifo(PL011State * s)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
pl011_reset_tx_fifo(PL011State * s)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
pl011_fifo_rx_put(void * opaque,uint32_t value)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
pl011_loopback_tx(PL011State * s,uint32_t value)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
pl011_write_txdata(PL011State * s,uint8_t data)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
pl011_read_rxdata(PL011State * s)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
pl011_read(void * opaque,hwaddr offset,unsigned size)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
pl011_set_read_trigger(PL011State * s)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
pl011_get_baudrate(const PL011State * s)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
pl011_trace_baudrate_change(const PL011State * s)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
pl011_loopback_mdmctrl(PL011State * s)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
pl011_loopback_break(PL011State * s,int brk_enable)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
pl011_write(void * opaque,hwaddr offset,uint64_t value,unsigned size)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
pl011_can_receive(void * opaque)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
pl011_receive(void * opaque,const uint8_t * buf,int size)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
pl011_event(void * opaque,QEMUChrEvent event)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
pl011_clock_update(void * opaque,ClockEvent event)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
pl011_clock_needed(void * opaque)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
pl011_post_load(void * opaque,int version_id)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
pl011_init(Object * obj)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
pl011_realize(DeviceState * dev,Error ** errp)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
pl011_reset(DeviceState * dev)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
pl011_class_init(ObjectClass * oc,void * data)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
pl011_luminary_init(Object * obj)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
pl011_register_types(void)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