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