]> git.proxmox.com Git - mirror_qemu.git/blame - hw/char/cmsdk-apb-uart.c
migration: remove sent parameter in get_queued_page_not_dirty
[mirror_qemu.git] / hw / char / cmsdk-apb-uart.c
CommitLineData
775df84e
PM
1/*
2 * ARM CMSDK APB UART emulation
3 *
4 * Copyright (c) 2017 Linaro Limited
5 * Written by Peter Maydell
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 or
9 * (at your option) any later version.
10 */
11
12/* This is a model of the "APB UART" which is part of the Cortex-M
13 * System Design Kit (CMSDK) and documented in the Cortex-M System
14 * Design Kit Technical Reference Manual (ARM DDI0479C):
15 * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
16 */
17
18#include "qemu/osdep.h"
19#include "qemu/log.h"
0b8fa32f 20#include "qemu/module.h"
775df84e
PM
21#include "qapi/error.h"
22#include "trace.h"
23#include "hw/sysbus.h"
d6454270 24#include "migration/vmstate.h"
775df84e
PM
25#include "hw/registerfields.h"
26#include "chardev/char-fe.h"
27#include "chardev/char-serial.h"
28#include "hw/char/cmsdk-apb-uart.h"
64552b6b 29#include "hw/irq.h"
775df84e
PM
30
31REG32(DATA, 0)
32REG32(STATE, 4)
33 FIELD(STATE, TXFULL, 0, 1)
34 FIELD(STATE, RXFULL, 1, 1)
35 FIELD(STATE, TXOVERRUN, 2, 1)
36 FIELD(STATE, RXOVERRUN, 3, 1)
37REG32(CTRL, 8)
38 FIELD(CTRL, TX_EN, 0, 1)
39 FIELD(CTRL, RX_EN, 1, 1)
40 FIELD(CTRL, TX_INTEN, 2, 1)
41 FIELD(CTRL, RX_INTEN, 3, 1)
42 FIELD(CTRL, TXO_INTEN, 4, 1)
43 FIELD(CTRL, RXO_INTEN, 5, 1)
44 FIELD(CTRL, HSTEST, 6, 1)
45REG32(INTSTATUS, 0xc)
46 FIELD(INTSTATUS, TX, 0, 1)
47 FIELD(INTSTATUS, RX, 1, 1)
48 FIELD(INTSTATUS, TXO, 2, 1)
49 FIELD(INTSTATUS, RXO, 3, 1)
50REG32(BAUDDIV, 0x10)
51REG32(PID4, 0xFD0)
52REG32(PID5, 0xFD4)
53REG32(PID6, 0xFD8)
54REG32(PID7, 0xFDC)
55REG32(PID0, 0xFE0)
56REG32(PID1, 0xFE4)
57REG32(PID2, 0xFE8)
58REG32(PID3, 0xFEC)
59REG32(CID0, 0xFF0)
60REG32(CID1, 0xFF4)
61REG32(CID2, 0xFF8)
62REG32(CID3, 0xFFC)
63
64/* PID/CID values */
65static const int uart_id[] = {
66 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
67 0x21, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
68 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
69};
70
71static bool uart_baudrate_ok(CMSDKAPBUART *s)
72{
73 /* The minimum permitted bauddiv setting is 16, so we just ignore
74 * settings below that (usually this means the device has just
75 * been reset and not yet programmed).
76 */
77 return s->bauddiv >= 16 && s->bauddiv <= s->pclk_frq;
78}
79
80static void uart_update_parameters(CMSDKAPBUART *s)
81{
82 QEMUSerialSetParams ssp;
83
84 /* This UART is always 8N1 but the baud rate is programmable. */
85 if (!uart_baudrate_ok(s)) {
86 return;
87 }
88
89 ssp.data_bits = 8;
90 ssp.parity = 'N';
91 ssp.stop_bits = 1;
92 ssp.speed = s->pclk_frq / s->bauddiv;
93 qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
94 trace_cmsdk_apb_uart_set_params(ssp.speed);
95}
96
97static void cmsdk_apb_uart_update(CMSDKAPBUART *s)
98{
99 /* update outbound irqs, including handling the way the rxo and txo
100 * interrupt status bits are just logical AND of the overrun bit in
101 * STATE and the overrun interrupt enable bit in CTRL.
102 */
103 uint32_t omask = (R_INTSTATUS_RXO_MASK | R_INTSTATUS_TXO_MASK);
104 s->intstatus &= ~omask;
105 s->intstatus |= (s->state & (s->ctrl >> 2) & omask);
106
107 qemu_set_irq(s->txint, !!(s->intstatus & R_INTSTATUS_TX_MASK));
108 qemu_set_irq(s->rxint, !!(s->intstatus & R_INTSTATUS_RX_MASK));
109 qemu_set_irq(s->txovrint, !!(s->intstatus & R_INTSTATUS_TXO_MASK));
110 qemu_set_irq(s->rxovrint, !!(s->intstatus & R_INTSTATUS_RXO_MASK));
111 qemu_set_irq(s->uartint, !!(s->intstatus));
112}
113
114static int uart_can_receive(void *opaque)
115{
116 CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
117
118 /* We can take a char if RX is enabled and the buffer is empty */
119 if (s->ctrl & R_CTRL_RX_EN_MASK && !(s->state & R_STATE_RXFULL_MASK)) {
120 return 1;
121 }
122 return 0;
123}
124
125static void uart_receive(void *opaque, const uint8_t *buf, int size)
126{
127 CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
128
129 trace_cmsdk_apb_uart_receive(*buf);
130
131 /* In fact uart_can_receive() ensures that we can't be
132 * called unless RX is enabled and the buffer is empty,
133 * but we include this logic as documentation of what the
134 * hardware does if a character arrives in these circumstances.
135 */
136 if (!(s->ctrl & R_CTRL_RX_EN_MASK)) {
137 /* Just drop the character on the floor */
138 return;
139 }
140
141 if (s->state & R_STATE_RXFULL_MASK) {
142 s->state |= R_STATE_RXOVERRUN_MASK;
143 }
144
145 s->rxbuf = *buf;
146 s->state |= R_STATE_RXFULL_MASK;
147 if (s->ctrl & R_CTRL_RX_INTEN_MASK) {
148 s->intstatus |= R_INTSTATUS_RX_MASK;
149 }
150 cmsdk_apb_uart_update(s);
151}
152
153static uint64_t uart_read(void *opaque, hwaddr offset, unsigned size)
154{
155 CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
156 uint64_t r;
157
158 switch (offset) {
159 case A_DATA:
160 r = s->rxbuf;
161 s->state &= ~R_STATE_RXFULL_MASK;
162 cmsdk_apb_uart_update(s);
0c6a108e 163 qemu_chr_fe_accept_input(&s->chr);
775df84e
PM
164 break;
165 case A_STATE:
166 r = s->state;
167 break;
168 case A_CTRL:
169 r = s->ctrl;
170 break;
171 case A_INTSTATUS:
172 r = s->intstatus;
173 break;
174 case A_BAUDDIV:
175 r = s->bauddiv;
176 break;
177 case A_PID4 ... A_CID3:
178 r = uart_id[(offset - A_PID4) / 4];
179 break;
180 default:
181 qemu_log_mask(LOG_GUEST_ERROR,
182 "CMSDK APB UART read: bad offset %x\n", (int) offset);
183 r = 0;
184 break;
185 }
186 trace_cmsdk_apb_uart_read(offset, r, size);
187 return r;
188}
189
190/* Try to send tx data, and arrange to be called back later if
191 * we can't (ie the char backend is busy/blocking).
192 */
193static gboolean uart_transmit(GIOChannel *chan, GIOCondition cond, void *opaque)
194{
195 CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
196 int ret;
197
198 s->watch_tag = 0;
199
200 if (!(s->ctrl & R_CTRL_TX_EN_MASK) || !(s->state & R_STATE_TXFULL_MASK)) {
201 return FALSE;
202 }
203
204 ret = qemu_chr_fe_write(&s->chr, &s->txbuf, 1);
205 if (ret <= 0) {
206 s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
207 uart_transmit, s);
208 if (!s->watch_tag) {
209 /* Most common reason to be here is "no chardev backend":
210 * just insta-drain the buffer, so the serial output
211 * goes into a void, rather than blocking the guest.
212 */
213 goto buffer_drained;
214 }
215 /* Transmit pending */
216 trace_cmsdk_apb_uart_tx_pending();
217 return FALSE;
218 }
219
220buffer_drained:
221 /* Character successfully sent */
222 trace_cmsdk_apb_uart_tx(s->txbuf);
223 s->state &= ~R_STATE_TXFULL_MASK;
224 /* Going from TXFULL set to clear triggers the tx interrupt */
225 if (s->ctrl & R_CTRL_TX_INTEN_MASK) {
226 s->intstatus |= R_INTSTATUS_TX_MASK;
227 }
228 cmsdk_apb_uart_update(s);
229 return FALSE;
230}
231
232static void uart_cancel_transmit(CMSDKAPBUART *s)
233{
234 if (s->watch_tag) {
235 g_source_remove(s->watch_tag);
236 s->watch_tag = 0;
237 }
238}
239
240static void uart_write(void *opaque, hwaddr offset, uint64_t value,
241 unsigned size)
242{
243 CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
244
245 trace_cmsdk_apb_uart_write(offset, value, size);
246
247 switch (offset) {
248 case A_DATA:
249 s->txbuf = value;
250 if (s->state & R_STATE_TXFULL_MASK) {
251 /* Buffer already full -- note the overrun and let the
252 * existing pending transmit callback handle the new char.
253 */
254 s->state |= R_STATE_TXOVERRUN_MASK;
255 cmsdk_apb_uart_update(s);
256 } else {
257 s->state |= R_STATE_TXFULL_MASK;
258 uart_transmit(NULL, G_IO_OUT, s);
259 }
260 break;
261 case A_STATE:
262 /* Bits 0 and 1 are read only; bits 2 and 3 are W1C */
263 s->state &= ~(value &
264 (R_STATE_TXOVERRUN_MASK | R_STATE_RXOVERRUN_MASK));
265 cmsdk_apb_uart_update(s);
266 break;
267 case A_CTRL:
268 s->ctrl = value & 0x7f;
269 if ((s->ctrl & R_CTRL_TX_EN_MASK) && !uart_baudrate_ok(s)) {
270 qemu_log_mask(LOG_GUEST_ERROR,
271 "CMSDK APB UART: Tx enabled with invalid baudrate\n");
272 }
273 cmsdk_apb_uart_update(s);
274 break;
275 case A_INTSTATUS:
276 /* All bits are W1C. Clearing the overrun interrupt bits really
277 * clears the overrun status bits in the STATE register (which
278 * is then reflected into the intstatus value by the update function).
279 */
280 s->state &= ~(value & (R_INTSTATUS_TXO_MASK | R_INTSTATUS_RXO_MASK));
6670b494 281 s->intstatus &= ~value;
775df84e
PM
282 cmsdk_apb_uart_update(s);
283 break;
284 case A_BAUDDIV:
285 s->bauddiv = value & 0xFFFFF;
286 uart_update_parameters(s);
287 break;
288 case A_PID4 ... A_CID3:
289 qemu_log_mask(LOG_GUEST_ERROR,
290 "CMSDK APB UART write: write to RO offset 0x%x\n",
291 (int)offset);
292 break;
293 default:
294 qemu_log_mask(LOG_GUEST_ERROR,
295 "CMSDK APB UART write: bad offset 0x%x\n", (int) offset);
296 break;
297 }
298}
299
300static const MemoryRegionOps uart_ops = {
301 .read = uart_read,
302 .write = uart_write,
303 .endianness = DEVICE_LITTLE_ENDIAN,
304};
305
306static void cmsdk_apb_uart_reset(DeviceState *dev)
307{
308 CMSDKAPBUART *s = CMSDK_APB_UART(dev);
309
310 trace_cmsdk_apb_uart_reset();
311 uart_cancel_transmit(s);
312 s->state = 0;
313 s->ctrl = 0;
314 s->intstatus = 0;
315 s->bauddiv = 0;
316 s->txbuf = 0;
317 s->rxbuf = 0;
318}
319
320static void cmsdk_apb_uart_init(Object *obj)
321{
322 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
323 CMSDKAPBUART *s = CMSDK_APB_UART(obj);
324
325 memory_region_init_io(&s->iomem, obj, &uart_ops, s, "uart", 0x1000);
326 sysbus_init_mmio(sbd, &s->iomem);
327 sysbus_init_irq(sbd, &s->txint);
328 sysbus_init_irq(sbd, &s->rxint);
329 sysbus_init_irq(sbd, &s->txovrint);
330 sysbus_init_irq(sbd, &s->rxovrint);
331 sysbus_init_irq(sbd, &s->uartint);
332}
333
334static void cmsdk_apb_uart_realize(DeviceState *dev, Error **errp)
335{
336 CMSDKAPBUART *s = CMSDK_APB_UART(dev);
337
338 if (s->pclk_frq == 0) {
339 error_setg(errp, "CMSDK APB UART: pclk-frq property must be set");
340 return;
341 }
342
343 /* This UART has no flow control, so we do not need to register
344 * an event handler to deal with CHR_EVENT_BREAK.
345 */
346 qemu_chr_fe_set_handlers(&s->chr, uart_can_receive, uart_receive,
977a15f4 347 NULL, NULL, s, NULL, true);
775df84e
PM
348}
349
350static int cmsdk_apb_uart_post_load(void *opaque, int version_id)
351{
352 CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
353
354 /* If we have a pending character, arrange to resend it. */
355 if (s->state & R_STATE_TXFULL_MASK) {
356 s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
357 uart_transmit, s);
358 }
359 uart_update_parameters(s);
360 return 0;
361}
362
363static const VMStateDescription cmsdk_apb_uart_vmstate = {
364 .name = "cmsdk-apb-uart",
365 .version_id = 1,
366 .minimum_version_id = 1,
367 .post_load = cmsdk_apb_uart_post_load,
368 .fields = (VMStateField[]) {
369 VMSTATE_UINT32(state, CMSDKAPBUART),
370 VMSTATE_UINT32(ctrl, CMSDKAPBUART),
371 VMSTATE_UINT32(intstatus, CMSDKAPBUART),
372 VMSTATE_UINT32(bauddiv, CMSDKAPBUART),
373 VMSTATE_UINT8(txbuf, CMSDKAPBUART),
374 VMSTATE_UINT8(rxbuf, CMSDKAPBUART),
375 VMSTATE_END_OF_LIST()
376 }
377};
378
379static Property cmsdk_apb_uart_properties[] = {
380 DEFINE_PROP_CHR("chardev", CMSDKAPBUART, chr),
381 DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBUART, pclk_frq, 0),
382 DEFINE_PROP_END_OF_LIST(),
383};
384
385static void cmsdk_apb_uart_class_init(ObjectClass *klass, void *data)
386{
387 DeviceClass *dc = DEVICE_CLASS(klass);
388
389 dc->realize = cmsdk_apb_uart_realize;
390 dc->vmsd = &cmsdk_apb_uart_vmstate;
391 dc->reset = cmsdk_apb_uart_reset;
392 dc->props = cmsdk_apb_uart_properties;
393}
394
395static const TypeInfo cmsdk_apb_uart_info = {
396 .name = TYPE_CMSDK_APB_UART,
397 .parent = TYPE_SYS_BUS_DEVICE,
398 .instance_size = sizeof(CMSDKAPBUART),
399 .instance_init = cmsdk_apb_uart_init,
400 .class_init = cmsdk_apb_uart_class_init,
401};
402
403static void cmsdk_apb_uart_register_types(void)
404{
405 type_register_static(&cmsdk_apb_uart_info);
406}
407
408type_init(cmsdk_apb_uart_register_types);