include/standard-headers: add pvrdma related headers
[qemu.git] / hw / char / mcf_uart.c
blobfaae083e782f3cfad1b23295456c4a16fad91571
1 /*
2 * ColdFire UART emulation.
4 * Copyright (c) 2007 CodeSourcery.
6 * This code is licensed under the GPL
7 */
8 #include "qemu/osdep.h"
9 #include "hw/hw.h"
10 #include "hw/sysbus.h"
11 #include "hw/m68k/mcf.h"
12 #include "chardev/char-fe.h"
13 #include "exec/address-spaces.h"
15 typedef struct {
16 SysBusDevice parent_obj;
18 MemoryRegion iomem;
19 uint8_t mr[2];
20 uint8_t sr;
21 uint8_t isr;
22 uint8_t imr;
23 uint8_t bg1;
24 uint8_t bg2;
25 uint8_t fifo[4];
26 uint8_t tb;
27 int current_mr;
28 int fifo_len;
29 int tx_enabled;
30 int rx_enabled;
31 qemu_irq irq;
32 CharBackend chr;
33 } mcf_uart_state;
35 #define TYPE_MCF_UART "mcf-uart"
36 #define MCF_UART(obj) OBJECT_CHECK(mcf_uart_state, (obj), TYPE_MCF_UART)
38 /* UART Status Register bits. */
39 #define MCF_UART_RxRDY 0x01
40 #define MCF_UART_FFULL 0x02
41 #define MCF_UART_TxRDY 0x04
42 #define MCF_UART_TxEMP 0x08
43 #define MCF_UART_OE 0x10
44 #define MCF_UART_PE 0x20
45 #define MCF_UART_FE 0x40
46 #define MCF_UART_RB 0x80
48 /* Interrupt flags. */
49 #define MCF_UART_TxINT 0x01
50 #define MCF_UART_RxINT 0x02
51 #define MCF_UART_DBINT 0x04
52 #define MCF_UART_COSINT 0x80
54 /* UMR1 flags. */
55 #define MCF_UART_BC0 0x01
56 #define MCF_UART_BC1 0x02
57 #define MCF_UART_PT 0x04
58 #define MCF_UART_PM0 0x08
59 #define MCF_UART_PM1 0x10
60 #define MCF_UART_ERR 0x20
61 #define MCF_UART_RxIRQ 0x40
62 #define MCF_UART_RxRTS 0x80
64 static void mcf_uart_update(mcf_uart_state *s)
66 s->isr &= ~(MCF_UART_TxINT | MCF_UART_RxINT);
67 if (s->sr & MCF_UART_TxRDY)
68 s->isr |= MCF_UART_TxINT;
69 if ((s->sr & ((s->mr[0] & MCF_UART_RxIRQ)
70 ? MCF_UART_FFULL : MCF_UART_RxRDY)) != 0)
71 s->isr |= MCF_UART_RxINT;
73 qemu_set_irq(s->irq, (s->isr & s->imr) != 0);
76 uint64_t mcf_uart_read(void *opaque, hwaddr addr,
77 unsigned size)
79 mcf_uart_state *s = (mcf_uart_state *)opaque;
80 switch (addr & 0x3f) {
81 case 0x00:
82 return s->mr[s->current_mr];
83 case 0x04:
84 return s->sr;
85 case 0x0c:
87 uint8_t val;
88 int i;
90 if (s->fifo_len == 0)
91 return 0;
93 val = s->fifo[0];
94 s->fifo_len--;
95 for (i = 0; i < s->fifo_len; i++)
96 s->fifo[i] = s->fifo[i + 1];
97 s->sr &= ~MCF_UART_FFULL;
98 if (s->fifo_len == 0)
99 s->sr &= ~MCF_UART_RxRDY;
100 mcf_uart_update(s);
101 qemu_chr_fe_accept_input(&s->chr);
102 return val;
104 case 0x10:
105 /* TODO: Implement IPCR. */
106 return 0;
107 case 0x14:
108 return s->isr;
109 case 0x18:
110 return s->bg1;
111 case 0x1c:
112 return s->bg2;
113 default:
114 return 0;
118 /* Update TxRDY flag and set data if present and enabled. */
119 static void mcf_uart_do_tx(mcf_uart_state *s)
121 if (s->tx_enabled && (s->sr & MCF_UART_TxEMP) == 0) {
122 /* XXX this blocks entire thread. Rewrite to use
123 * qemu_chr_fe_write and background I/O callbacks */
124 qemu_chr_fe_write_all(&s->chr, (unsigned char *)&s->tb, 1);
125 s->sr |= MCF_UART_TxEMP;
127 if (s->tx_enabled) {
128 s->sr |= MCF_UART_TxRDY;
129 } else {
130 s->sr &= ~MCF_UART_TxRDY;
134 static void mcf_do_command(mcf_uart_state *s, uint8_t cmd)
136 /* Misc command. */
137 switch ((cmd >> 4) & 7) {
138 case 0: /* No-op. */
139 break;
140 case 1: /* Reset mode register pointer. */
141 s->current_mr = 0;
142 break;
143 case 2: /* Reset receiver. */
144 s->rx_enabled = 0;
145 s->fifo_len = 0;
146 s->sr &= ~(MCF_UART_RxRDY | MCF_UART_FFULL);
147 break;
148 case 3: /* Reset transmitter. */
149 s->tx_enabled = 0;
150 s->sr |= MCF_UART_TxEMP;
151 s->sr &= ~MCF_UART_TxRDY;
152 break;
153 case 4: /* Reset error status. */
154 break;
155 case 5: /* Reset break-change interrupt. */
156 s->isr &= ~MCF_UART_DBINT;
157 break;
158 case 6: /* Start break. */
159 case 7: /* Stop break. */
160 break;
163 /* Transmitter command. */
164 switch ((cmd >> 2) & 3) {
165 case 0: /* No-op. */
166 break;
167 case 1: /* Enable. */
168 s->tx_enabled = 1;
169 mcf_uart_do_tx(s);
170 break;
171 case 2: /* Disable. */
172 s->tx_enabled = 0;
173 mcf_uart_do_tx(s);
174 break;
175 case 3: /* Reserved. */
176 fprintf(stderr, "mcf_uart: Bad TX command\n");
177 break;
180 /* Receiver command. */
181 switch (cmd & 3) {
182 case 0: /* No-op. */
183 break;
184 case 1: /* Enable. */
185 s->rx_enabled = 1;
186 break;
187 case 2:
188 s->rx_enabled = 0;
189 break;
190 case 3: /* Reserved. */
191 fprintf(stderr, "mcf_uart: Bad RX command\n");
192 break;
196 void mcf_uart_write(void *opaque, hwaddr addr,
197 uint64_t val, unsigned size)
199 mcf_uart_state *s = (mcf_uart_state *)opaque;
200 switch (addr & 0x3f) {
201 case 0x00:
202 s->mr[s->current_mr] = val;
203 s->current_mr = 1;
204 break;
205 case 0x04:
206 /* CSR is ignored. */
207 break;
208 case 0x08: /* Command Register. */
209 mcf_do_command(s, val);
210 break;
211 case 0x0c: /* Transmit Buffer. */
212 s->sr &= ~MCF_UART_TxEMP;
213 s->tb = val;
214 mcf_uart_do_tx(s);
215 break;
216 case 0x10:
217 /* ACR is ignored. */
218 break;
219 case 0x14:
220 s->imr = val;
221 break;
222 default:
223 break;
225 mcf_uart_update(s);
228 static void mcf_uart_reset(DeviceState *dev)
230 mcf_uart_state *s = MCF_UART(dev);
232 s->fifo_len = 0;
233 s->mr[0] = 0;
234 s->mr[1] = 0;
235 s->sr = MCF_UART_TxEMP;
236 s->tx_enabled = 0;
237 s->rx_enabled = 0;
238 s->isr = 0;
239 s->imr = 0;
242 static void mcf_uart_push_byte(mcf_uart_state *s, uint8_t data)
244 /* Break events overwrite the last byte if the fifo is full. */
245 if (s->fifo_len == 4)
246 s->fifo_len--;
248 s->fifo[s->fifo_len] = data;
249 s->fifo_len++;
250 s->sr |= MCF_UART_RxRDY;
251 if (s->fifo_len == 4)
252 s->sr |= MCF_UART_FFULL;
254 mcf_uart_update(s);
257 static void mcf_uart_event(void *opaque, int event)
259 mcf_uart_state *s = (mcf_uart_state *)opaque;
261 switch (event) {
262 case CHR_EVENT_BREAK:
263 s->isr |= MCF_UART_DBINT;
264 mcf_uart_push_byte(s, 0);
265 break;
266 default:
267 break;
271 static int mcf_uart_can_receive(void *opaque)
273 mcf_uart_state *s = (mcf_uart_state *)opaque;
275 return s->rx_enabled && (s->sr & MCF_UART_FFULL) == 0;
278 static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size)
280 mcf_uart_state *s = (mcf_uart_state *)opaque;
282 mcf_uart_push_byte(s, buf[0]);
285 static const MemoryRegionOps mcf_uart_ops = {
286 .read = mcf_uart_read,
287 .write = mcf_uart_write,
288 .endianness = DEVICE_NATIVE_ENDIAN,
291 static void mcf_uart_instance_init(Object *obj)
293 SysBusDevice *dev = SYS_BUS_DEVICE(obj);
294 mcf_uart_state *s = MCF_UART(dev);
296 memory_region_init_io(&s->iomem, obj, &mcf_uart_ops, s, "uart", 0x40);
297 sysbus_init_mmio(dev, &s->iomem);
299 sysbus_init_irq(dev, &s->irq);
302 static void mcf_uart_realize(DeviceState *dev, Error **errp)
304 mcf_uart_state *s = MCF_UART(dev);
306 qemu_chr_fe_set_handlers(&s->chr, mcf_uart_can_receive, mcf_uart_receive,
307 mcf_uart_event, NULL, s, NULL, true);
310 static Property mcf_uart_properties[] = {
311 DEFINE_PROP_CHR("chardev", mcf_uart_state, chr),
312 DEFINE_PROP_END_OF_LIST(),
315 static void mcf_uart_class_init(ObjectClass *oc, void *data)
317 DeviceClass *dc = DEVICE_CLASS(oc);
319 dc->realize = mcf_uart_realize;
320 dc->reset = mcf_uart_reset;
321 dc->props = mcf_uart_properties;
322 set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
325 static const TypeInfo mcf_uart_info = {
326 .name = TYPE_MCF_UART,
327 .parent = TYPE_SYS_BUS_DEVICE,
328 .instance_size = sizeof(mcf_uart_state),
329 .instance_init = mcf_uart_instance_init,
330 .class_init = mcf_uart_class_init,
333 static void mcf_uart_register(void)
335 type_register_static(&mcf_uart_info);
338 type_init(mcf_uart_register)
340 void *mcf_uart_init(qemu_irq irq, Chardev *chrdrv)
342 DeviceState *dev;
344 dev = qdev_create(NULL, TYPE_MCF_UART);
345 if (chrdrv) {
346 qdev_prop_set_chr(dev, "chardev", chrdrv);
348 qdev_init_nofail(dev);
350 sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
352 return dev;
355 void mcf_uart_mm_init(hwaddr base, qemu_irq irq, Chardev *chrdrv)
357 DeviceState *dev;
359 dev = mcf_uart_init(irq, chrdrv);
360 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);