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