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" 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 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. */ 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 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 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 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 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 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 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 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 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 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 325 static void mcf_uart_class_init(ObjectClass *oc, 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 343 static void mcf_uart_register(void) 344 { 345 type_register_static(&mcf_uart_info); 346 } 347 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 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