1 /* 2 * Arm PrimeCell PL011 UART 3 * 4 * Copyright (c) 2006 CodeSourcery. 5 * Written by Paul Brook 6 * 7 * This code is licensed under the GPL. 8 */ 9 10 /* 11 * QEMU interface: 12 * + sysbus MMIO region 0: device registers 13 * + sysbus IRQ 0: UARTINTR (combined interrupt line) 14 * + sysbus IRQ 1: UARTRXINTR (receive FIFO interrupt line) 15 * + sysbus IRQ 2: UARTTXINTR (transmit FIFO interrupt line) 16 * + sysbus IRQ 3: UARTRTINTR (receive timeout interrupt line) 17 * + sysbus IRQ 4: UARTMSINTR (momem status interrupt line) 18 * + sysbus IRQ 5: UARTEINTR (error interrupt line) 19 */ 20 21 #include "qemu/osdep.h" 22 #include "hw/char/pl011.h" 23 #include "hw/irq.h" 24 #include "hw/sysbus.h" 25 #include "hw/qdev-clock.h" 26 #include "migration/vmstate.h" 27 #include "chardev/char-fe.h" 28 #include "qemu/log.h" 29 #include "qemu/module.h" 30 #include "trace.h" 31 32 #define PL011_INT_TX 0x20 33 #define PL011_INT_RX 0x10 34 35 #define PL011_FLAG_TXFE 0x80 36 #define PL011_FLAG_RXFF 0x40 37 #define PL011_FLAG_TXFF 0x20 38 #define PL011_FLAG_RXFE 0x10 39 40 /* Interrupt status bits in UARTRIS, UARTMIS, UARTIMSC */ 41 #define INT_OE (1 << 10) 42 #define INT_BE (1 << 9) 43 #define INT_PE (1 << 8) 44 #define INT_FE (1 << 7) 45 #define INT_RT (1 << 6) 46 #define INT_TX (1 << 5) 47 #define INT_RX (1 << 4) 48 #define INT_DSR (1 << 3) 49 #define INT_DCD (1 << 2) 50 #define INT_CTS (1 << 1) 51 #define INT_RI (1 << 0) 52 #define INT_E (INT_OE | INT_BE | INT_PE | INT_FE) 53 #define INT_MS (INT_RI | INT_DSR | INT_DCD | INT_CTS) 54 55 static const unsigned char pl011_id_arm[8] = 56 { 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 }; 57 static const unsigned char pl011_id_luminary[8] = 58 { 0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 }; 59 60 /* Which bits in the interrupt status matter for each outbound IRQ line ? */ 61 static const uint32_t irqmask[] = { 62 INT_E | INT_MS | INT_RT | INT_TX | INT_RX, /* combined IRQ */ 63 INT_RX, 64 INT_TX, 65 INT_RT, 66 INT_MS, 67 INT_E, 68 }; 69 70 static void pl011_update(PL011State *s) 71 { 72 uint32_t flags; 73 int i; 74 75 flags = s->int_level & s->int_enabled; 76 trace_pl011_irq_state(flags != 0); 77 for (i = 0; i < ARRAY_SIZE(s->irq); i++) { 78 qemu_set_irq(s->irq[i], (flags & irqmask[i]) != 0); 79 } 80 } 81 82 static uint64_t pl011_read(void *opaque, hwaddr offset, 83 unsigned size) 84 { 85 PL011State *s = (PL011State *)opaque; 86 uint32_t c; 87 uint64_t r; 88 89 switch (offset >> 2) { 90 case 0: /* UARTDR */ 91 s->flags &= ~PL011_FLAG_RXFF; 92 c = s->read_fifo[s->read_pos]; 93 if (s->read_count > 0) { 94 s->read_count--; 95 if (++s->read_pos == 16) 96 s->read_pos = 0; 97 } 98 if (s->read_count == 0) { 99 s->flags |= PL011_FLAG_RXFE; 100 } 101 if (s->read_count == s->read_trigger - 1) 102 s->int_level &= ~ PL011_INT_RX; 103 trace_pl011_read_fifo(s->read_count); 104 s->rsr = c >> 8; 105 pl011_update(s); 106 qemu_chr_fe_accept_input(&s->chr); 107 r = c; 108 break; 109 case 1: /* UARTRSR */ 110 r = s->rsr; 111 break; 112 case 6: /* UARTFR */ 113 r = s->flags; 114 break; 115 case 8: /* UARTILPR */ 116 r = s->ilpr; 117 break; 118 case 9: /* UARTIBRD */ 119 r = s->ibrd; 120 break; 121 case 10: /* UARTFBRD */ 122 r = s->fbrd; 123 break; 124 case 11: /* UARTLCR_H */ 125 r = s->lcr; 126 break; 127 case 12: /* UARTCR */ 128 r = s->cr; 129 break; 130 case 13: /* UARTIFLS */ 131 r = s->ifl; 132 break; 133 case 14: /* UARTIMSC */ 134 r = s->int_enabled; 135 break; 136 case 15: /* UARTRIS */ 137 r = s->int_level; 138 break; 139 case 16: /* UARTMIS */ 140 r = s->int_level & s->int_enabled; 141 break; 142 case 18: /* UARTDMACR */ 143 r = s->dmacr; 144 break; 145 case 0x3f8 ... 0x400: 146 r = s->id[(offset - 0xfe0) >> 2]; 147 break; 148 default: 149 qemu_log_mask(LOG_GUEST_ERROR, 150 "pl011_read: Bad offset 0x%x\n", (int)offset); 151 r = 0; 152 break; 153 } 154 155 trace_pl011_read(offset, r); 156 return r; 157 } 158 159 static void pl011_set_read_trigger(PL011State *s) 160 { 161 #if 0 162 /* The docs say the RX interrupt is triggered when the FIFO exceeds 163 the threshold. However linux only reads the FIFO in response to an 164 interrupt. Triggering the interrupt when the FIFO is non-empty seems 165 to make things work. */ 166 if (s->lcr & 0x10) 167 s->read_trigger = (s->ifl >> 1) & 0x1c; 168 else 169 #endif 170 s->read_trigger = 1; 171 } 172 173 static unsigned int pl011_get_baudrate(const PL011State *s) 174 { 175 uint64_t clk; 176 177 if (s->fbrd == 0) { 178 return 0; 179 } 180 181 clk = clock_get_hz(s->clk); 182 return (clk / ((s->ibrd << 6) + s->fbrd)) << 2; 183 } 184 185 static void pl011_trace_baudrate_change(const PL011State *s) 186 { 187 trace_pl011_baudrate_change(pl011_get_baudrate(s), 188 clock_get_hz(s->clk), 189 s->ibrd, s->fbrd); 190 } 191 192 static void pl011_write(void *opaque, hwaddr offset, 193 uint64_t value, unsigned size) 194 { 195 PL011State *s = (PL011State *)opaque; 196 unsigned char ch; 197 198 trace_pl011_write(offset, value); 199 200 switch (offset >> 2) { 201 case 0: /* UARTDR */ 202 /* ??? Check if transmitter is enabled. */ 203 ch = value; 204 /* XXX this blocks entire thread. Rewrite to use 205 * qemu_chr_fe_write and background I/O callbacks */ 206 qemu_chr_fe_write_all(&s->chr, &ch, 1); 207 s->int_level |= PL011_INT_TX; 208 pl011_update(s); 209 break; 210 case 1: /* UARTRSR/UARTECR */ 211 s->rsr = 0; 212 break; 213 case 6: /* UARTFR */ 214 /* Writes to Flag register are ignored. */ 215 break; 216 case 8: /* UARTUARTILPR */ 217 s->ilpr = value; 218 break; 219 case 9: /* UARTIBRD */ 220 s->ibrd = value; 221 pl011_trace_baudrate_change(s); 222 break; 223 case 10: /* UARTFBRD */ 224 s->fbrd = value; 225 pl011_trace_baudrate_change(s); 226 break; 227 case 11: /* UARTLCR_H */ 228 /* Reset the FIFO state on FIFO enable or disable */ 229 if ((s->lcr ^ value) & 0x10) { 230 s->read_count = 0; 231 s->read_pos = 0; 232 } 233 s->lcr = value; 234 pl011_set_read_trigger(s); 235 break; 236 case 12: /* UARTCR */ 237 /* ??? Need to implement the enable and loopback bits. */ 238 s->cr = value; 239 break; 240 case 13: /* UARTIFS */ 241 s->ifl = value; 242 pl011_set_read_trigger(s); 243 break; 244 case 14: /* UARTIMSC */ 245 s->int_enabled = value; 246 pl011_update(s); 247 break; 248 case 17: /* UARTICR */ 249 s->int_level &= ~value; 250 pl011_update(s); 251 break; 252 case 18: /* UARTDMACR */ 253 s->dmacr = value; 254 if (value & 3) { 255 qemu_log_mask(LOG_UNIMP, "pl011: DMA not implemented\n"); 256 } 257 break; 258 default: 259 qemu_log_mask(LOG_GUEST_ERROR, 260 "pl011_write: Bad offset 0x%x\n", (int)offset); 261 } 262 } 263 264 static int pl011_can_receive(void *opaque) 265 { 266 PL011State *s = (PL011State *)opaque; 267 int r; 268 269 if (s->lcr & 0x10) { 270 r = s->read_count < 16; 271 } else { 272 r = s->read_count < 1; 273 } 274 trace_pl011_can_receive(s->lcr, s->read_count, r); 275 return r; 276 } 277 278 static void pl011_put_fifo(void *opaque, uint32_t value) 279 { 280 PL011State *s = (PL011State *)opaque; 281 int slot; 282 283 slot = s->read_pos + s->read_count; 284 if (slot >= 16) 285 slot -= 16; 286 s->read_fifo[slot] = value; 287 s->read_count++; 288 s->flags &= ~PL011_FLAG_RXFE; 289 trace_pl011_put_fifo(value, s->read_count); 290 if (!(s->lcr & 0x10) || s->read_count == 16) { 291 trace_pl011_put_fifo_full(); 292 s->flags |= PL011_FLAG_RXFF; 293 } 294 if (s->read_count == s->read_trigger) { 295 s->int_level |= PL011_INT_RX; 296 pl011_update(s); 297 } 298 } 299 300 static void pl011_receive(void *opaque, const uint8_t *buf, int size) 301 { 302 pl011_put_fifo(opaque, *buf); 303 } 304 305 static void pl011_event(void *opaque, QEMUChrEvent event) 306 { 307 if (event == CHR_EVENT_BREAK) 308 pl011_put_fifo(opaque, 0x400); 309 } 310 311 static void pl011_clock_update(void *opaque) 312 { 313 PL011State *s = PL011(opaque); 314 315 pl011_trace_baudrate_change(s); 316 } 317 318 static const MemoryRegionOps pl011_ops = { 319 .read = pl011_read, 320 .write = pl011_write, 321 .endianness = DEVICE_NATIVE_ENDIAN, 322 }; 323 324 static const VMStateDescription vmstate_pl011_clock = { 325 .name = "pl011/clock", 326 .version_id = 1, 327 .minimum_version_id = 1, 328 .fields = (VMStateField[]) { 329 VMSTATE_CLOCK(clk, PL011State), 330 VMSTATE_END_OF_LIST() 331 } 332 }; 333 334 static const VMStateDescription vmstate_pl011 = { 335 .name = "pl011", 336 .version_id = 2, 337 .minimum_version_id = 2, 338 .fields = (VMStateField[]) { 339 VMSTATE_UINT32(readbuff, PL011State), 340 VMSTATE_UINT32(flags, PL011State), 341 VMSTATE_UINT32(lcr, PL011State), 342 VMSTATE_UINT32(rsr, PL011State), 343 VMSTATE_UINT32(cr, PL011State), 344 VMSTATE_UINT32(dmacr, PL011State), 345 VMSTATE_UINT32(int_enabled, PL011State), 346 VMSTATE_UINT32(int_level, PL011State), 347 VMSTATE_UINT32_ARRAY(read_fifo, PL011State, 16), 348 VMSTATE_UINT32(ilpr, PL011State), 349 VMSTATE_UINT32(ibrd, PL011State), 350 VMSTATE_UINT32(fbrd, PL011State), 351 VMSTATE_UINT32(ifl, PL011State), 352 VMSTATE_INT32(read_pos, PL011State), 353 VMSTATE_INT32(read_count, PL011State), 354 VMSTATE_INT32(read_trigger, PL011State), 355 VMSTATE_END_OF_LIST() 356 }, 357 .subsections = (const VMStateDescription * []) { 358 &vmstate_pl011_clock, 359 NULL 360 } 361 }; 362 363 static Property pl011_properties[] = { 364 DEFINE_PROP_CHR("chardev", PL011State, chr), 365 DEFINE_PROP_END_OF_LIST(), 366 }; 367 368 static void pl011_init(Object *obj) 369 { 370 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 371 PL011State *s = PL011(obj); 372 int i; 373 374 memory_region_init_io(&s->iomem, OBJECT(s), &pl011_ops, s, "pl011", 0x1000); 375 sysbus_init_mmio(sbd, &s->iomem); 376 for (i = 0; i < ARRAY_SIZE(s->irq); i++) { 377 sysbus_init_irq(sbd, &s->irq[i]); 378 } 379 380 s->clk = qdev_init_clock_in(DEVICE(obj), "clk", pl011_clock_update, s); 381 382 s->read_trigger = 1; 383 s->ifl = 0x12; 384 s->cr = 0x300; 385 s->flags = 0x90; 386 387 s->id = pl011_id_arm; 388 } 389 390 static void pl011_realize(DeviceState *dev, Error **errp) 391 { 392 PL011State *s = PL011(dev); 393 394 qemu_chr_fe_set_handlers(&s->chr, pl011_can_receive, pl011_receive, 395 pl011_event, NULL, s, NULL, true); 396 } 397 398 static void pl011_class_init(ObjectClass *oc, void *data) 399 { 400 DeviceClass *dc = DEVICE_CLASS(oc); 401 402 dc->realize = pl011_realize; 403 dc->vmsd = &vmstate_pl011; 404 device_class_set_props(dc, pl011_properties); 405 } 406 407 static const TypeInfo pl011_arm_info = { 408 .name = TYPE_PL011, 409 .parent = TYPE_SYS_BUS_DEVICE, 410 .instance_size = sizeof(PL011State), 411 .instance_init = pl011_init, 412 .class_init = pl011_class_init, 413 }; 414 415 static void pl011_luminary_init(Object *obj) 416 { 417 PL011State *s = PL011(obj); 418 419 s->id = pl011_id_luminary; 420 } 421 422 static const TypeInfo pl011_luminary_info = { 423 .name = TYPE_PL011_LUMINARY, 424 .parent = TYPE_PL011, 425 .instance_init = pl011_luminary_init, 426 }; 427 428 static void pl011_register_types(void) 429 { 430 type_register_static(&pl011_arm_info); 431 type_register_static(&pl011_luminary_info); 432 } 433 434 type_init(pl011_register_types) 435