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