1 /*
2 * ColdFire UART emulation.
3 *
4 * Copyright (c) 2007 CodeSourcery.
5 *
6 * This code is licensed under the GPL
7 */
8
9 #include "qemu/osdep.h"
10 #include "hw/irq.h"
11 #include "hw/sysbus.h"
12 #include "qemu/module.h"
13 #include "qapi/error.h"
14 #include "hw/m68k/mcf.h"
15 #include "hw/qdev-properties.h"
16 #include "hw/qdev-properties-system.h"
17 #include "chardev/char-fe.h"
18 #include "qom/object.h"
19
20 #define FIFO_DEPTH 4
21
22 struct mcf_uart_state {
23 SysBusDevice parent_obj;
24
25 MemoryRegion iomem;
26 uint8_t mr[2];
27 uint8_t sr;
28 uint8_t isr;
29 uint8_t imr;
30 uint8_t bg1;
31 uint8_t bg2;
32 uint8_t fifo[FIFO_DEPTH];
33 uint8_t tb;
34 int current_mr;
35 int fifo_len;
36 int tx_enabled;
37 int rx_enabled;
38 qemu_irq irq;
39 CharBackend chr;
40 };
41
42 #define TYPE_MCF_UART "mcf-uart"
OBJECT_DECLARE_SIMPLE_TYPE(mcf_uart_state,MCF_UART)43 OBJECT_DECLARE_SIMPLE_TYPE(mcf_uart_state, MCF_UART)
44
45 /* UART Status Register bits. */
46 #define MCF_UART_RxRDY 0x01
47 #define MCF_UART_FFULL 0x02
48 #define MCF_UART_TxRDY 0x04
49 #define MCF_UART_TxEMP 0x08
50 #define MCF_UART_OE 0x10
51 #define MCF_UART_PE 0x20
52 #define MCF_UART_FE 0x40
53 #define MCF_UART_RB 0x80
54
55 /* Interrupt flags. */
56 #define MCF_UART_TxINT 0x01
57 #define MCF_UART_RxINT 0x02
58 #define MCF_UART_DBINT 0x04
59 #define MCF_UART_COSINT 0x80
60
61 /* UMR1 flags. */
62 #define MCF_UART_BC0 0x01
63 #define MCF_UART_BC1 0x02
64 #define MCF_UART_PT 0x04
65 #define MCF_UART_PM0 0x08
66 #define MCF_UART_PM1 0x10
67 #define MCF_UART_ERR 0x20
68 #define MCF_UART_RxIRQ 0x40
69 #define MCF_UART_RxRTS 0x80
70
71 static void mcf_uart_update(mcf_uart_state *s)
72 {
73 s->isr &= ~(MCF_UART_TxINT | MCF_UART_RxINT);
74 if (s->sr & MCF_UART_TxRDY)
75 s->isr |= MCF_UART_TxINT;
76 if ((s->sr & ((s->mr[0] & MCF_UART_RxIRQ)
77 ? MCF_UART_FFULL : MCF_UART_RxRDY)) != 0)
78 s->isr |= MCF_UART_RxINT;
79
80 qemu_set_irq(s->irq, (s->isr & s->imr) != 0);
81 }
82
mcf_uart_read(void * opaque,hwaddr addr,unsigned size)83 uint64_t mcf_uart_read(void *opaque, hwaddr addr,
84 unsigned size)
85 {
86 mcf_uart_state *s = (mcf_uart_state *)opaque;
87 switch (addr & 0x3f) {
88 case 0x00:
89 return s->mr[s->current_mr];
90 case 0x04:
91 return s->sr;
92 case 0x0c:
93 {
94 uint8_t val;
95 int i;
96
97 if (s->fifo_len == 0)
98 return 0;
99
100 val = s->fifo[0];
101 s->fifo_len--;
102 for (i = 0; i < s->fifo_len; i++)
103 s->fifo[i] = s->fifo[i + 1];
104 s->sr &= ~MCF_UART_FFULL;
105 if (s->fifo_len == 0)
106 s->sr &= ~MCF_UART_RxRDY;
107 mcf_uart_update(s);
108 qemu_chr_fe_accept_input(&s->chr);
109 return val;
110 }
111 case 0x10:
112 /* TODO: Implement IPCR. */
113 return 0;
114 case 0x14:
115 return s->isr;
116 case 0x18:
117 return s->bg1;
118 case 0x1c:
119 return s->bg2;
120 default:
121 return 0;
122 }
123 }
124
125 /* Update TxRDY flag and set data if present and enabled. */
mcf_uart_do_tx(mcf_uart_state * s)126 static void mcf_uart_do_tx(mcf_uart_state *s)
127 {
128 if (s->tx_enabled && (s->sr & MCF_UART_TxEMP) == 0) {
129 /* XXX this blocks entire thread. Rewrite to use
130 * qemu_chr_fe_write and background I/O callbacks */
131 qemu_chr_fe_write_all(&s->chr, (unsigned char *)&s->tb, 1);
132 s->sr |= MCF_UART_TxEMP;
133 }
134 if (s->tx_enabled) {
135 s->sr |= MCF_UART_TxRDY;
136 } else {
137 s->sr &= ~MCF_UART_TxRDY;
138 }
139 }
140
mcf_do_command(mcf_uart_state * s,uint8_t cmd)141 static void mcf_do_command(mcf_uart_state *s, uint8_t cmd)
142 {
143 /* Misc command. */
144 switch ((cmd >> 4) & 7) {
145 case 0: /* No-op. */
146 break;
147 case 1: /* Reset mode register pointer. */
148 s->current_mr = 0;
149 break;
150 case 2: /* Reset receiver. */
151 s->rx_enabled = 0;
152 s->fifo_len = 0;
153 s->sr &= ~(MCF_UART_RxRDY | MCF_UART_FFULL);
154 break;
155 case 3: /* Reset transmitter. */
156 s->tx_enabled = 0;
157 s->sr |= MCF_UART_TxEMP;
158 s->sr &= ~MCF_UART_TxRDY;
159 break;
160 case 4: /* Reset error status. */
161 break;
162 case 5: /* Reset break-change interrupt. */
163 s->isr &= ~MCF_UART_DBINT;
164 break;
165 case 6: /* Start break. */
166 case 7: /* Stop break. */
167 break;
168 }
169
170 /* Transmitter command. */
171 switch ((cmd >> 2) & 3) {
172 case 0: /* No-op. */
173 break;
174 case 1: /* Enable. */
175 s->tx_enabled = 1;
176 mcf_uart_do_tx(s);
177 break;
178 case 2: /* Disable. */
179 s->tx_enabled = 0;
180 mcf_uart_do_tx(s);
181 break;
182 case 3: /* Reserved. */
183 fprintf(stderr, "mcf_uart: Bad TX command\n");
184 break;
185 }
186
187 /* Receiver command. */
188 switch (cmd & 3) {
189 case 0: /* No-op. */
190 break;
191 case 1: /* Enable. */
192 s->rx_enabled = 1;
193 break;
194 case 2:
195 s->rx_enabled = 0;
196 break;
197 case 3: /* Reserved. */
198 fprintf(stderr, "mcf_uart: Bad RX command\n");
199 break;
200 }
201 }
202
mcf_uart_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)203 void mcf_uart_write(void *opaque, hwaddr addr,
204 uint64_t val, unsigned size)
205 {
206 mcf_uart_state *s = (mcf_uart_state *)opaque;
207 switch (addr & 0x3f) {
208 case 0x00:
209 s->mr[s->current_mr] = val;
210 s->current_mr = 1;
211 break;
212 case 0x04:
213 /* CSR is ignored. */
214 break;
215 case 0x08: /* Command Register. */
216 mcf_do_command(s, val);
217 break;
218 case 0x0c: /* Transmit Buffer. */
219 s->sr &= ~MCF_UART_TxEMP;
220 s->tb = val;
221 mcf_uart_do_tx(s);
222 break;
223 case 0x10:
224 /* ACR is ignored. */
225 break;
226 case 0x14:
227 s->imr = val;
228 break;
229 default:
230 break;
231 }
232 mcf_uart_update(s);
233 }
234
mcf_uart_reset(DeviceState * dev)235 static void mcf_uart_reset(DeviceState *dev)
236 {
237 mcf_uart_state *s = MCF_UART(dev);
238
239 s->fifo_len = 0;
240 s->mr[0] = 0;
241 s->mr[1] = 0;
242 s->sr = MCF_UART_TxEMP;
243 s->tx_enabled = 0;
244 s->rx_enabled = 0;
245 s->isr = 0;
246 s->imr = 0;
247 }
248
mcf_uart_push_byte(mcf_uart_state * s,uint8_t data)249 static void mcf_uart_push_byte(mcf_uart_state *s, uint8_t data)
250 {
251 /* Break events overwrite the last byte if the fifo is full. */
252 if (s->fifo_len == FIFO_DEPTH) {
253 s->fifo_len--;
254 }
255
256 s->fifo[s->fifo_len] = data;
257 s->fifo_len++;
258 s->sr |= MCF_UART_RxRDY;
259 if (s->fifo_len == FIFO_DEPTH) {
260 s->sr |= MCF_UART_FFULL;
261 }
262
263 mcf_uart_update(s);
264 }
265
mcf_uart_event(void * opaque,QEMUChrEvent event)266 static void mcf_uart_event(void *opaque, QEMUChrEvent event)
267 {
268 mcf_uart_state *s = (mcf_uart_state *)opaque;
269
270 switch (event) {
271 case CHR_EVENT_BREAK:
272 s->isr |= MCF_UART_DBINT;
273 mcf_uart_push_byte(s, 0);
274 break;
275 default:
276 break;
277 }
278 }
279
mcf_uart_can_receive(void * opaque)280 static int mcf_uart_can_receive(void *opaque)
281 {
282 mcf_uart_state *s = (mcf_uart_state *)opaque;
283
284 return s->rx_enabled ? FIFO_DEPTH - s->fifo_len : 0;
285 }
286
mcf_uart_receive(void * opaque,const uint8_t * buf,int size)287 static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size)
288 {
289 mcf_uart_state *s = (mcf_uart_state *)opaque;
290
291 for (int i = 0; i < size; i++) {
292 mcf_uart_push_byte(s, buf[i]);
293 }
294 }
295
296 static const MemoryRegionOps mcf_uart_ops = {
297 .read = mcf_uart_read,
298 .write = mcf_uart_write,
299 .endianness = DEVICE_NATIVE_ENDIAN,
300 };
301
mcf_uart_instance_init(Object * obj)302 static void mcf_uart_instance_init(Object *obj)
303 {
304 SysBusDevice *dev = SYS_BUS_DEVICE(obj);
305 mcf_uart_state *s = MCF_UART(dev);
306
307 memory_region_init_io(&s->iomem, obj, &mcf_uart_ops, s, "uart", 0x40);
308 sysbus_init_mmio(dev, &s->iomem);
309
310 sysbus_init_irq(dev, &s->irq);
311 }
312
mcf_uart_realize(DeviceState * dev,Error ** errp)313 static void mcf_uart_realize(DeviceState *dev, Error **errp)
314 {
315 mcf_uart_state *s = MCF_UART(dev);
316
317 qemu_chr_fe_set_handlers(&s->chr, mcf_uart_can_receive, mcf_uart_receive,
318 mcf_uart_event, NULL, s, NULL, true);
319 }
320
321 static const Property mcf_uart_properties[] = {
322 DEFINE_PROP_CHR("chardev", mcf_uart_state, chr),
323 };
324
mcf_uart_class_init(ObjectClass * oc,const void * data)325 static void mcf_uart_class_init(ObjectClass *oc, const void *data)
326 {
327 DeviceClass *dc = DEVICE_CLASS(oc);
328
329 dc->realize = mcf_uart_realize;
330 device_class_set_legacy_reset(dc, mcf_uart_reset);
331 device_class_set_props(dc, mcf_uart_properties);
332 set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
333 }
334
335 static const TypeInfo mcf_uart_info = {
336 .name = TYPE_MCF_UART,
337 .parent = TYPE_SYS_BUS_DEVICE,
338 .instance_size = sizeof(mcf_uart_state),
339 .instance_init = mcf_uart_instance_init,
340 .class_init = mcf_uart_class_init,
341 };
342
mcf_uart_register(void)343 static void mcf_uart_register(void)
344 {
345 type_register_static(&mcf_uart_info);
346 }
347
type_init(mcf_uart_register)348 type_init(mcf_uart_register)
349
350 DeviceState *mcf_uart_create(qemu_irq irq, Chardev *chrdrv)
351 {
352 DeviceState *dev;
353
354 dev = qdev_new(TYPE_MCF_UART);
355 if (chrdrv) {
356 qdev_prop_set_chr(dev, "chardev", chrdrv);
357 }
358 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
359 sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
360
361 return dev;
362 }
363
mcf_uart_create_mmap(hwaddr base,qemu_irq irq,Chardev * chrdrv)364 DeviceState *mcf_uart_create_mmap(hwaddr base, qemu_irq irq, Chardev *chrdrv)
365 {
366 DeviceState *dev;
367
368 dev = mcf_uart_create(irq, chrdrv);
369 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
370
371 return dev;
372 }
373