1 /* 2 * Motorola ColdFire MCF5206 SoC embedded peripheral emulation. 3 * 4 * Copyright (c) 2007 CodeSourcery. 5 * 6 * This code is licensed under the GPL 7 */ 8 9 #include "qemu/osdep.h" 10 #include "qemu/error-report.h" 11 #include "qemu/log.h" 12 #include "cpu.h" 13 #include "hw/irq.h" 14 #include "hw/m68k/mcf.h" 15 #include "qemu/timer.h" 16 #include "hw/ptimer.h" 17 #include "sysemu/sysemu.h" 18 #include "hw/sysbus.h" 19 20 /* General purpose timer module. */ 21 typedef struct { 22 uint16_t tmr; 23 uint16_t trr; 24 uint16_t tcr; 25 uint16_t ter; 26 ptimer_state *timer; 27 qemu_irq irq; 28 int irq_state; 29 } m5206_timer_state; 30 31 #define TMR_RST 0x01 32 #define TMR_CLK 0x06 33 #define TMR_FRR 0x08 34 #define TMR_ORI 0x10 35 #define TMR_OM 0x20 36 #define TMR_CE 0xc0 37 38 #define TER_CAP 0x01 39 #define TER_REF 0x02 40 41 static void m5206_timer_update(m5206_timer_state *s) 42 { 43 if ((s->tmr & TMR_ORI) != 0 && (s->ter & TER_REF)) 44 qemu_irq_raise(s->irq); 45 else 46 qemu_irq_lower(s->irq); 47 } 48 49 static void m5206_timer_reset(m5206_timer_state *s) 50 { 51 s->tmr = 0; 52 s->trr = 0; 53 } 54 55 static void m5206_timer_recalibrate(m5206_timer_state *s) 56 { 57 int prescale; 58 int mode; 59 60 ptimer_transaction_begin(s->timer); 61 ptimer_stop(s->timer); 62 63 if ((s->tmr & TMR_RST) == 0) { 64 goto exit; 65 } 66 67 prescale = (s->tmr >> 8) + 1; 68 mode = (s->tmr >> 1) & 3; 69 if (mode == 2) 70 prescale *= 16; 71 72 if (mode == 3 || mode == 0) { 73 qemu_log_mask(LOG_UNIMP, "m5206_timer: mode %d not implemented\n", 74 mode); 75 goto exit; 76 } 77 if ((s->tmr & TMR_FRR) == 0) { 78 qemu_log_mask(LOG_UNIMP, 79 "m5206_timer: free running mode not implemented\n"); 80 goto exit; 81 } 82 83 /* Assume 66MHz system clock. */ 84 ptimer_set_freq(s->timer, 66000000 / prescale); 85 86 ptimer_set_limit(s->timer, s->trr, 0); 87 88 ptimer_run(s->timer, 0); 89 exit: 90 ptimer_transaction_commit(s->timer); 91 } 92 93 static void m5206_timer_trigger(void *opaque) 94 { 95 m5206_timer_state *s = (m5206_timer_state *)opaque; 96 s->ter |= TER_REF; 97 m5206_timer_update(s); 98 } 99 100 static uint32_t m5206_timer_read(m5206_timer_state *s, uint32_t addr) 101 { 102 switch (addr) { 103 case 0: 104 return s->tmr; 105 case 4: 106 return s->trr; 107 case 8: 108 return s->tcr; 109 case 0xc: 110 return s->trr - ptimer_get_count(s->timer); 111 case 0x11: 112 return s->ter; 113 default: 114 return 0; 115 } 116 } 117 118 static void m5206_timer_write(m5206_timer_state *s, uint32_t addr, uint32_t val) 119 { 120 switch (addr) { 121 case 0: 122 if ((s->tmr & TMR_RST) != 0 && (val & TMR_RST) == 0) { 123 m5206_timer_reset(s); 124 } 125 s->tmr = val; 126 m5206_timer_recalibrate(s); 127 break; 128 case 4: 129 s->trr = val; 130 m5206_timer_recalibrate(s); 131 break; 132 case 8: 133 s->tcr = val; 134 break; 135 case 0xc: 136 ptimer_transaction_begin(s->timer); 137 ptimer_set_count(s->timer, val); 138 ptimer_transaction_commit(s->timer); 139 break; 140 case 0x11: 141 s->ter &= ~val; 142 break; 143 default: 144 break; 145 } 146 m5206_timer_update(s); 147 } 148 149 static m5206_timer_state *m5206_timer_init(qemu_irq irq) 150 { 151 m5206_timer_state *s; 152 153 s = g_new0(m5206_timer_state, 1); 154 s->timer = ptimer_init(m5206_timer_trigger, s, PTIMER_POLICY_DEFAULT); 155 s->irq = irq; 156 m5206_timer_reset(s); 157 return s; 158 } 159 160 /* System Integration Module. */ 161 162 typedef struct { 163 SysBusDevice parent_obj; 164 165 M68kCPU *cpu; 166 MemoryRegion iomem; 167 qemu_irq *pic; 168 m5206_timer_state *timer[2]; 169 void *uart[2]; 170 uint8_t scr; 171 uint8_t icr[14]; 172 uint16_t imr; /* 1 == interrupt is masked. */ 173 uint16_t ipr; 174 uint8_t rsr; 175 uint8_t swivr; 176 uint8_t par; 177 /* Include the UART vector registers here. */ 178 uint8_t uivr[2]; 179 } m5206_mbar_state; 180 181 #define MCF5206_MBAR(obj) OBJECT_CHECK(m5206_mbar_state, (obj), TYPE_MCF5206_MBAR) 182 183 /* Interrupt controller. */ 184 185 static int m5206_find_pending_irq(m5206_mbar_state *s) 186 { 187 int level; 188 int vector; 189 uint16_t active; 190 int i; 191 192 level = 0; 193 vector = 0; 194 active = s->ipr & ~s->imr; 195 if (!active) 196 return 0; 197 198 for (i = 1; i < 14; i++) { 199 if (active & (1 << i)) { 200 if ((s->icr[i] & 0x1f) > level) { 201 level = s->icr[i] & 0x1f; 202 vector = i; 203 } 204 } 205 } 206 207 if (level < 4) 208 vector = 0; 209 210 return vector; 211 } 212 213 static void m5206_mbar_update(m5206_mbar_state *s) 214 { 215 int irq; 216 int vector; 217 int level; 218 219 irq = m5206_find_pending_irq(s); 220 if (irq) { 221 int tmp; 222 tmp = s->icr[irq]; 223 level = (tmp >> 2) & 7; 224 if (tmp & 0x80) { 225 /* Autovector. */ 226 vector = 24 + level; 227 } else { 228 switch (irq) { 229 case 8: /* SWT */ 230 vector = s->swivr; 231 break; 232 case 12: /* UART1 */ 233 vector = s->uivr[0]; 234 break; 235 case 13: /* UART2 */ 236 vector = s->uivr[1]; 237 break; 238 default: 239 /* Unknown vector. */ 240 qemu_log_mask(LOG_UNIMP, "%s: Unhandled vector for IRQ %d\n", 241 __func__, irq); 242 vector = 0xf; 243 break; 244 } 245 } 246 } else { 247 level = 0; 248 vector = 0; 249 } 250 m68k_set_irq_level(s->cpu, level, vector); 251 } 252 253 static void m5206_mbar_set_irq(void *opaque, int irq, int level) 254 { 255 m5206_mbar_state *s = (m5206_mbar_state *)opaque; 256 if (level) { 257 s->ipr |= 1 << irq; 258 } else { 259 s->ipr &= ~(1 << irq); 260 } 261 m5206_mbar_update(s); 262 } 263 264 /* System Integration Module. */ 265 266 static void m5206_mbar_reset(DeviceState *dev) 267 { 268 m5206_mbar_state *s = MCF5206_MBAR(dev); 269 270 s->scr = 0xc0; 271 s->icr[1] = 0x04; 272 s->icr[2] = 0x08; 273 s->icr[3] = 0x0c; 274 s->icr[4] = 0x10; 275 s->icr[5] = 0x14; 276 s->icr[6] = 0x18; 277 s->icr[7] = 0x1c; 278 s->icr[8] = 0x1c; 279 s->icr[9] = 0x80; 280 s->icr[10] = 0x80; 281 s->icr[11] = 0x80; 282 s->icr[12] = 0x00; 283 s->icr[13] = 0x00; 284 s->imr = 0x3ffe; 285 s->rsr = 0x80; 286 s->swivr = 0x0f; 287 s->par = 0; 288 } 289 290 static uint64_t m5206_mbar_read(m5206_mbar_state *s, 291 uint16_t offset, unsigned size) 292 { 293 if (offset >= 0x100 && offset < 0x120) { 294 return m5206_timer_read(s->timer[0], offset - 0x100); 295 } else if (offset >= 0x120 && offset < 0x140) { 296 return m5206_timer_read(s->timer[1], offset - 0x120); 297 } else if (offset >= 0x140 && offset < 0x160) { 298 return mcf_uart_read(s->uart[0], offset - 0x140, size); 299 } else if (offset >= 0x180 && offset < 0x1a0) { 300 return mcf_uart_read(s->uart[1], offset - 0x180, size); 301 } 302 switch (offset) { 303 case 0x03: return s->scr; 304 case 0x14 ... 0x20: return s->icr[offset - 0x13]; 305 case 0x36: return s->imr; 306 case 0x3a: return s->ipr; 307 case 0x40: return s->rsr; 308 case 0x41: return 0; 309 case 0x42: return s->swivr; 310 case 0x50: 311 /* DRAM mask register. */ 312 /* FIXME: currently hardcoded to 128Mb. */ 313 { 314 uint32_t mask = ~0; 315 while (mask > ram_size) 316 mask >>= 1; 317 return mask & 0x0ffe0000; 318 } 319 case 0x5c: return 1; /* DRAM bank 1 empty. */ 320 case 0xcb: return s->par; 321 case 0x170: return s->uivr[0]; 322 case 0x1b0: return s->uivr[1]; 323 } 324 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad MBAR offset 0x%"PRIx16"\n", 325 __func__, offset); 326 return 0; 327 } 328 329 static void m5206_mbar_write(m5206_mbar_state *s, uint16_t offset, 330 uint64_t value, unsigned size) 331 { 332 if (offset >= 0x100 && offset < 0x120) { 333 m5206_timer_write(s->timer[0], offset - 0x100, value); 334 return; 335 } else if (offset >= 0x120 && offset < 0x140) { 336 m5206_timer_write(s->timer[1], offset - 0x120, value); 337 return; 338 } else if (offset >= 0x140 && offset < 0x160) { 339 mcf_uart_write(s->uart[0], offset - 0x140, value, size); 340 return; 341 } else if (offset >= 0x180 && offset < 0x1a0) { 342 mcf_uart_write(s->uart[1], offset - 0x180, value, size); 343 return; 344 } 345 switch (offset) { 346 case 0x03: 347 s->scr = value; 348 break; 349 case 0x14 ... 0x20: 350 s->icr[offset - 0x13] = value; 351 m5206_mbar_update(s); 352 break; 353 case 0x36: 354 s->imr = value; 355 m5206_mbar_update(s); 356 break; 357 case 0x40: 358 s->rsr &= ~value; 359 break; 360 case 0x41: 361 /* TODO: implement watchdog. */ 362 break; 363 case 0x42: 364 s->swivr = value; 365 break; 366 case 0xcb: 367 s->par = value; 368 break; 369 case 0x170: 370 s->uivr[0] = value; 371 break; 372 case 0x178: case 0x17c: case 0x1c8: case 0x1bc: 373 /* Not implemented: UART Output port bits. */ 374 break; 375 case 0x1b0: 376 s->uivr[1] = value; 377 break; 378 default: 379 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad MBAR offset 0x%"PRIx16"\n", 380 __func__, offset); 381 break; 382 } 383 } 384 385 /* Internal peripherals use a variety of register widths. 386 This lookup table allows a single routine to handle all of them. */ 387 static const uint8_t m5206_mbar_width[] = 388 { 389 /* 000-040 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 390 /* 040-080 */ 1, 2, 2, 2, 4, 1, 2, 4, 1, 2, 4, 2, 2, 4, 2, 2, 391 /* 080-0c0 */ 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 392 /* 0c0-100 */ 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 393 /* 100-140 */ 2, 2, 2, 2, 1, 0, 0, 0, 2, 2, 2, 2, 1, 0, 0, 0, 394 /* 140-180 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 395 /* 180-1c0 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 396 /* 1c0-200 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 397 }; 398 399 static uint32_t m5206_mbar_readw(void *opaque, hwaddr offset); 400 static uint32_t m5206_mbar_readl(void *opaque, hwaddr offset); 401 402 static uint32_t m5206_mbar_readb(void *opaque, hwaddr offset) 403 { 404 m5206_mbar_state *s = (m5206_mbar_state *)opaque; 405 offset &= 0x3ff; 406 if (offset >= 0x200) { 407 qemu_log_mask(LOG_GUEST_ERROR, "Bad MBAR read offset 0x%" HWADDR_PRIX, 408 offset); 409 return 0; 410 } 411 if (m5206_mbar_width[offset >> 2] > 1) { 412 uint16_t val; 413 val = m5206_mbar_readw(opaque, offset & ~1); 414 if ((offset & 1) == 0) { 415 val >>= 8; 416 } 417 return val & 0xff; 418 } 419 return m5206_mbar_read(s, offset, 1); 420 } 421 422 static uint32_t m5206_mbar_readw(void *opaque, hwaddr offset) 423 { 424 m5206_mbar_state *s = (m5206_mbar_state *)opaque; 425 int width; 426 offset &= 0x3ff; 427 if (offset >= 0x200) { 428 qemu_log_mask(LOG_GUEST_ERROR, "Bad MBAR read offset 0x%" HWADDR_PRIX, 429 offset); 430 return 0; 431 } 432 width = m5206_mbar_width[offset >> 2]; 433 if (width > 2) { 434 uint32_t val; 435 val = m5206_mbar_readl(opaque, offset & ~3); 436 if ((offset & 3) == 0) 437 val >>= 16; 438 return val & 0xffff; 439 } else if (width < 2) { 440 uint16_t val; 441 val = m5206_mbar_readb(opaque, offset) << 8; 442 val |= m5206_mbar_readb(opaque, offset + 1); 443 return val; 444 } 445 return m5206_mbar_read(s, offset, 2); 446 } 447 448 static uint32_t m5206_mbar_readl(void *opaque, hwaddr offset) 449 { 450 m5206_mbar_state *s = (m5206_mbar_state *)opaque; 451 int width; 452 offset &= 0x3ff; 453 if (offset >= 0x200) { 454 qemu_log_mask(LOG_GUEST_ERROR, "Bad MBAR read offset 0x%" HWADDR_PRIX, 455 offset); 456 return 0; 457 } 458 width = m5206_mbar_width[offset >> 2]; 459 if (width < 4) { 460 uint32_t val; 461 val = m5206_mbar_readw(opaque, offset) << 16; 462 val |= m5206_mbar_readw(opaque, offset + 2); 463 return val; 464 } 465 return m5206_mbar_read(s, offset, 4); 466 } 467 468 static void m5206_mbar_writew(void *opaque, hwaddr offset, 469 uint32_t value); 470 static void m5206_mbar_writel(void *opaque, hwaddr offset, 471 uint32_t value); 472 473 static void m5206_mbar_writeb(void *opaque, hwaddr offset, 474 uint32_t value) 475 { 476 m5206_mbar_state *s = (m5206_mbar_state *)opaque; 477 int width; 478 offset &= 0x3ff; 479 if (offset >= 0x200) { 480 qemu_log_mask(LOG_GUEST_ERROR, "Bad MBAR write offset 0x%" HWADDR_PRIX, 481 offset); 482 return; 483 } 484 width = m5206_mbar_width[offset >> 2]; 485 if (width > 1) { 486 uint32_t tmp; 487 tmp = m5206_mbar_readw(opaque, offset & ~1); 488 if (offset & 1) { 489 tmp = (tmp & 0xff00) | value; 490 } else { 491 tmp = (tmp & 0x00ff) | (value << 8); 492 } 493 m5206_mbar_writew(opaque, offset & ~1, tmp); 494 return; 495 } 496 m5206_mbar_write(s, offset, value, 1); 497 } 498 499 static void m5206_mbar_writew(void *opaque, hwaddr offset, 500 uint32_t value) 501 { 502 m5206_mbar_state *s = (m5206_mbar_state *)opaque; 503 int width; 504 offset &= 0x3ff; 505 if (offset >= 0x200) { 506 qemu_log_mask(LOG_GUEST_ERROR, "Bad MBAR write offset 0x%" HWADDR_PRIX, 507 offset); 508 return; 509 } 510 width = m5206_mbar_width[offset >> 2]; 511 if (width > 2) { 512 uint32_t tmp; 513 tmp = m5206_mbar_readl(opaque, offset & ~3); 514 if (offset & 3) { 515 tmp = (tmp & 0xffff0000) | value; 516 } else { 517 tmp = (tmp & 0x0000ffff) | (value << 16); 518 } 519 m5206_mbar_writel(opaque, offset & ~3, tmp); 520 return; 521 } else if (width < 2) { 522 m5206_mbar_writeb(opaque, offset, value >> 8); 523 m5206_mbar_writeb(opaque, offset + 1, value & 0xff); 524 return; 525 } 526 m5206_mbar_write(s, offset, value, 2); 527 } 528 529 static void m5206_mbar_writel(void *opaque, hwaddr offset, 530 uint32_t value) 531 { 532 m5206_mbar_state *s = (m5206_mbar_state *)opaque; 533 int width; 534 offset &= 0x3ff; 535 if (offset >= 0x200) { 536 qemu_log_mask(LOG_GUEST_ERROR, "Bad MBAR write offset 0x%" HWADDR_PRIX, 537 offset); 538 return; 539 } 540 width = m5206_mbar_width[offset >> 2]; 541 if (width < 4) { 542 m5206_mbar_writew(opaque, offset, value >> 16); 543 m5206_mbar_writew(opaque, offset + 2, value & 0xffff); 544 return; 545 } 546 m5206_mbar_write(s, offset, value, 4); 547 } 548 549 static uint64_t m5206_mbar_readfn(void *opaque, hwaddr addr, unsigned size) 550 { 551 switch (size) { 552 case 1: 553 return m5206_mbar_readb(opaque, addr); 554 case 2: 555 return m5206_mbar_readw(opaque, addr); 556 case 4: 557 return m5206_mbar_readl(opaque, addr); 558 default: 559 g_assert_not_reached(); 560 } 561 } 562 563 static void m5206_mbar_writefn(void *opaque, hwaddr addr, 564 uint64_t value, unsigned size) 565 { 566 switch (size) { 567 case 1: 568 m5206_mbar_writeb(opaque, addr, value); 569 break; 570 case 2: 571 m5206_mbar_writew(opaque, addr, value); 572 break; 573 case 4: 574 m5206_mbar_writel(opaque, addr, value); 575 break; 576 default: 577 g_assert_not_reached(); 578 } 579 } 580 581 static const MemoryRegionOps m5206_mbar_ops = { 582 .read = m5206_mbar_readfn, 583 .write = m5206_mbar_writefn, 584 .valid.min_access_size = 1, 585 .valid.max_access_size = 4, 586 .endianness = DEVICE_NATIVE_ENDIAN, 587 }; 588 589 static void mcf5206_mbar_realize(DeviceState *dev, Error **errp) 590 { 591 m5206_mbar_state *s = MCF5206_MBAR(dev); 592 593 memory_region_init_io(&s->iomem, NULL, &m5206_mbar_ops, s, 594 "mbar", 0x00001000); 595 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); 596 597 s->pic = qemu_allocate_irqs(m5206_mbar_set_irq, s, 14); 598 s->timer[0] = m5206_timer_init(s->pic[9]); 599 s->timer[1] = m5206_timer_init(s->pic[10]); 600 s->uart[0] = mcf_uart_init(s->pic[12], serial_hd(0)); 601 s->uart[1] = mcf_uart_init(s->pic[13], serial_hd(1)); 602 s->cpu = M68K_CPU(qemu_get_cpu(0)); 603 } 604 605 static void mcf5206_mbar_class_init(ObjectClass *oc, void *data) 606 { 607 DeviceClass *dc = DEVICE_CLASS(oc); 608 609 set_bit(DEVICE_CATEGORY_MISC, dc->categories); 610 dc->desc = "MCF5206 system integration module"; 611 dc->realize = mcf5206_mbar_realize; 612 dc->reset = m5206_mbar_reset; 613 } 614 615 static const TypeInfo mcf5206_mbar_info = { 616 .name = TYPE_MCF5206_MBAR, 617 .parent = TYPE_SYS_BUS_DEVICE, 618 .instance_size = sizeof(m5206_mbar_state), 619 .class_init = mcf5206_mbar_class_init, 620 }; 621 622 static void mcf5206_mbar_register_types(void) 623 { 624 type_register_static(&mcf5206_mbar_info); 625 } 626 627 type_init(mcf5206_mbar_register_types) 628