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 m5206_timer_state *timer[2]; 168 void *uart[2]; 169 uint8_t scr; 170 uint8_t icr[14]; 171 uint16_t imr; /* 1 == interrupt is masked. */ 172 uint16_t ipr; 173 uint8_t rsr; 174 uint8_t swivr; 175 uint8_t par; 176 /* Include the UART vector registers here. */ 177 uint8_t uivr[2]; 178 } m5206_mbar_state; 179 180 #define MCF5206_MBAR(obj) OBJECT_CHECK(m5206_mbar_state, (obj), TYPE_MCF5206_MBAR) 181 182 /* Interrupt controller. */ 183 184 static int m5206_find_pending_irq(m5206_mbar_state *s) 185 { 186 int level; 187 int vector; 188 uint16_t active; 189 int i; 190 191 level = 0; 192 vector = 0; 193 active = s->ipr & ~s->imr; 194 if (!active) 195 return 0; 196 197 for (i = 1; i < 14; i++) { 198 if (active & (1 << i)) { 199 if ((s->icr[i] & 0x1f) > level) { 200 level = s->icr[i] & 0x1f; 201 vector = i; 202 } 203 } 204 } 205 206 if (level < 4) 207 vector = 0; 208 209 return vector; 210 } 211 212 static void m5206_mbar_update(m5206_mbar_state *s) 213 { 214 int irq; 215 int vector; 216 int level; 217 218 irq = m5206_find_pending_irq(s); 219 if (irq) { 220 int tmp; 221 tmp = s->icr[irq]; 222 level = (tmp >> 2) & 7; 223 if (tmp & 0x80) { 224 /* Autovector. */ 225 vector = 24 + level; 226 } else { 227 switch (irq) { 228 case 8: /* SWT */ 229 vector = s->swivr; 230 break; 231 case 12: /* UART1 */ 232 vector = s->uivr[0]; 233 break; 234 case 13: /* UART2 */ 235 vector = s->uivr[1]; 236 break; 237 default: 238 /* Unknown vector. */ 239 qemu_log_mask(LOG_UNIMP, "%s: Unhandled vector for IRQ %d\n", 240 __func__, irq); 241 vector = 0xf; 242 break; 243 } 244 } 245 } else { 246 level = 0; 247 vector = 0; 248 } 249 m68k_set_irq_level(s->cpu, level, vector); 250 } 251 252 static void m5206_mbar_set_irq(void *opaque, int irq, int level) 253 { 254 m5206_mbar_state *s = (m5206_mbar_state *)opaque; 255 if (level) { 256 s->ipr |= 1 << irq; 257 } else { 258 s->ipr &= ~(1 << irq); 259 } 260 m5206_mbar_update(s); 261 } 262 263 /* System Integration Module. */ 264 265 static void m5206_mbar_reset(DeviceState *dev) 266 { 267 m5206_mbar_state *s = MCF5206_MBAR(dev); 268 269 s->scr = 0xc0; 270 s->icr[1] = 0x04; 271 s->icr[2] = 0x08; 272 s->icr[3] = 0x0c; 273 s->icr[4] = 0x10; 274 s->icr[5] = 0x14; 275 s->icr[6] = 0x18; 276 s->icr[7] = 0x1c; 277 s->icr[8] = 0x1c; 278 s->icr[9] = 0x80; 279 s->icr[10] = 0x80; 280 s->icr[11] = 0x80; 281 s->icr[12] = 0x00; 282 s->icr[13] = 0x00; 283 s->imr = 0x3ffe; 284 s->rsr = 0x80; 285 s->swivr = 0x0f; 286 s->par = 0; 287 } 288 289 static uint64_t m5206_mbar_read(m5206_mbar_state *s, 290 uint16_t offset, unsigned size) 291 { 292 if (offset >= 0x100 && offset < 0x120) { 293 return m5206_timer_read(s->timer[0], offset - 0x100); 294 } else if (offset >= 0x120 && offset < 0x140) { 295 return m5206_timer_read(s->timer[1], offset - 0x120); 296 } else if (offset >= 0x140 && offset < 0x160) { 297 return mcf_uart_read(s->uart[0], offset - 0x140, size); 298 } else if (offset >= 0x180 && offset < 0x1a0) { 299 return mcf_uart_read(s->uart[1], offset - 0x180, size); 300 } 301 switch (offset) { 302 case 0x03: return s->scr; 303 case 0x14 ... 0x20: return s->icr[offset - 0x13]; 304 case 0x36: return s->imr; 305 case 0x3a: return s->ipr; 306 case 0x40: return s->rsr; 307 case 0x41: return 0; 308 case 0x42: return s->swivr; 309 case 0x50: 310 /* DRAM mask register. */ 311 /* FIXME: currently hardcoded to 128Mb. */ 312 { 313 uint32_t mask = ~0; 314 while (mask > ram_size) 315 mask >>= 1; 316 return mask & 0x0ffe0000; 317 } 318 case 0x5c: return 1; /* DRAM bank 1 empty. */ 319 case 0xcb: return s->par; 320 case 0x170: return s->uivr[0]; 321 case 0x1b0: return s->uivr[1]; 322 } 323 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad MBAR offset 0x%"PRIx16"\n", 324 __func__, offset); 325 return 0; 326 } 327 328 static void m5206_mbar_write(m5206_mbar_state *s, uint16_t offset, 329 uint64_t value, unsigned size) 330 { 331 if (offset >= 0x100 && offset < 0x120) { 332 m5206_timer_write(s->timer[0], offset - 0x100, value); 333 return; 334 } else if (offset >= 0x120 && offset < 0x140) { 335 m5206_timer_write(s->timer[1], offset - 0x120, value); 336 return; 337 } else if (offset >= 0x140 && offset < 0x160) { 338 mcf_uart_write(s->uart[0], offset - 0x140, value, size); 339 return; 340 } else if (offset >= 0x180 && offset < 0x1a0) { 341 mcf_uart_write(s->uart[1], offset - 0x180, value, size); 342 return; 343 } 344 switch (offset) { 345 case 0x03: 346 s->scr = value; 347 break; 348 case 0x14 ... 0x20: 349 s->icr[offset - 0x13] = value; 350 m5206_mbar_update(s); 351 break; 352 case 0x36: 353 s->imr = value; 354 m5206_mbar_update(s); 355 break; 356 case 0x40: 357 s->rsr &= ~value; 358 break; 359 case 0x41: 360 /* TODO: implement watchdog. */ 361 break; 362 case 0x42: 363 s->swivr = value; 364 break; 365 case 0xcb: 366 s->par = value; 367 break; 368 case 0x170: 369 s->uivr[0] = value; 370 break; 371 case 0x178: case 0x17c: case 0x1c8: case 0x1bc: 372 /* Not implemented: UART Output port bits. */ 373 break; 374 case 0x1b0: 375 s->uivr[1] = value; 376 break; 377 default: 378 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad MBAR offset 0x%"PRIx16"\n", 379 __func__, offset); 380 break; 381 } 382 } 383 384 /* Internal peripherals use a variety of register widths. 385 This lookup table allows a single routine to handle all of them. */ 386 static const uint8_t m5206_mbar_width[] = 387 { 388 /* 000-040 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 389 /* 040-080 */ 1, 2, 2, 2, 4, 1, 2, 4, 1, 2, 4, 2, 2, 4, 2, 2, 390 /* 080-0c0 */ 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 391 /* 0c0-100 */ 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 392 /* 100-140 */ 2, 2, 2, 2, 1, 0, 0, 0, 2, 2, 2, 2, 1, 0, 0, 0, 393 /* 140-180 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 394 /* 180-1c0 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 395 /* 1c0-200 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 396 }; 397 398 static uint32_t m5206_mbar_readw(void *opaque, hwaddr offset); 399 static uint32_t m5206_mbar_readl(void *opaque, hwaddr offset); 400 401 static uint32_t m5206_mbar_readb(void *opaque, hwaddr offset) 402 { 403 m5206_mbar_state *s = (m5206_mbar_state *)opaque; 404 offset &= 0x3ff; 405 if (offset >= 0x200) { 406 qemu_log_mask(LOG_GUEST_ERROR, "Bad MBAR read offset 0x%" HWADDR_PRIX, 407 offset); 408 return 0; 409 } 410 if (m5206_mbar_width[offset >> 2] > 1) { 411 uint16_t val; 412 val = m5206_mbar_readw(opaque, offset & ~1); 413 if ((offset & 1) == 0) { 414 val >>= 8; 415 } 416 return val & 0xff; 417 } 418 return m5206_mbar_read(s, offset, 1); 419 } 420 421 static uint32_t m5206_mbar_readw(void *opaque, hwaddr offset) 422 { 423 m5206_mbar_state *s = (m5206_mbar_state *)opaque; 424 int width; 425 offset &= 0x3ff; 426 if (offset >= 0x200) { 427 qemu_log_mask(LOG_GUEST_ERROR, "Bad MBAR read offset 0x%" HWADDR_PRIX, 428 offset); 429 return 0; 430 } 431 width = m5206_mbar_width[offset >> 2]; 432 if (width > 2) { 433 uint32_t val; 434 val = m5206_mbar_readl(opaque, offset & ~3); 435 if ((offset & 3) == 0) 436 val >>= 16; 437 return val & 0xffff; 438 } else if (width < 2) { 439 uint16_t val; 440 val = m5206_mbar_readb(opaque, offset) << 8; 441 val |= m5206_mbar_readb(opaque, offset + 1); 442 return val; 443 } 444 return m5206_mbar_read(s, offset, 2); 445 } 446 447 static uint32_t m5206_mbar_readl(void *opaque, hwaddr offset) 448 { 449 m5206_mbar_state *s = (m5206_mbar_state *)opaque; 450 int width; 451 offset &= 0x3ff; 452 if (offset >= 0x200) { 453 qemu_log_mask(LOG_GUEST_ERROR, "Bad MBAR read offset 0x%" HWADDR_PRIX, 454 offset); 455 return 0; 456 } 457 width = m5206_mbar_width[offset >> 2]; 458 if (width < 4) { 459 uint32_t val; 460 val = m5206_mbar_readw(opaque, offset) << 16; 461 val |= m5206_mbar_readw(opaque, offset + 2); 462 return val; 463 } 464 return m5206_mbar_read(s, offset, 4); 465 } 466 467 static void m5206_mbar_writew(void *opaque, hwaddr offset, 468 uint32_t value); 469 static void m5206_mbar_writel(void *opaque, hwaddr offset, 470 uint32_t value); 471 472 static void m5206_mbar_writeb(void *opaque, hwaddr offset, 473 uint32_t value) 474 { 475 m5206_mbar_state *s = (m5206_mbar_state *)opaque; 476 int width; 477 offset &= 0x3ff; 478 if (offset >= 0x200) { 479 qemu_log_mask(LOG_GUEST_ERROR, "Bad MBAR write offset 0x%" HWADDR_PRIX, 480 offset); 481 return; 482 } 483 width = m5206_mbar_width[offset >> 2]; 484 if (width > 1) { 485 uint32_t tmp; 486 tmp = m5206_mbar_readw(opaque, offset & ~1); 487 if (offset & 1) { 488 tmp = (tmp & 0xff00) | value; 489 } else { 490 tmp = (tmp & 0x00ff) | (value << 8); 491 } 492 m5206_mbar_writew(opaque, offset & ~1, tmp); 493 return; 494 } 495 m5206_mbar_write(s, offset, value, 1); 496 } 497 498 static void m5206_mbar_writew(void *opaque, hwaddr offset, 499 uint32_t value) 500 { 501 m5206_mbar_state *s = (m5206_mbar_state *)opaque; 502 int width; 503 offset &= 0x3ff; 504 if (offset >= 0x200) { 505 qemu_log_mask(LOG_GUEST_ERROR, "Bad MBAR write offset 0x%" HWADDR_PRIX, 506 offset); 507 return; 508 } 509 width = m5206_mbar_width[offset >> 2]; 510 if (width > 2) { 511 uint32_t tmp; 512 tmp = m5206_mbar_readl(opaque, offset & ~3); 513 if (offset & 3) { 514 tmp = (tmp & 0xffff0000) | value; 515 } else { 516 tmp = (tmp & 0x0000ffff) | (value << 16); 517 } 518 m5206_mbar_writel(opaque, offset & ~3, tmp); 519 return; 520 } else if (width < 2) { 521 m5206_mbar_writeb(opaque, offset, value >> 8); 522 m5206_mbar_writeb(opaque, offset + 1, value & 0xff); 523 return; 524 } 525 m5206_mbar_write(s, offset, value, 2); 526 } 527 528 static void m5206_mbar_writel(void *opaque, hwaddr offset, 529 uint32_t value) 530 { 531 m5206_mbar_state *s = (m5206_mbar_state *)opaque; 532 int width; 533 offset &= 0x3ff; 534 if (offset >= 0x200) { 535 qemu_log_mask(LOG_GUEST_ERROR, "Bad MBAR write offset 0x%" HWADDR_PRIX, 536 offset); 537 return; 538 } 539 width = m5206_mbar_width[offset >> 2]; 540 if (width < 4) { 541 m5206_mbar_writew(opaque, offset, value >> 16); 542 m5206_mbar_writew(opaque, offset + 2, value & 0xffff); 543 return; 544 } 545 m5206_mbar_write(s, offset, value, 4); 546 } 547 548 static uint64_t m5206_mbar_readfn(void *opaque, hwaddr addr, unsigned size) 549 { 550 switch (size) { 551 case 1: 552 return m5206_mbar_readb(opaque, addr); 553 case 2: 554 return m5206_mbar_readw(opaque, addr); 555 case 4: 556 return m5206_mbar_readl(opaque, addr); 557 default: 558 g_assert_not_reached(); 559 } 560 } 561 562 static void m5206_mbar_writefn(void *opaque, hwaddr addr, 563 uint64_t value, unsigned size) 564 { 565 switch (size) { 566 case 1: 567 m5206_mbar_writeb(opaque, addr, value); 568 break; 569 case 2: 570 m5206_mbar_writew(opaque, addr, value); 571 break; 572 case 4: 573 m5206_mbar_writel(opaque, addr, value); 574 break; 575 default: 576 g_assert_not_reached(); 577 } 578 } 579 580 static const MemoryRegionOps m5206_mbar_ops = { 581 .read = m5206_mbar_readfn, 582 .write = m5206_mbar_writefn, 583 .valid.min_access_size = 1, 584 .valid.max_access_size = 4, 585 .endianness = DEVICE_NATIVE_ENDIAN, 586 }; 587 588 static void mcf5206_mbar_realize(DeviceState *dev, Error **errp) 589 { 590 m5206_mbar_state *s = MCF5206_MBAR(dev); 591 qemu_irq *pic; 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 pic = qemu_allocate_irqs(m5206_mbar_set_irq, s, 14); 598 s->timer[0] = m5206_timer_init(pic[9]); 599 s->timer[1] = m5206_timer_init(pic[10]); 600 s->uart[0] = mcf_uart_init(pic[12], serial_hd(0)); 601 s->uart[1] = mcf_uart_init(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