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