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_TXFE 0x80
53 #define PL011_FLAG_RXFF 0x40
54 #define PL011_FLAG_TXFF 0x20
55 #define PL011_FLAG_RXFE 0x10
56
57 /* Data Register, UARTDR */
58 #define DR_BE (1 << 10)
59
60 /* Interrupt status bits in UARTRIS, UARTMIS, UARTIMSC */
61 #define INT_OE (1 << 10)
62 #define INT_BE (1 << 9)
63 #define INT_PE (1 << 8)
64 #define INT_FE (1 << 7)
65 #define INT_RT (1 << 6)
66 #define INT_TX (1 << 5)
67 #define INT_RX (1 << 4)
68 #define INT_DSR (1 << 3)
69 #define INT_DCD (1 << 2)
70 #define INT_CTS (1 << 1)
71 #define INT_RI (1 << 0)
72 #define INT_E (INT_OE | INT_BE | INT_PE | INT_FE)
73 #define INT_MS (INT_RI | INT_DSR | INT_DCD | INT_CTS)
74
75 /* Line Control Register, UARTLCR_H */
76 #define LCR_FEN (1 << 4)
77 #define LCR_BRK (1 << 0)
78
79 static const unsigned char pl011_id_arm[8] =
80 { 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
81 static const unsigned char pl011_id_luminary[8] =
82 { 0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 };
83
pl011_regname(hwaddr offset)84 static const char *pl011_regname(hwaddr offset)
85 {
86 static const char *const rname[] = {
87 [0] = "DR", [1] = "RSR", [6] = "FR", [8] = "ILPR", [9] = "IBRD",
88 [10] = "FBRD", [11] = "LCRH", [12] = "CR", [13] = "IFLS", [14] = "IMSC",
89 [15] = "RIS", [16] = "MIS", [17] = "ICR", [18] = "DMACR",
90 };
91 unsigned idx = offset >> 2;
92
93 if (idx < ARRAY_SIZE(rname) && rname[idx]) {
94 return rname[idx];
95 }
96 if (idx >= 0x3f8 && idx <= 0x400) {
97 return "ID";
98 }
99 return "UNKN";
100 }
101
102 /* Which bits in the interrupt status matter for each outbound IRQ line ? */
103 static const uint32_t irqmask[] = {
104 INT_E | INT_MS | INT_RT | INT_TX | INT_RX, /* combined IRQ */
105 INT_RX,
106 INT_TX,
107 INT_RT,
108 INT_MS,
109 INT_E,
110 };
111
pl011_update(PL011State * s)112 static void pl011_update(PL011State *s)
113 {
114 uint32_t flags;
115 int i;
116
117 flags = s->int_level & s->int_enabled;
118 trace_pl011_irq_state(flags != 0);
119 for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
120 qemu_set_irq(s->irq[i], (flags & irqmask[i]) != 0);
121 }
122 }
123
pl011_is_fifo_enabled(PL011State * s)124 static bool pl011_is_fifo_enabled(PL011State *s)
125 {
126 return (s->lcr & LCR_FEN) != 0;
127 }
128
pl011_get_fifo_depth(PL011State * s)129 static inline unsigned pl011_get_fifo_depth(PL011State *s)
130 {
131 /* Note: FIFO depth is expected to be power-of-2 */
132 return pl011_is_fifo_enabled(s) ? PL011_FIFO_DEPTH : 1;
133 }
134
pl011_reset_fifo(PL011State * s)135 static inline void pl011_reset_fifo(PL011State *s)
136 {
137 s->read_count = 0;
138 s->read_pos = 0;
139
140 /* Reset FIFO flags */
141 s->flags &= ~(PL011_FLAG_RXFF | PL011_FLAG_TXFF);
142 s->flags |= PL011_FLAG_RXFE | PL011_FLAG_TXFE;
143 }
144
pl011_read(void * opaque,hwaddr offset,unsigned size)145 static uint64_t pl011_read(void *opaque, hwaddr offset,
146 unsigned size)
147 {
148 PL011State *s = (PL011State *)opaque;
149 uint32_t c;
150 uint64_t r;
151
152 switch (offset >> 2) {
153 case 0: /* UARTDR */
154 s->flags &= ~PL011_FLAG_RXFF;
155 c = s->read_fifo[s->read_pos];
156 if (s->read_count > 0) {
157 s->read_count--;
158 s->read_pos = (s->read_pos + 1) & (pl011_get_fifo_depth(s) - 1);
159 }
160 if (s->read_count == 0) {
161 s->flags |= PL011_FLAG_RXFE;
162 }
163 if (s->read_count == s->read_trigger - 1)
164 s->int_level &= ~ INT_RX;
165 trace_pl011_read_fifo(s->read_count);
166 s->rsr = c >> 8;
167 pl011_update(s);
168 qemu_chr_fe_accept_input(&s->chr);
169 r = c;
170 break;
171 case 1: /* UARTRSR */
172 r = s->rsr;
173 break;
174 case 6: /* UARTFR */
175 r = s->flags;
176 break;
177 case 8: /* UARTILPR */
178 r = s->ilpr;
179 break;
180 case 9: /* UARTIBRD */
181 r = s->ibrd;
182 break;
183 case 10: /* UARTFBRD */
184 r = s->fbrd;
185 break;
186 case 11: /* UARTLCR_H */
187 r = s->lcr;
188 break;
189 case 12: /* UARTCR */
190 r = s->cr;
191 break;
192 case 13: /* UARTIFLS */
193 r = s->ifl;
194 break;
195 case 14: /* UARTIMSC */
196 r = s->int_enabled;
197 break;
198 case 15: /* UARTRIS */
199 r = s->int_level;
200 break;
201 case 16: /* UARTMIS */
202 r = s->int_level & s->int_enabled;
203 break;
204 case 18: /* UARTDMACR */
205 r = s->dmacr;
206 break;
207 case 0x3f8 ... 0x400:
208 r = s->id[(offset - 0xfe0) >> 2];
209 break;
210 default:
211 qemu_log_mask(LOG_GUEST_ERROR,
212 "pl011_read: Bad offset 0x%x\n", (int)offset);
213 r = 0;
214 break;
215 }
216
217 trace_pl011_read(offset, r, pl011_regname(offset));
218 return r;
219 }
220
pl011_set_read_trigger(PL011State * s)221 static void pl011_set_read_trigger(PL011State *s)
222 {
223 #if 0
224 /* The docs say the RX interrupt is triggered when the FIFO exceeds
225 the threshold. However linux only reads the FIFO in response to an
226 interrupt. Triggering the interrupt when the FIFO is non-empty seems
227 to make things work. */
228 if (s->lcr & LCR_FEN)
229 s->read_trigger = (s->ifl >> 1) & 0x1c;
230 else
231 #endif
232 s->read_trigger = 1;
233 }
234
pl011_get_baudrate(const PL011State * s)235 static unsigned int pl011_get_baudrate(const PL011State *s)
236 {
237 uint64_t clk;
238
239 if (s->ibrd == 0) {
240 return 0;
241 }
242
243 clk = clock_get_hz(s->clk);
244 return (clk / ((s->ibrd << 6) + s->fbrd)) << 2;
245 }
246
pl011_trace_baudrate_change(const PL011State * s)247 static void pl011_trace_baudrate_change(const PL011State *s)
248 {
249 trace_pl011_baudrate_change(pl011_get_baudrate(s),
250 clock_get_hz(s->clk),
251 s->ibrd, s->fbrd);
252 }
253
pl011_write(void * opaque,hwaddr offset,uint64_t value,unsigned size)254 static void pl011_write(void *opaque, hwaddr offset,
255 uint64_t value, unsigned size)
256 {
257 PL011State *s = (PL011State *)opaque;
258 unsigned char ch;
259
260 trace_pl011_write(offset, value, pl011_regname(offset));
261
262 switch (offset >> 2) {
263 case 0: /* UARTDR */
264 /* ??? Check if transmitter is enabled. */
265 ch = value;
266 /* XXX this blocks entire thread. Rewrite to use
267 * qemu_chr_fe_write and background I/O callbacks */
268 qemu_chr_fe_write_all(&s->chr, &ch, 1);
269 s->int_level |= INT_TX;
270 pl011_update(s);
271 break;
272 case 1: /* UARTRSR/UARTECR */
273 s->rsr = 0;
274 break;
275 case 6: /* UARTFR */
276 /* Writes to Flag register are ignored. */
277 break;
278 case 8: /* UARTILPR */
279 s->ilpr = value;
280 break;
281 case 9: /* UARTIBRD */
282 s->ibrd = value;
283 pl011_trace_baudrate_change(s);
284 break;
285 case 10: /* UARTFBRD */
286 s->fbrd = value;
287 pl011_trace_baudrate_change(s);
288 break;
289 case 11: /* UARTLCR_H */
290 /* Reset the FIFO state on FIFO enable or disable */
291 if ((s->lcr ^ value) & LCR_FEN) {
292 pl011_reset_fifo(s);
293 }
294 if ((s->lcr ^ value) & LCR_BRK) {
295 int break_enable = value & LCR_BRK;
296 qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
297 &break_enable);
298 }
299 s->lcr = value;
300 pl011_set_read_trigger(s);
301 break;
302 case 12: /* UARTCR */
303 /* ??? Need to implement the enable and loopback bits. */
304 s->cr = value;
305 break;
306 case 13: /* UARTIFS */
307 s->ifl = value;
308 pl011_set_read_trigger(s);
309 break;
310 case 14: /* UARTIMSC */
311 s->int_enabled = value;
312 pl011_update(s);
313 break;
314 case 17: /* UARTICR */
315 s->int_level &= ~value;
316 pl011_update(s);
317 break;
318 case 18: /* UARTDMACR */
319 s->dmacr = value;
320 if (value & 3) {
321 qemu_log_mask(LOG_UNIMP, "pl011: DMA not implemented\n");
322 }
323 break;
324 default:
325 qemu_log_mask(LOG_GUEST_ERROR,
326 "pl011_write: Bad offset 0x%x\n", (int)offset);
327 }
328 }
329
pl011_can_receive(void * opaque)330 static int pl011_can_receive(void *opaque)
331 {
332 PL011State *s = (PL011State *)opaque;
333 int r;
334
335 r = s->read_count < pl011_get_fifo_depth(s);
336 trace_pl011_can_receive(s->lcr, s->read_count, r);
337 return r;
338 }
339
pl011_put_fifo(void * opaque,uint32_t value)340 static void pl011_put_fifo(void *opaque, uint32_t value)
341 {
342 PL011State *s = (PL011State *)opaque;
343 int slot;
344 unsigned pipe_depth;
345
346 pipe_depth = pl011_get_fifo_depth(s);
347 slot = (s->read_pos + s->read_count) & (pipe_depth - 1);
348 s->read_fifo[slot] = value;
349 s->read_count++;
350 s->flags &= ~PL011_FLAG_RXFE;
351 trace_pl011_put_fifo(value, s->read_count);
352 if (s->read_count == pipe_depth) {
353 trace_pl011_put_fifo_full();
354 s->flags |= PL011_FLAG_RXFF;
355 }
356 if (s->read_count == s->read_trigger) {
357 s->int_level |= INT_RX;
358 pl011_update(s);
359 }
360 }
361
pl011_receive(void * opaque,const uint8_t * buf,int size)362 static void pl011_receive(void *opaque, const uint8_t *buf, int size)
363 {
364 pl011_put_fifo(opaque, *buf);
365 }
366
pl011_event(void * opaque,QEMUChrEvent event)367 static void pl011_event(void *opaque, QEMUChrEvent event)
368 {
369 if (event == CHR_EVENT_BREAK) {
370 pl011_put_fifo(opaque, DR_BE);
371 }
372 }
373
pl011_clock_update(void * opaque,ClockEvent event)374 static void pl011_clock_update(void *opaque, ClockEvent event)
375 {
376 PL011State *s = PL011(opaque);
377
378 pl011_trace_baudrate_change(s);
379 }
380
381 static const MemoryRegionOps pl011_ops = {
382 .read = pl011_read,
383 .write = pl011_write,
384 .endianness = DEVICE_NATIVE_ENDIAN,
385 .impl.min_access_size = 4,
386 .impl.max_access_size = 4,
387 };
388
pl011_clock_needed(void * opaque)389 static bool pl011_clock_needed(void *opaque)
390 {
391 PL011State *s = PL011(opaque);
392
393 return s->migrate_clk;
394 }
395
396 static const VMStateDescription vmstate_pl011_clock = {
397 .name = "pl011/clock",
398 .version_id = 1,
399 .minimum_version_id = 1,
400 .needed = pl011_clock_needed,
401 .fields = (VMStateField[]) {
402 VMSTATE_CLOCK(clk, PL011State),
403 VMSTATE_END_OF_LIST()
404 }
405 };
406
pl011_post_load(void * opaque,int version_id)407 static int pl011_post_load(void *opaque, int version_id)
408 {
409 PL011State* s = opaque;
410
411 /* Sanity-check input state */
412 if (s->read_pos >= ARRAY_SIZE(s->read_fifo) ||
413 s->read_count > ARRAY_SIZE(s->read_fifo)) {
414 return -1;
415 }
416
417 if (!pl011_is_fifo_enabled(s) && s->read_count > 0 && s->read_pos > 0) {
418 /*
419 * Older versions of PL011 didn't ensure that the single
420 * character in the FIFO in FIFO-disabled mode is in
421 * element 0 of the array; convert to follow the current
422 * code's assumptions.
423 */
424 s->read_fifo[0] = s->read_fifo[s->read_pos];
425 s->read_pos = 0;
426 }
427
428 return 0;
429 }
430
431 static const VMStateDescription vmstate_pl011 = {
432 .name = "pl011",
433 .version_id = 2,
434 .minimum_version_id = 2,
435 .post_load = pl011_post_load,
436 .fields = (VMStateField[]) {
437 VMSTATE_UINT32(readbuff, PL011State),
438 VMSTATE_UINT32(flags, PL011State),
439 VMSTATE_UINT32(lcr, PL011State),
440 VMSTATE_UINT32(rsr, PL011State),
441 VMSTATE_UINT32(cr, PL011State),
442 VMSTATE_UINT32(dmacr, PL011State),
443 VMSTATE_UINT32(int_enabled, PL011State),
444 VMSTATE_UINT32(int_level, PL011State),
445 VMSTATE_UINT32_ARRAY(read_fifo, PL011State, PL011_FIFO_DEPTH),
446 VMSTATE_UINT32(ilpr, PL011State),
447 VMSTATE_UINT32(ibrd, PL011State),
448 VMSTATE_UINT32(fbrd, PL011State),
449 VMSTATE_UINT32(ifl, PL011State),
450 VMSTATE_INT32(read_pos, PL011State),
451 VMSTATE_INT32(read_count, PL011State),
452 VMSTATE_INT32(read_trigger, PL011State),
453 VMSTATE_END_OF_LIST()
454 },
455 .subsections = (const VMStateDescription * []) {
456 &vmstate_pl011_clock,
457 NULL
458 }
459 };
460
461 static Property pl011_properties[] = {
462 DEFINE_PROP_CHR("chardev", PL011State, chr),
463 DEFINE_PROP_BOOL("migrate-clk", PL011State, migrate_clk, true),
464 DEFINE_PROP_END_OF_LIST(),
465 };
466
pl011_init(Object * obj)467 static void pl011_init(Object *obj)
468 {
469 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
470 PL011State *s = PL011(obj);
471 int i;
472
473 memory_region_init_io(&s->iomem, OBJECT(s), &pl011_ops, s, "pl011", 0x1000);
474 sysbus_init_mmio(sbd, &s->iomem);
475 for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
476 sysbus_init_irq(sbd, &s->irq[i]);
477 }
478
479 s->clk = qdev_init_clock_in(DEVICE(obj), "clk", pl011_clock_update, s,
480 ClockUpdate);
481
482 s->id = pl011_id_arm;
483 }
484
pl011_realize(DeviceState * dev,Error ** errp)485 static void pl011_realize(DeviceState *dev, Error **errp)
486 {
487 PL011State *s = PL011(dev);
488
489 qemu_chr_fe_set_handlers(&s->chr, pl011_can_receive, pl011_receive,
490 pl011_event, NULL, s, NULL, true);
491 }
492
pl011_reset(DeviceState * dev)493 static void pl011_reset(DeviceState *dev)
494 {
495 PL011State *s = PL011(dev);
496
497 s->lcr = 0;
498 s->rsr = 0;
499 s->dmacr = 0;
500 s->int_enabled = 0;
501 s->int_level = 0;
502 s->ilpr = 0;
503 s->ibrd = 0;
504 s->fbrd = 0;
505 s->read_trigger = 1;
506 s->ifl = 0x12;
507 s->cr = 0x300;
508 s->flags = 0;
509 pl011_reset_fifo(s);
510 }
511
pl011_class_init(ObjectClass * oc,void * data)512 static void pl011_class_init(ObjectClass *oc, void *data)
513 {
514 DeviceClass *dc = DEVICE_CLASS(oc);
515
516 dc->realize = pl011_realize;
517 dc->reset = pl011_reset;
518 dc->vmsd = &vmstate_pl011;
519 device_class_set_props(dc, pl011_properties);
520 }
521
522 static const TypeInfo pl011_arm_info = {
523 .name = TYPE_PL011,
524 .parent = TYPE_SYS_BUS_DEVICE,
525 .instance_size = sizeof(PL011State),
526 .instance_init = pl011_init,
527 .class_init = pl011_class_init,
528 };
529
pl011_luminary_init(Object * obj)530 static void pl011_luminary_init(Object *obj)
531 {
532 PL011State *s = PL011(obj);
533
534 s->id = pl011_id_luminary;
535 }
536
537 static const TypeInfo pl011_luminary_info = {
538 .name = TYPE_PL011_LUMINARY,
539 .parent = TYPE_PL011,
540 .instance_init = pl011_luminary_init,
541 };
542
pl011_register_types(void)543 static void pl011_register_types(void)
544 {
545 type_register_static(&pl011_arm_info);
546 type_register_static(&pl011_luminary_info);
547 }
548
549 type_init(pl011_register_types)
550