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