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