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