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