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