xref: /openbmc/qemu/hw/char/pl011.c (revision 4e6b1384)
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 "migration/vmstate.h"
26 #include "chardev/char-fe.h"
27 #include "qemu/log.h"
28 #include "qemu/module.h"
29 #include "trace.h"
30 
31 #define PL011_INT_TX 0x20
32 #define PL011_INT_RX 0x10
33 
34 #define PL011_FLAG_TXFE 0x80
35 #define PL011_FLAG_RXFF 0x40
36 #define PL011_FLAG_TXFF 0x20
37 #define PL011_FLAG_RXFE 0x10
38 
39 /* Interrupt status bits in UARTRIS, UARTMIS, UARTIMSC */
40 #define INT_OE (1 << 10)
41 #define INT_BE (1 << 9)
42 #define INT_PE (1 << 8)
43 #define INT_FE (1 << 7)
44 #define INT_RT (1 << 6)
45 #define INT_TX (1 << 5)
46 #define INT_RX (1 << 4)
47 #define INT_DSR (1 << 3)
48 #define INT_DCD (1 << 2)
49 #define INT_CTS (1 << 1)
50 #define INT_RI (1 << 0)
51 #define INT_E (INT_OE | INT_BE | INT_PE | INT_FE)
52 #define INT_MS (INT_RI | INT_DSR | INT_DCD | INT_CTS)
53 
54 static const unsigned char pl011_id_arm[8] =
55   { 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
56 static const unsigned char pl011_id_luminary[8] =
57   { 0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 };
58 
59 /* Which bits in the interrupt status matter for each outbound IRQ line ? */
60 static const uint32_t irqmask[] = {
61     INT_E | INT_MS | INT_RT | INT_TX | INT_RX, /* combined IRQ */
62     INT_RX,
63     INT_TX,
64     INT_RT,
65     INT_MS,
66     INT_E,
67 };
68 
69 static void pl011_update(PL011State *s)
70 {
71     uint32_t flags;
72     int i;
73 
74     flags = s->int_level & s->int_enabled;
75     trace_pl011_irq_state(flags != 0);
76     for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
77         qemu_set_irq(s->irq[i], (flags & irqmask[i]) != 0);
78     }
79 }
80 
81 static uint64_t pl011_read(void *opaque, hwaddr offset,
82                            unsigned size)
83 {
84     PL011State *s = (PL011State *)opaque;
85     uint32_t c;
86     uint64_t r;
87 
88     switch (offset >> 2) {
89     case 0: /* UARTDR */
90         s->flags &= ~PL011_FLAG_RXFF;
91         c = s->read_fifo[s->read_pos];
92         if (s->read_count > 0) {
93             s->read_count--;
94             if (++s->read_pos == 16)
95                 s->read_pos = 0;
96         }
97         if (s->read_count == 0) {
98             s->flags |= PL011_FLAG_RXFE;
99         }
100         if (s->read_count == s->read_trigger - 1)
101             s->int_level &= ~ PL011_INT_RX;
102         trace_pl011_read_fifo(s->read_count);
103         s->rsr = c >> 8;
104         pl011_update(s);
105         qemu_chr_fe_accept_input(&s->chr);
106         r = c;
107         break;
108     case 1: /* UARTRSR */
109         r = s->rsr;
110         break;
111     case 6: /* UARTFR */
112         r = s->flags;
113         break;
114     case 8: /* UARTILPR */
115         r = s->ilpr;
116         break;
117     case 9: /* UARTIBRD */
118         r = s->ibrd;
119         break;
120     case 10: /* UARTFBRD */
121         r = s->fbrd;
122         break;
123     case 11: /* UARTLCR_H */
124         r = s->lcr;
125         break;
126     case 12: /* UARTCR */
127         r = s->cr;
128         break;
129     case 13: /* UARTIFLS */
130         r = s->ifl;
131         break;
132     case 14: /* UARTIMSC */
133         r = s->int_enabled;
134         break;
135     case 15: /* UARTRIS */
136         r = s->int_level;
137         break;
138     case 16: /* UARTMIS */
139         r = s->int_level & s->int_enabled;
140         break;
141     case 18: /* UARTDMACR */
142         r = s->dmacr;
143         break;
144     case 0x3f8 ... 0x400:
145         r = s->id[(offset - 0xfe0) >> 2];
146         break;
147     default:
148         qemu_log_mask(LOG_GUEST_ERROR,
149                       "pl011_read: Bad offset 0x%x\n", (int)offset);
150         r = 0;
151         break;
152     }
153 
154     trace_pl011_read(offset, r);
155     return r;
156 }
157 
158 static void pl011_set_read_trigger(PL011State *s)
159 {
160 #if 0
161     /* The docs say the RX interrupt is triggered when the FIFO exceeds
162        the threshold.  However linux only reads the FIFO in response to an
163        interrupt.  Triggering the interrupt when the FIFO is non-empty seems
164        to make things work.  */
165     if (s->lcr & 0x10)
166         s->read_trigger = (s->ifl >> 1) & 0x1c;
167     else
168 #endif
169         s->read_trigger = 1;
170 }
171 
172 static void pl011_write(void *opaque, hwaddr offset,
173                         uint64_t value, unsigned size)
174 {
175     PL011State *s = (PL011State *)opaque;
176     unsigned char ch;
177 
178     trace_pl011_write(offset, value);
179 
180     switch (offset >> 2) {
181     case 0: /* UARTDR */
182         /* ??? Check if transmitter is enabled.  */
183         ch = value;
184         /* XXX this blocks entire thread. Rewrite to use
185          * qemu_chr_fe_write and background I/O callbacks */
186         qemu_chr_fe_write_all(&s->chr, &ch, 1);
187         s->int_level |= PL011_INT_TX;
188         pl011_update(s);
189         break;
190     case 1: /* UARTRSR/UARTECR */
191         s->rsr = 0;
192         break;
193     case 6: /* UARTFR */
194         /* Writes to Flag register are ignored.  */
195         break;
196     case 8: /* UARTUARTILPR */
197         s->ilpr = value;
198         break;
199     case 9: /* UARTIBRD */
200         s->ibrd = value;
201         break;
202     case 10: /* UARTFBRD */
203         s->fbrd = value;
204         break;
205     case 11: /* UARTLCR_H */
206         /* Reset the FIFO state on FIFO enable or disable */
207         if ((s->lcr ^ value) & 0x10) {
208             s->read_count = 0;
209             s->read_pos = 0;
210         }
211         s->lcr = value;
212         pl011_set_read_trigger(s);
213         break;
214     case 12: /* UARTCR */
215         /* ??? Need to implement the enable and loopback bits.  */
216         s->cr = value;
217         break;
218     case 13: /* UARTIFS */
219         s->ifl = value;
220         pl011_set_read_trigger(s);
221         break;
222     case 14: /* UARTIMSC */
223         s->int_enabled = value;
224         pl011_update(s);
225         break;
226     case 17: /* UARTICR */
227         s->int_level &= ~value;
228         pl011_update(s);
229         break;
230     case 18: /* UARTDMACR */
231         s->dmacr = value;
232         if (value & 3) {
233             qemu_log_mask(LOG_UNIMP, "pl011: DMA not implemented\n");
234         }
235         break;
236     default:
237         qemu_log_mask(LOG_GUEST_ERROR,
238                       "pl011_write: Bad offset 0x%x\n", (int)offset);
239     }
240 }
241 
242 static int pl011_can_receive(void *opaque)
243 {
244     PL011State *s = (PL011State *)opaque;
245     int r;
246 
247     if (s->lcr & 0x10) {
248         r = s->read_count < 16;
249     } else {
250         r = s->read_count < 1;
251     }
252     trace_pl011_can_receive(s->lcr, s->read_count, r);
253     return r;
254 }
255 
256 static void pl011_put_fifo(void *opaque, uint32_t value)
257 {
258     PL011State *s = (PL011State *)opaque;
259     int slot;
260 
261     slot = s->read_pos + s->read_count;
262     if (slot >= 16)
263         slot -= 16;
264     s->read_fifo[slot] = value;
265     s->read_count++;
266     s->flags &= ~PL011_FLAG_RXFE;
267     trace_pl011_put_fifo(value, s->read_count);
268     if (!(s->lcr & 0x10) || s->read_count == 16) {
269         trace_pl011_put_fifo_full();
270         s->flags |= PL011_FLAG_RXFF;
271     }
272     if (s->read_count == s->read_trigger) {
273         s->int_level |= PL011_INT_RX;
274         pl011_update(s);
275     }
276 }
277 
278 static void pl011_receive(void *opaque, const uint8_t *buf, int size)
279 {
280     pl011_put_fifo(opaque, *buf);
281 }
282 
283 static void pl011_event(void *opaque, QEMUChrEvent event)
284 {
285     if (event == CHR_EVENT_BREAK)
286         pl011_put_fifo(opaque, 0x400);
287 }
288 
289 static const MemoryRegionOps pl011_ops = {
290     .read = pl011_read,
291     .write = pl011_write,
292     .endianness = DEVICE_NATIVE_ENDIAN,
293 };
294 
295 static const VMStateDescription vmstate_pl011 = {
296     .name = "pl011",
297     .version_id = 2,
298     .minimum_version_id = 2,
299     .fields = (VMStateField[]) {
300         VMSTATE_UINT32(readbuff, PL011State),
301         VMSTATE_UINT32(flags, PL011State),
302         VMSTATE_UINT32(lcr, PL011State),
303         VMSTATE_UINT32(rsr, PL011State),
304         VMSTATE_UINT32(cr, PL011State),
305         VMSTATE_UINT32(dmacr, PL011State),
306         VMSTATE_UINT32(int_enabled, PL011State),
307         VMSTATE_UINT32(int_level, PL011State),
308         VMSTATE_UINT32_ARRAY(read_fifo, PL011State, 16),
309         VMSTATE_UINT32(ilpr, PL011State),
310         VMSTATE_UINT32(ibrd, PL011State),
311         VMSTATE_UINT32(fbrd, PL011State),
312         VMSTATE_UINT32(ifl, PL011State),
313         VMSTATE_INT32(read_pos, PL011State),
314         VMSTATE_INT32(read_count, PL011State),
315         VMSTATE_INT32(read_trigger, PL011State),
316         VMSTATE_END_OF_LIST()
317     }
318 };
319 
320 static Property pl011_properties[] = {
321     DEFINE_PROP_CHR("chardev", PL011State, chr),
322     DEFINE_PROP_END_OF_LIST(),
323 };
324 
325 static void pl011_init(Object *obj)
326 {
327     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
328     PL011State *s = PL011(obj);
329     int i;
330 
331     memory_region_init_io(&s->iomem, OBJECT(s), &pl011_ops, s, "pl011", 0x1000);
332     sysbus_init_mmio(sbd, &s->iomem);
333     for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
334         sysbus_init_irq(sbd, &s->irq[i]);
335     }
336 
337     s->read_trigger = 1;
338     s->ifl = 0x12;
339     s->cr = 0x300;
340     s->flags = 0x90;
341 
342     s->id = pl011_id_arm;
343 }
344 
345 static void pl011_realize(DeviceState *dev, Error **errp)
346 {
347     PL011State *s = PL011(dev);
348 
349     qemu_chr_fe_set_handlers(&s->chr, pl011_can_receive, pl011_receive,
350                              pl011_event, NULL, s, NULL, true);
351 }
352 
353 static void pl011_class_init(ObjectClass *oc, void *data)
354 {
355     DeviceClass *dc = DEVICE_CLASS(oc);
356 
357     dc->realize = pl011_realize;
358     dc->vmsd = &vmstate_pl011;
359     dc->props = pl011_properties;
360 }
361 
362 static const TypeInfo pl011_arm_info = {
363     .name          = TYPE_PL011,
364     .parent        = TYPE_SYS_BUS_DEVICE,
365     .instance_size = sizeof(PL011State),
366     .instance_init = pl011_init,
367     .class_init    = pl011_class_init,
368 };
369 
370 static void pl011_luminary_init(Object *obj)
371 {
372     PL011State *s = PL011(obj);
373 
374     s->id = pl011_id_luminary;
375 }
376 
377 static const TypeInfo pl011_luminary_info = {
378     .name          = TYPE_PL011_LUMINARY,
379     .parent        = TYPE_PL011,
380     .instance_init = pl011_luminary_init,
381 };
382 
383 static void pl011_register_types(void)
384 {
385     type_register_static(&pl011_arm_info);
386     type_register_static(&pl011_luminary_info);
387 }
388 
389 type_init(pl011_register_types)
390