xref: /openbmc/qemu/hw/char/pl011.c (revision 5b5968c4)
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)
524