2 * Arm PrimeCell PL011 UART
4 * Copyright (c) 2006 CodeSourcery.
5 * Written by Paul Brook
7 * This code is licensed under the GPL.
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)
21 #include "qemu/osdep.h"
22 #include "qapi/error.h"
23 #include "hw/char/pl011.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"
33 #include "qemu/module.h"
36 DeviceState
*pl011_create(hwaddr addr
, qemu_irq irq
, Chardev
*chr
)
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
);
51 #define PL011_INT_TX 0x20
52 #define PL011_INT_RX 0x10
54 #define PL011_FLAG_TXFE 0x80
55 #define PL011_FLAG_RXFF 0x40
56 #define PL011_FLAG_TXFF 0x20
57 #define PL011_FLAG_RXFE 0x10
59 /* Interrupt status bits in UARTRIS, UARTMIS, UARTIMSC */
60 #define INT_OE (1 << 10)
61 #define INT_BE (1 << 9)
62 #define INT_PE (1 << 8)
63 #define INT_FE (1 << 7)
64 #define INT_RT (1 << 6)
65 #define INT_TX (1 << 5)
66 #define INT_RX (1 << 4)
67 #define INT_DSR (1 << 3)
68 #define INT_DCD (1 << 2)
69 #define INT_CTS (1 << 1)
70 #define INT_RI (1 << 0)
71 #define INT_E (INT_OE | INT_BE | INT_PE | INT_FE)
72 #define INT_MS (INT_RI | INT_DSR | INT_DCD | INT_CTS)
74 static const unsigned char pl011_id_arm
[8] =
75 { 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
76 static const unsigned char pl011_id_luminary
[8] =
77 { 0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 };
79 /* Which bits in the interrupt status matter for each outbound IRQ line ? */
80 static const uint32_t irqmask
[] = {
81 INT_E
| INT_MS
| INT_RT
| INT_TX
| INT_RX
, /* combined IRQ */
89 static void pl011_update(PL011State
*s
)
94 flags
= s
->int_level
& s
->int_enabled
;
95 trace_pl011_irq_state(flags
!= 0);
96 for (i
= 0; i
< ARRAY_SIZE(s
->irq
); i
++) {
97 qemu_set_irq(s
->irq
[i
], (flags
& irqmask
[i
]) != 0);
101 static bool pl011_is_fifo_enabled(PL011State
*s
)
103 return (s
->lcr
& 0x10) != 0;
106 static inline unsigned pl011_get_fifo_depth(PL011State
*s
)
108 /* Note: FIFO depth is expected to be power-of-2 */
109 return pl011_is_fifo_enabled(s
) ? PL011_FIFO_DEPTH
: 1;
112 static inline void pl011_reset_fifo(PL011State
*s
)
117 /* Reset FIFO flags */
118 s
->flags
&= ~(PL011_FLAG_RXFF
| PL011_FLAG_TXFF
);
119 s
->flags
|= PL011_FLAG_RXFE
| PL011_FLAG_TXFE
;
122 static uint64_t pl011_read(void *opaque
, hwaddr offset
,
125 PL011State
*s
= (PL011State
*)opaque
;
129 switch (offset
>> 2) {
131 s
->flags
&= ~PL011_FLAG_RXFF
;
132 c
= s
->read_fifo
[s
->read_pos
];
133 if (s
->read_count
> 0) {
135 s
->read_pos
= (s
->read_pos
+ 1) & (pl011_get_fifo_depth(s
) - 1);
137 if (s
->read_count
== 0) {
138 s
->flags
|= PL011_FLAG_RXFE
;
140 if (s
->read_count
== s
->read_trigger
- 1)
141 s
->int_level
&= ~ PL011_INT_RX
;
142 trace_pl011_read_fifo(s
->read_count
);
145 qemu_chr_fe_accept_input(&s
->chr
);
148 case 1: /* UARTRSR */
154 case 8: /* UARTILPR */
157 case 9: /* UARTIBRD */
160 case 10: /* UARTFBRD */
163 case 11: /* UARTLCR_H */
166 case 12: /* UARTCR */
169 case 13: /* UARTIFLS */
172 case 14: /* UARTIMSC */
175 case 15: /* UARTRIS */
178 case 16: /* UARTMIS */
179 r
= s
->int_level
& s
->int_enabled
;
181 case 18: /* UARTDMACR */
184 case 0x3f8 ... 0x400:
185 r
= s
->id
[(offset
- 0xfe0) >> 2];
188 qemu_log_mask(LOG_GUEST_ERROR
,
189 "pl011_read: Bad offset 0x%x\n", (int)offset
);
194 trace_pl011_read(offset
, r
);
198 static void pl011_set_read_trigger(PL011State
*s
)
201 /* The docs say the RX interrupt is triggered when the FIFO exceeds
202 the threshold. However linux only reads the FIFO in response to an
203 interrupt. Triggering the interrupt when the FIFO is non-empty seems
204 to make things work. */
206 s
->read_trigger
= (s
->ifl
>> 1) & 0x1c;
212 static unsigned int pl011_get_baudrate(const PL011State
*s
)
220 clk
= clock_get_hz(s
->clk
);
221 return (clk
/ ((s
->ibrd
<< 6) + s
->fbrd
)) << 2;
224 static void pl011_trace_baudrate_change(const PL011State
*s
)
226 trace_pl011_baudrate_change(pl011_get_baudrate(s
),
227 clock_get_hz(s
->clk
),
231 static void pl011_write(void *opaque
, hwaddr offset
,
232 uint64_t value
, unsigned size
)
234 PL011State
*s
= (PL011State
*)opaque
;
237 trace_pl011_write(offset
, value
);
239 switch (offset
>> 2) {
241 /* ??? Check if transmitter is enabled. */
243 /* XXX this blocks entire thread. Rewrite to use
244 * qemu_chr_fe_write and background I/O callbacks */
245 qemu_chr_fe_write_all(&s
->chr
, &ch
, 1);
246 s
->int_level
|= PL011_INT_TX
;
249 case 1: /* UARTRSR/UARTECR */
253 /* Writes to Flag register are ignored. */
255 case 8: /* UARTUARTILPR */
258 case 9: /* UARTIBRD */
260 pl011_trace_baudrate_change(s
);
262 case 10: /* UARTFBRD */
264 pl011_trace_baudrate_change(s
);
266 case 11: /* UARTLCR_H */
267 /* Reset the FIFO state on FIFO enable or disable */
268 if ((s
->lcr
^ value
) & 0x10) {
271 if ((s
->lcr
^ value
) & 0x1) {
272 int break_enable
= value
& 0x1;
273 qemu_chr_fe_ioctl(&s
->chr
, CHR_IOCTL_SERIAL_SET_BREAK
,
277 pl011_set_read_trigger(s
);
279 case 12: /* UARTCR */
280 /* ??? Need to implement the enable and loopback bits. */
283 case 13: /* UARTIFS */
285 pl011_set_read_trigger(s
);
287 case 14: /* UARTIMSC */
288 s
->int_enabled
= value
;
291 case 17: /* UARTICR */
292 s
->int_level
&= ~value
;
295 case 18: /* UARTDMACR */
298 qemu_log_mask(LOG_UNIMP
, "pl011: DMA not implemented\n");
302 qemu_log_mask(LOG_GUEST_ERROR
,
303 "pl011_write: Bad offset 0x%x\n", (int)offset
);
307 static int pl011_can_receive(void *opaque
)
309 PL011State
*s
= (PL011State
*)opaque
;
312 r
= s
->read_count
< pl011_get_fifo_depth(s
);
313 trace_pl011_can_receive(s
->lcr
, s
->read_count
, r
);
317 static void pl011_put_fifo(void *opaque
, uint32_t value
)
319 PL011State
*s
= (PL011State
*)opaque
;
323 pipe_depth
= pl011_get_fifo_depth(s
);
324 slot
= (s
->read_pos
+ s
->read_count
) & (pipe_depth
- 1);
325 s
->read_fifo
[slot
] = value
;
327 s
->flags
&= ~PL011_FLAG_RXFE
;
328 trace_pl011_put_fifo(value
, s
->read_count
);
329 if (s
->read_count
== pipe_depth
) {
330 trace_pl011_put_fifo_full();
331 s
->flags
|= PL011_FLAG_RXFF
;
333 if (s
->read_count
== s
->read_trigger
) {
334 s
->int_level
|= PL011_INT_RX
;
339 static void pl011_receive(void *opaque
, const uint8_t *buf
, int size
)
341 pl011_put_fifo(opaque
, *buf
);
344 static void pl011_event(void *opaque
, QEMUChrEvent event
)
346 if (event
== CHR_EVENT_BREAK
)
347 pl011_put_fifo(opaque
, 0x400);
350 static void pl011_clock_update(void *opaque
, ClockEvent event
)
352 PL011State
*s
= PL011(opaque
);
354 pl011_trace_baudrate_change(s
);
357 static const MemoryRegionOps pl011_ops
= {
359 .write
= pl011_write
,
360 .endianness
= DEVICE_NATIVE_ENDIAN
,
363 static bool pl011_clock_needed(void *opaque
)
365 PL011State
*s
= PL011(opaque
);
367 return s
->migrate_clk
;
370 static const VMStateDescription vmstate_pl011_clock
= {
371 .name
= "pl011/clock",
373 .minimum_version_id
= 1,
374 .needed
= pl011_clock_needed
,
375 .fields
= (VMStateField
[]) {
376 VMSTATE_CLOCK(clk
, PL011State
),
377 VMSTATE_END_OF_LIST()
381 static int pl011_post_load(void *opaque
, int version_id
)
383 PL011State
* s
= opaque
;
385 /* Sanity-check input state */
386 if (s
->read_pos
>= ARRAY_SIZE(s
->read_fifo
) ||
387 s
->read_count
> ARRAY_SIZE(s
->read_fifo
)) {
391 if (!pl011_is_fifo_enabled(s
) && s
->read_count
> 0 && s
->read_pos
> 0) {
393 * Older versions of PL011 didn't ensure that the single
394 * character in the FIFO in FIFO-disabled mode is in
395 * element 0 of the array; convert to follow the current
396 * code's assumptions.
398 s
->read_fifo
[0] = s
->read_fifo
[s
->read_pos
];
405 static const VMStateDescription vmstate_pl011
= {
408 .minimum_version_id
= 2,
409 .post_load
= pl011_post_load
,
410 .fields
= (VMStateField
[]) {
411 VMSTATE_UINT32(readbuff
, PL011State
),
412 VMSTATE_UINT32(flags
, PL011State
),
413 VMSTATE_UINT32(lcr
, PL011State
),
414 VMSTATE_UINT32(rsr
, PL011State
),
415 VMSTATE_UINT32(cr
, PL011State
),
416 VMSTATE_UINT32(dmacr
, PL011State
),
417 VMSTATE_UINT32(int_enabled
, PL011State
),
418 VMSTATE_UINT32(int_level
, PL011State
),
419 VMSTATE_UINT32_ARRAY(read_fifo
, PL011State
, PL011_FIFO_DEPTH
),
420 VMSTATE_UINT32(ilpr
, PL011State
),
421 VMSTATE_UINT32(ibrd
, PL011State
),
422 VMSTATE_UINT32(fbrd
, PL011State
),
423 VMSTATE_UINT32(ifl
, PL011State
),
424 VMSTATE_INT32(read_pos
, PL011State
),
425 VMSTATE_INT32(read_count
, PL011State
),
426 VMSTATE_INT32(read_trigger
, PL011State
),
427 VMSTATE_END_OF_LIST()
429 .subsections
= (const VMStateDescription
* []) {
430 &vmstate_pl011_clock
,
435 static Property pl011_properties
[] = {
436 DEFINE_PROP_CHR("chardev", PL011State
, chr
),
437 DEFINE_PROP_BOOL("migrate-clk", PL011State
, migrate_clk
, true),
438 DEFINE_PROP_END_OF_LIST(),
441 static void pl011_init(Object
*obj
)
443 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
444 PL011State
*s
= PL011(obj
);
447 memory_region_init_io(&s
->iomem
, OBJECT(s
), &pl011_ops
, s
, "pl011", 0x1000);
448 sysbus_init_mmio(sbd
, &s
->iomem
);
449 for (i
= 0; i
< ARRAY_SIZE(s
->irq
); i
++) {
450 sysbus_init_irq(sbd
, &s
->irq
[i
]);
453 s
->clk
= qdev_init_clock_in(DEVICE(obj
), "clk", pl011_clock_update
, s
,
456 s
->id
= pl011_id_arm
;
459 static void pl011_realize(DeviceState
*dev
, Error
**errp
)
461 PL011State
*s
= PL011(dev
);
463 qemu_chr_fe_set_handlers(&s
->chr
, pl011_can_receive
, pl011_receive
,
464 pl011_event
, NULL
, s
, NULL
, true);
467 static void pl011_reset(DeviceState
*dev
)
469 PL011State
*s
= PL011(dev
);
486 static void pl011_class_init(ObjectClass
*oc
, void *data
)
488 DeviceClass
*dc
= DEVICE_CLASS(oc
);
490 dc
->realize
= pl011_realize
;
491 dc
->reset
= pl011_reset
;
492 dc
->vmsd
= &vmstate_pl011
;
493 device_class_set_props(dc
, pl011_properties
);
496 static const TypeInfo pl011_arm_info
= {
498 .parent
= TYPE_SYS_BUS_DEVICE
,
499 .instance_size
= sizeof(PL011State
),
500 .instance_init
= pl011_init
,
501 .class_init
= pl011_class_init
,
504 static void pl011_luminary_init(Object
*obj
)
506 PL011State
*s
= PL011(obj
);
508 s
->id
= pl011_id_luminary
;
511 static const TypeInfo pl011_luminary_info
= {
512 .name
= TYPE_PL011_LUMINARY
,
513 .parent
= TYPE_PL011
,
514 .instance_init
= pl011_luminary_init
,
517 static void pl011_register_types(void)
519 type_register_static(&pl011_arm_info
);
520 type_register_static(&pl011_luminary_info
);
523 type_init(pl011_register_types
)