]> git.proxmox.com Git - mirror_qemu.git/blob - hw/char/pl011.c
Merge tag 'pw-pull-request' of https://gitlab.com/marcandre.lureau/qemu into staging
[mirror_qemu.git] / hw / char / pl011.c
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 #define PL011_INT_TX 0x20
52 #define PL011_INT_RX 0x10
53
54 #define PL011_FLAG_TXFE 0x80
55 #define PL011_FLAG_RXFF 0x40
56 #define PL011_FLAG_TXFF 0x20
57 #define PL011_FLAG_RXFE 0x10
58
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)
73
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 };
78
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 */
82 INT_RX,
83 INT_TX,
84 INT_RT,
85 INT_MS,
86 INT_E,
87 };
88
89 static void pl011_update(PL011State *s)
90 {
91 uint32_t flags;
92 int i;
93
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);
98 }
99 }
100
101 static bool pl011_is_fifo_enabled(PL011State *s)
102 {
103 return (s->lcr & 0x10) != 0;
104 }
105
106 static inline unsigned pl011_get_fifo_depth(PL011State *s)
107 {
108 /* Note: FIFO depth is expected to be power-of-2 */
109 return pl011_is_fifo_enabled(s) ? PL011_FIFO_DEPTH : 1;
110 }
111
112 static inline void pl011_reset_fifo(PL011State *s)
113 {
114 s->read_count = 0;
115 s->read_pos = 0;
116
117 /* Reset FIFO flags */
118 s->flags &= ~(PL011_FLAG_RXFF | PL011_FLAG_TXFF);
119 s->flags |= PL011_FLAG_RXFE | PL011_FLAG_TXFE;
120 }
121
122 static uint64_t pl011_read(void *opaque, hwaddr offset,
123 unsigned size)
124 {
125 PL011State *s = (PL011State *)opaque;
126 uint32_t c;
127 uint64_t r;
128
129 switch (offset >> 2) {
130 case 0: /* UARTDR */
131 s->flags &= ~PL011_FLAG_RXFF;
132 c = s->read_fifo[s->read_pos];
133 if (s->read_count > 0) {
134 s->read_count--;
135 s->read_pos = (s->read_pos + 1) & (pl011_get_fifo_depth(s) - 1);
136 }
137 if (s->read_count == 0) {
138 s->flags |= PL011_FLAG_RXFE;
139 }
140 if (s->read_count == s->read_trigger - 1)
141 s->int_level &= ~ PL011_INT_RX;
142 trace_pl011_read_fifo(s->read_count);
143 s->rsr = c >> 8;
144 pl011_update(s);
145 qemu_chr_fe_accept_input(&s->chr);
146 r = c;
147 break;
148 case 1: /* UARTRSR */
149 r = s->rsr;
150 break;
151 case 6: /* UARTFR */
152 r = s->flags;
153 break;
154 case 8: /* UARTILPR */
155 r = s->ilpr;
156 break;
157 case 9: /* UARTIBRD */
158 r = s->ibrd;
159 break;
160 case 10: /* UARTFBRD */
161 r = s->fbrd;
162 break;
163 case 11: /* UARTLCR_H */
164 r = s->lcr;
165 break;
166 case 12: /* UARTCR */
167 r = s->cr;
168 break;
169 case 13: /* UARTIFLS */
170 r = s->ifl;
171 break;
172 case 14: /* UARTIMSC */
173 r = s->int_enabled;
174 break;
175 case 15: /* UARTRIS */
176 r = s->int_level;
177 break;
178 case 16: /* UARTMIS */
179 r = s->int_level & s->int_enabled;
180 break;
181 case 18: /* UARTDMACR */
182 r = s->dmacr;
183 break;
184 case 0x3f8 ... 0x400:
185 r = s->id[(offset - 0xfe0) >> 2];
186 break;
187 default:
188 qemu_log_mask(LOG_GUEST_ERROR,
189 "pl011_read: Bad offset 0x%x\n", (int)offset);
190 r = 0;
191 break;
192 }
193
194 trace_pl011_read(offset, r);
195 return r;
196 }
197
198 static void pl011_set_read_trigger(PL011State *s)
199 {
200 #if 0
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. */
205 if (s->lcr & 0x10)
206 s->read_trigger = (s->ifl >> 1) & 0x1c;
207 else
208 #endif
209 s->read_trigger = 1;
210 }
211
212 static unsigned int pl011_get_baudrate(const PL011State *s)
213 {
214 uint64_t clk;
215
216 if (s->ibrd == 0) {
217 return 0;
218 }
219
220 clk = clock_get_hz(s->clk);
221 return (clk / ((s->ibrd << 6) + s->fbrd)) << 2;
222 }
223
224 static void pl011_trace_baudrate_change(const PL011State *s)
225 {
226 trace_pl011_baudrate_change(pl011_get_baudrate(s),
227 clock_get_hz(s->clk),
228 s->ibrd, s->fbrd);
229 }
230
231 static void pl011_write(void *opaque, hwaddr offset,
232 uint64_t value, unsigned size)
233 {
234 PL011State *s = (PL011State *)opaque;
235 unsigned char ch;
236
237 trace_pl011_write(offset, value);
238
239 switch (offset >> 2) {
240 case 0: /* UARTDR */
241 /* ??? Check if transmitter is enabled. */
242 ch = value;
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;
247 pl011_update(s);
248 break;
249 case 1: /* UARTRSR/UARTECR */
250 s->rsr = 0;
251 break;
252 case 6: /* UARTFR */
253 /* Writes to Flag register are ignored. */
254 break;
255 case 8: /* UARTUARTILPR */
256 s->ilpr = value;
257 break;
258 case 9: /* UARTIBRD */
259 s->ibrd = value;
260 pl011_trace_baudrate_change(s);
261 break;
262 case 10: /* UARTFBRD */
263 s->fbrd = value;
264 pl011_trace_baudrate_change(s);
265 break;
266 case 11: /* UARTLCR_H */
267 /* Reset the FIFO state on FIFO enable or disable */
268 if ((s->lcr ^ value) & 0x10) {
269 pl011_reset_fifo(s);
270 }
271 if ((s->lcr ^ value) & 0x1) {
272 int break_enable = value & 0x1;
273 qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
274 &break_enable);
275 }
276 s->lcr = value;
277 pl011_set_read_trigger(s);
278 break;
279 case 12: /* UARTCR */
280 /* ??? Need to implement the enable and loopback bits. */
281 s->cr = value;
282 break;
283 case 13: /* UARTIFS */
284 s->ifl = value;
285 pl011_set_read_trigger(s);
286 break;
287 case 14: /* UARTIMSC */
288 s->int_enabled = value;
289 pl011_update(s);
290 break;
291 case 17: /* UARTICR */
292 s->int_level &= ~value;
293 pl011_update(s);
294 break;
295 case 18: /* UARTDMACR */
296 s->dmacr = value;
297 if (value & 3) {
298 qemu_log_mask(LOG_UNIMP, "pl011: DMA not implemented\n");
299 }
300 break;
301 default:
302 qemu_log_mask(LOG_GUEST_ERROR,
303 "pl011_write: Bad offset 0x%x\n", (int)offset);
304 }
305 }
306
307 static int pl011_can_receive(void *opaque)
308 {
309 PL011State *s = (PL011State *)opaque;
310 int r;
311
312 r = s->read_count < pl011_get_fifo_depth(s);
313 trace_pl011_can_receive(s->lcr, s->read_count, r);
314 return r;
315 }
316
317 static void pl011_put_fifo(void *opaque, uint32_t value)
318 {
319 PL011State *s = (PL011State *)opaque;
320 int slot;
321 unsigned pipe_depth;
322
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;
326 s->read_count++;
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;
332 }
333 if (s->read_count == s->read_trigger) {
334 s->int_level |= PL011_INT_RX;
335 pl011_update(s);
336 }
337 }
338
339 static void pl011_receive(void *opaque, const uint8_t *buf, int size)
340 {
341 pl011_put_fifo(opaque, *buf);
342 }
343
344 static void pl011_event(void *opaque, QEMUChrEvent event)
345 {
346 if (event == CHR_EVENT_BREAK)
347 pl011_put_fifo(opaque, 0x400);
348 }
349
350 static void pl011_clock_update(void *opaque, ClockEvent event)
351 {
352 PL011State *s = PL011(opaque);
353
354 pl011_trace_baudrate_change(s);
355 }
356
357 static const MemoryRegionOps pl011_ops = {
358 .read = pl011_read,
359 .write = pl011_write,
360 .endianness = DEVICE_NATIVE_ENDIAN,
361 };
362
363 static bool pl011_clock_needed(void *opaque)
364 {
365 PL011State *s = PL011(opaque);
366
367 return s->migrate_clk;
368 }
369
370 static const VMStateDescription vmstate_pl011_clock = {
371 .name = "pl011/clock",
372 .version_id = 1,
373 .minimum_version_id = 1,
374 .needed = pl011_clock_needed,
375 .fields = (VMStateField[]) {
376 VMSTATE_CLOCK(clk, PL011State),
377 VMSTATE_END_OF_LIST()
378 }
379 };
380
381 static int pl011_post_load(void *opaque, int version_id)
382 {
383 PL011State* s = opaque;
384
385 /* Sanity-check input state */
386 if (s->read_pos >= ARRAY_SIZE(s->read_fifo) ||
387 s->read_count > ARRAY_SIZE(s->read_fifo)) {
388 return -1;
389 }
390
391 if (!pl011_is_fifo_enabled(s) && s->read_count > 0 && s->read_pos > 0) {
392 /*
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.
397 */
398 s->read_fifo[0] = s->read_fifo[s->read_pos];
399 s->read_pos = 0;
400 }
401
402 return 0;
403 }
404
405 static const VMStateDescription vmstate_pl011 = {
406 .name = "pl011",
407 .version_id = 2,
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()
428 },
429 .subsections = (const VMStateDescription * []) {
430 &vmstate_pl011_clock,
431 NULL
432 }
433 };
434
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(),
439 };
440
441 static void pl011_init(Object *obj)
442 {
443 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
444 PL011State *s = PL011(obj);
445 int i;
446
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]);
451 }
452
453 s->clk = qdev_init_clock_in(DEVICE(obj), "clk", pl011_clock_update, s,
454 ClockUpdate);
455
456 s->id = pl011_id_arm;
457 }
458
459 static void pl011_realize(DeviceState *dev, Error **errp)
460 {
461 PL011State *s = PL011(dev);
462
463 qemu_chr_fe_set_handlers(&s->chr, pl011_can_receive, pl011_receive,
464 pl011_event, NULL, s, NULL, true);
465 }
466
467 static void pl011_reset(DeviceState *dev)
468 {
469 PL011State *s = PL011(dev);
470
471 s->lcr = 0;
472 s->rsr = 0;
473 s->dmacr = 0;
474 s->int_enabled = 0;
475 s->int_level = 0;
476 s->ilpr = 0;
477 s->ibrd = 0;
478 s->fbrd = 0;
479 s->read_trigger = 1;
480 s->ifl = 0x12;
481 s->cr = 0x300;
482 s->flags = 0;
483 pl011_reset_fifo(s);
484 }
485
486 static void pl011_class_init(ObjectClass *oc, void *data)
487 {
488 DeviceClass *dc = DEVICE_CLASS(oc);
489
490 dc->realize = pl011_realize;
491 dc->reset = pl011_reset;
492 dc->vmsd = &vmstate_pl011;
493 device_class_set_props(dc, pl011_properties);
494 }
495
496 static const TypeInfo pl011_arm_info = {
497 .name = TYPE_PL011,
498 .parent = TYPE_SYS_BUS_DEVICE,
499 .instance_size = sizeof(PL011State),
500 .instance_init = pl011_init,
501 .class_init = pl011_class_init,
502 };
503
504 static void pl011_luminary_init(Object *obj)
505 {
506 PL011State *s = PL011(obj);
507
508 s->id = pl011_id_luminary;
509 }
510
511 static const TypeInfo pl011_luminary_info = {
512 .name = TYPE_PL011_LUMINARY,
513 .parent = TYPE_PL011,
514 .instance_init = pl011_luminary_init,
515 };
516
517 static void pl011_register_types(void)
518 {
519 type_register_static(&pl011_arm_info);
520 type_register_static(&pl011_luminary_info);
521 }
522
523 type_init(pl011_register_types)