graph-lock: TSA annotations for lock/unlock functions
[qemu.git] / hw / char / pl011.c
blobc076813423fceccfa8d33be0143cf88a9177a7c2
1 /*
2 * Arm PrimeCell PL011 UART
4 * Copyright (c) 2006 CodeSourcery.
5 * Written by Paul Brook
7 * This code is licensed under the GPL.
8 */
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)
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"
34 #define PL011_INT_TX 0x20
35 #define PL011_INT_RX 0x10
37 #define PL011_FLAG_TXFE 0x80
38 #define PL011_FLAG_RXFF 0x40
39 #define PL011_FLAG_TXFF 0x20
40 #define PL011_FLAG_RXFE 0x10
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)
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 };
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,
72 static void pl011_update(PL011State *s)
74 uint32_t flags;
75 int i;
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);
84 static uint64_t pl011_read(void *opaque, hwaddr offset,
85 unsigned size)
87 PL011State *s = (PL011State *)opaque;
88 uint32_t c;
89 uint64_t r;
91 switch (offset >> 2) {
92 case 0: /* UARTDR */
93 s->flags &= ~PL011_FLAG_RXFF;
94 c = s->read_fifo[s->read_pos];
95 if (s->read_count > 0) {
96 s->read_count--;
97 if (++s->read_pos == 16)
98 s->read_pos = 0;
100 if (s->read_count == 0) {
101 s->flags |= PL011_FLAG_RXFE;
103 if (s->read_count == s->read_trigger - 1)
104 s->int_level &= ~ PL011_INT_RX;
105 trace_pl011_read_fifo(s->read_count);
106 s->rsr = c >> 8;
107 pl011_update(s);
108 qemu_chr_fe_accept_input(&s->chr);
109 r = c;
110 break;
111 case 1: /* UARTRSR */
112 r = s->rsr;
113 break;
114 case 6: /* UARTFR */
115 r = s->flags;
116 break;
117 case 8: /* UARTILPR */
118 r = s->ilpr;
119 break;
120 case 9: /* UARTIBRD */
121 r = s->ibrd;
122 break;
123 case 10: /* UARTFBRD */
124 r = s->fbrd;
125 break;
126 case 11: /* UARTLCR_H */
127 r = s->lcr;
128 break;
129 case 12: /* UARTCR */
130 r = s->cr;
131 break;
132 case 13: /* UARTIFLS */
133 r = s->ifl;
134 break;
135 case 14: /* UARTIMSC */
136 r = s->int_enabled;
137 break;
138 case 15: /* UARTRIS */
139 r = s->int_level;
140 break;
141 case 16: /* UARTMIS */
142 r = s->int_level & s->int_enabled;
143 break;
144 case 18: /* UARTDMACR */
145 r = s->dmacr;
146 break;
147 case 0x3f8 ... 0x400:
148 r = s->id[(offset - 0xfe0) >> 2];
149 break;
150 default:
151 qemu_log_mask(LOG_GUEST_ERROR,
152 "pl011_read: Bad offset 0x%x\n", (int)offset);
153 r = 0;
154 break;
157 trace_pl011_read(offset, r);
158 return r;
161 static void pl011_set_read_trigger(PL011State *s)
163 #if 0
164 /* The docs say the RX interrupt is triggered when the FIFO exceeds
165 the threshold. However linux only reads the FIFO in response to an
166 interrupt. Triggering the interrupt when the FIFO is non-empty seems
167 to make things work. */
168 if (s->lcr & 0x10)
169 s->read_trigger = (s->ifl >> 1) & 0x1c;
170 else
171 #endif
172 s->read_trigger = 1;
175 static unsigned int pl011_get_baudrate(const PL011State *s)
177 uint64_t clk;
179 if (s->ibrd == 0) {
180 return 0;
183 clk = clock_get_hz(s->clk);
184 return (clk / ((s->ibrd << 6) + s->fbrd)) << 2;
187 static void pl011_trace_baudrate_change(const PL011State *s)
189 trace_pl011_baudrate_change(pl011_get_baudrate(s),
190 clock_get_hz(s->clk),
191 s->ibrd, s->fbrd);
194 static void pl011_write(void *opaque, hwaddr offset,
195 uint64_t value, unsigned size)
197 PL011State *s = (PL011State *)opaque;
198 unsigned char ch;
200 trace_pl011_write(offset, value);
202 switch (offset >> 2) {
203 case 0: /* UARTDR */
204 /* ??? Check if transmitter is enabled. */
205 ch = value;
206 /* XXX this blocks entire thread. Rewrite to use
207 * qemu_chr_fe_write and background I/O callbacks */
208 qemu_chr_fe_write_all(&s->chr, &ch, 1);
209 s->int_level |= PL011_INT_TX;
210 pl011_update(s);
211 break;
212 case 1: /* UARTRSR/UARTECR */
213 s->rsr = 0;
214 break;
215 case 6: /* UARTFR */
216 /* Writes to Flag register are ignored. */
217 break;
218 case 8: /* UARTUARTILPR */
219 s->ilpr = value;
220 break;
221 case 9: /* UARTIBRD */
222 s->ibrd = value;
223 pl011_trace_baudrate_change(s);
224 break;
225 case 10: /* UARTFBRD */
226 s->fbrd = value;
227 pl011_trace_baudrate_change(s);
228 break;
229 case 11: /* UARTLCR_H */
230 /* Reset the FIFO state on FIFO enable or disable */
231 if ((s->lcr ^ value) & 0x10) {
232 s->read_count = 0;
233 s->read_pos = 0;
235 if ((s->lcr ^ value) & 0x1) {
236 int break_enable = value & 0x1;
237 qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
238 &break_enable);
240 s->lcr = value;
241 pl011_set_read_trigger(s);
242 break;
243 case 12: /* UARTCR */
244 /* ??? Need to implement the enable and loopback bits. */
245 s->cr = value;
246 break;
247 case 13: /* UARTIFS */
248 s->ifl = value;
249 pl011_set_read_trigger(s);
250 break;
251 case 14: /* UARTIMSC */
252 s->int_enabled = value;
253 pl011_update(s);
254 break;
255 case 17: /* UARTICR */
256 s->int_level &= ~value;
257 pl011_update(s);
258 break;
259 case 18: /* UARTDMACR */
260 s->dmacr = value;
261 if (value & 3) {
262 qemu_log_mask(LOG_UNIMP, "pl011: DMA not implemented\n");
264 break;
265 default:
266 qemu_log_mask(LOG_GUEST_ERROR,
267 "pl011_write: Bad offset 0x%x\n", (int)offset);
271 static int pl011_can_receive(void *opaque)
273 PL011State *s = (PL011State *)opaque;
274 int r;
276 if (s->lcr & 0x10) {
277 r = s->read_count < 16;
278 } else {
279 r = s->read_count < 1;
281 trace_pl011_can_receive(s->lcr, s->read_count, r);
282 return r;
285 static void pl011_put_fifo(void *opaque, uint32_t value)
287 PL011State *s = (PL011State *)opaque;
288 int slot;
290 slot = s->read_pos + s->read_count;
291 if (slot >= 16)
292 slot -= 16;
293 s->read_fifo[slot] = value;
294 s->read_count++;
295 s->flags &= ~PL011_FLAG_RXFE;
296 trace_pl011_put_fifo(value, s->read_count);
297 if (!(s->lcr & 0x10) || s->read_count == 16) {
298 trace_pl011_put_fifo_full();
299 s->flags |= PL011_FLAG_RXFF;
301 if (s->read_count == s->read_trigger) {
302 s->int_level |= PL011_INT_RX;
303 pl011_update(s);
307 static void pl011_receive(void *opaque, const uint8_t *buf, int size)
309 pl011_put_fifo(opaque, *buf);
312 static void pl011_event(void *opaque, QEMUChrEvent event)
314 if (event == CHR_EVENT_BREAK)
315 pl011_put_fifo(opaque, 0x400);
318 static void pl011_clock_update(void *opaque, ClockEvent event)
320 PL011State *s = PL011(opaque);
322 pl011_trace_baudrate_change(s);
325 static const MemoryRegionOps pl011_ops = {
326 .read = pl011_read,
327 .write = pl011_write,
328 .endianness = DEVICE_NATIVE_ENDIAN,
331 static bool pl011_clock_needed(void *opaque)
333 PL011State *s = PL011(opaque);
335 return s->migrate_clk;
338 static const VMStateDescription vmstate_pl011_clock = {
339 .name = "pl011/clock",
340 .version_id = 1,
341 .minimum_version_id = 1,
342 .needed = pl011_clock_needed,
343 .fields = (VMStateField[]) {
344 VMSTATE_CLOCK(clk, PL011State),
345 VMSTATE_END_OF_LIST()
349 static const VMStateDescription vmstate_pl011 = {
350 .name = "pl011",
351 .version_id = 2,
352 .minimum_version_id = 2,
353 .fields = (VMStateField[]) {
354 VMSTATE_UINT32(readbuff, PL011State),
355 VMSTATE_UINT32(flags, PL011State),
356 VMSTATE_UINT32(lcr, PL011State),
357 VMSTATE_UINT32(rsr, PL011State),
358 VMSTATE_UINT32(cr, PL011State),
359 VMSTATE_UINT32(dmacr, PL011State),
360 VMSTATE_UINT32(int_enabled, PL011State),
361 VMSTATE_UINT32(int_level, PL011State),
362 VMSTATE_UINT32_ARRAY(read_fifo, PL011State, 16),
363 VMSTATE_UINT32(ilpr, PL011State),
364 VMSTATE_UINT32(ibrd, PL011State),
365 VMSTATE_UINT32(fbrd, PL011State),
366 VMSTATE_UINT32(ifl, PL011State),
367 VMSTATE_INT32(read_pos, PL011State),
368 VMSTATE_INT32(read_count, PL011State),
369 VMSTATE_INT32(read_trigger, PL011State),
370 VMSTATE_END_OF_LIST()
372 .subsections = (const VMStateDescription * []) {
373 &vmstate_pl011_clock,
374 NULL
378 static Property pl011_properties[] = {
379 DEFINE_PROP_CHR("chardev", PL011State, chr),
380 DEFINE_PROP_BOOL("migrate-clk", PL011State, migrate_clk, true),
381 DEFINE_PROP_END_OF_LIST(),
384 static void pl011_init(Object *obj)
386 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
387 PL011State *s = PL011(obj);
388 int i;
390 memory_region_init_io(&s->iomem, OBJECT(s), &pl011_ops, s, "pl011", 0x1000);
391 sysbus_init_mmio(sbd, &s->iomem);
392 for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
393 sysbus_init_irq(sbd, &s->irq[i]);
396 s->clk = qdev_init_clock_in(DEVICE(obj), "clk", pl011_clock_update, s,
397 ClockUpdate);
399 s->read_trigger = 1;
400 s->ifl = 0x12;
401 s->cr = 0x300;
402 s->flags = 0x90;
404 s->id = pl011_id_arm;
407 static void pl011_realize(DeviceState *dev, Error **errp)
409 PL011State *s = PL011(dev);
411 qemu_chr_fe_set_handlers(&s->chr, pl011_can_receive, pl011_receive,
412 pl011_event, NULL, s, NULL, true);
415 static void pl011_class_init(ObjectClass *oc, void *data)
417 DeviceClass *dc = DEVICE_CLASS(oc);
419 dc->realize = pl011_realize;
420 dc->vmsd = &vmstate_pl011;
421 device_class_set_props(dc, pl011_properties);
424 static const TypeInfo pl011_arm_info = {
425 .name = TYPE_PL011,
426 .parent = TYPE_SYS_BUS_DEVICE,
427 .instance_size = sizeof(PL011State),
428 .instance_init = pl011_init,
429 .class_init = pl011_class_init,
432 static void pl011_luminary_init(Object *obj)
434 PL011State *s = PL011(obj);
436 s->id = pl011_id_luminary;
439 static const TypeInfo pl011_luminary_info = {
440 .name = TYPE_PL011_LUMINARY,
441 .parent = TYPE_PL011,
442 .instance_init = pl011_luminary_init,
445 static void pl011_register_types(void)
447 type_register_static(&pl011_arm_info);
448 type_register_static(&pl011_luminary_info);
451 type_init(pl011_register_types)