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