1 /* 2 * 8260 specific stuff: 3 * Interrupt handling 4 */ 5 #include "u.h" 6 #include "../port/lib.h" 7 #include "mem.h" 8 #include "dat.h" 9 #include "io.h" 10 #include "fns.h" 11 #include "m8260.h" 12 13 enum { 14 Pin4 = BIT(4), 15 }; 16 17 static union { 18 struct { 19 ulong hi; 20 ulong lo; 21 }; 22 uvlong val; 23 } ticks; 24 25 struct { 26 ulong hi; 27 ulong lo; 28 } vec2mask[64] = { 29 [0] = {0, 0 }, /* Error, No interrupt */ 30 [1] = {0, BIT(16) }, /* I2C */ 31 [2] = {0, BIT(17) }, /* SPI */ 32 [3] = {0, BIT(18) }, /* Risc Timers */ 33 [4] = {0, BIT(19) }, /* SMC1 */ 34 [5] = {0, BIT(20) }, /* SMC2 */ 35 [6] = {0, BIT(21) }, /* IDMA1 */ 36 [7] = {0, BIT(22) }, /* IDMA2 */ 37 [8] = {0, BIT(23) }, /* IDMA3 */ 38 [9] = {0, BIT(24) }, /* IDMA4 */ 39 [10] = {0, BIT(25) }, /* SDMA */ 40 [11] = {0, 0 }, /* Reserved */ 41 [12] = {0, BIT(27) }, /* Timer1 */ 42 [13] = {0, BIT(28) }, /* Timer2 */ 43 [14] = {0, BIT(29) }, /* Timer3 */ 44 [15] = {0, BIT(30) }, /* Timer4 */ 45 46 [16] = {BIT(29), 0 }, /* TMCNT */ 47 [17] = {BIT(30), 0 }, /* PIT */ 48 [18] = {0, 0 }, /* Reserved */ 49 [19] = {BIT(17), 0 }, /* IRQ1 */ 50 [20] = {BIT(18), 0 }, /* IRQ2 */ 51 [21] = {BIT(19), 0 }, /* IRQ3 */ 52 [22] = {BIT(20), 0 }, /* IRQ4 */ 53 [23] = {BIT(21), 0 }, /* IRQ5 */ 54 [24] = {BIT(22), 0 }, /* IRQ6 */ 55 [25] = {BIT(23), 0 }, /* IRQ7 */ 56 [26] = {0, 0 }, /* Reserved */ 57 [27] = {0, 0 }, /* Reserved */ 58 [28] = {0, 0 }, /* Reserved */ 59 [29] = {0, 0 }, /* Reserved */ 60 [30] = {0, 0 }, /* Reserved */ 61 [31] = {0, 0 }, /* Reserved */ 62 63 [32] = {0, BIT(0) }, /* FCC1 */ 64 [33] = {0, BIT(1) }, /* FCC2 */ 65 [34] = {0, BIT(2) }, /* FCC3 */ 66 [35] = {0, 0 }, /* Reserved */ 67 [36] = {0, BIT(4) }, /* MCC1 */ 68 [37] = {0, BIT(5) }, /* MCC2 */ 69 [38] = {0, 0 }, /* Reserved */ 70 [39] = {0, 0 }, /* Reserved */ 71 [40] = {0, BIT(8) }, /* SCC1 */ 72 [41] = {0, BIT(9) }, /* SCC2 */ 73 [42] = {0, BIT(10) }, /* SCC3 */ 74 [43] = {0, BIT(11) }, /* SCC4 */ 75 [44] = {0, 0 }, /* Reserved */ 76 [45] = {0, 0 }, /* Reserved */ 77 [46] = {0, 0 }, /* Reserved */ 78 [47] = {0, 0 }, /* Reserved */ 79 80 [48] = {BIT(15), 0 }, /* PC15 */ 81 [49] = {BIT(14), 0 }, /* PC14 */ 82 [50] = {BIT(13), 0 }, /* PC13 */ 83 [51] = {BIT(12), 0 }, /* PC12 */ 84 [52] = {BIT(11), 0 }, /* PC11 */ 85 [53] = {BIT(10), 0 }, /* PC10 */ 86 [54] = {BIT(9), 0 }, /* PC9 */ 87 [55] = {BIT(8), 0 }, /* PC8 */ 88 [56] = {BIT(7), 0 }, /* PC7 */ 89 [57] = {BIT(6), 0 }, /* PC6 */ 90 [58] = {BIT(5), 0 }, /* PC5 */ 91 [59] = {BIT(4), 0 }, /* PC4 */ 92 [60] = {BIT(3), 0 }, /* PC3 */ 93 [61] = {BIT(2), 0 }, /* PC2 */ 94 [62] = {BIT(1), 0 }, /* PC1 */ 95 [63] = {BIT(0), 0 }, /* PC0 */ 96 }; 97 98 /* Blast memory layout: 99 * CS0: FE000000 -> FFFFFFFF (Flash) 100 * CS1: FC000000 -> FCFFFFFF (DSP hpi) 101 * CS2: 00000000 -> 03FFFFFF (60x sdram) 102 * CS3: 04000000 -> 04FFFFFF (FPGA) 103 * CS4: 05000000 -> 06FFFFFF (local bus sdram) 104 * CS5: 07000000 -> 0700FFFF (eeprom - not populated) 105 * CS6: E0000000 -> E0FFFFFF (FPGA - 64bits) 106 * 107 * Main Board memory layout: 108 * CS0: FE000000 -> FEFFFFFF (16 M FLASH) 109 * CS1: FC000000 -> FCFFFFFF (16 M DSP1) 110 * CS2: 00000000 -> 03FFFFFF (64 M SDRAM) 111 * CS3: 04000000 -> 04FFFFFF (16M DSP2) 112 * CS4: 05000000 -> 06FFFFFF (32 M Local SDRAM) 113 * CS5: 07000000 -> 0700FFFF (eeprom - not populated) 114 * CS6: unused 115 * CS7: E0000000 -> E0FFFFFF (16 M FPGA) 116 */ 117 118 IMM* iomem = (IMM*)IOMEM; 119 uchar etheraddr[6] = { 0x90, 0x85, 0x82, 0x32, 0x83, 0x00}; 120 121 static Lock cpmlock; 122 123 void 124 machinit(void) 125 { 126 ulong scmr; 127 int pllmf; 128 extern char* plan9inistr; 129 130 memset(m, 0, sizeof(*m)); 131 m->cputype = getpvr()>>16; /* pvr = 0x00810101 for the 8260 */ 132 m->imap = (Imap*)INTMEM; 133 134 m->loopconst = 1096; 135 136 /* Make sure Ethernet is disabled (boot code may have buffers allocated anywhere in memory) */ 137 iomem->fcc[0].gfmr &= ~(BIT(27)|BIT(26)); 138 iomem->fcc[1].gfmr &= ~(BIT(27)|BIT(26)); 139 iomem->fcc[2].gfmr &= ~(BIT(27)|BIT(26)); 140 141 /* Flashed CS configuration is wrong for DSP2. It's set to 64 bits, should be 16 */ 142 iomem->bank[3].br = 0x04001001; /* Set 16-bit port */ 143 144 /* 145 * FPGA is capable of doing 64-bit transfers. To use these, set br to 0xe0000001. 146 * Currently we use 32-bit transfers, because the 8260 does not easily do 64-bit operations. 147 */ 148 iomem->bank[6].br = 0xe0001801; 149 iomem->bank[6].or = 0xff000830; /* Was 0xff000816 */ 150 151 /* 152 * All systems with rev. A.1 (0K26N) silicon had serious problems when doing 153 * DMA transfers with data cache enabled (usually this shows when using 154 * one of the FCC's with some traffic on the ethernet). Allocating FCC buffer 155 * descriptors in main memory instead of DP ram solves this problem. 156 */ 157 158 /* Guess at clocks based upon the PLL configuration from the 159 * power-on reset. 160 */ 161 scmr = iomem->scmr; 162 163 /* The EST8260 is typically run using either 33 or 66 MHz 164 * external clock. The configuration byte in the Flash will 165 * tell us which is configured. The blast appears to be slightly 166 * overclocked at 72 MHz (if set to 66 MHz, the uart runs too fast) 167 */ 168 169 m->clkin = CLKIN; 170 171 pllmf = scmr & 0xfff; 172 173 /* This is arithmetic from the 8260 manual, section 9.4.1. */ 174 175 /* Collect the bits from the scmr. 176 */ 177 m->vco_out = m->clkin * (pllmf + 1); 178 if (scmr & BIT(19)) /* plldf (division factor is 1 or 2) */ 179 m->vco_out >>= 1; 180 181 m->cpmhz = m->vco_out >> 1; /* cpm hz is half of vco_out */ 182 m->brghz = m->vco_out >> (2 * ((iomem->sccr & 0x3) + 1)); 183 m->bushz = m->vco_out / (((scmr & 0x00f00000) >> 20) + 1); 184 185 /* Serial init sets BRG clock....I don't know how to compute 186 * core clock from core configuration, but I think I know the 187 * mapping.... 188 */ 189 switch(scmr >> (31-7)){ 190 case 0x0a: 191 m->cpuhz = m->clkin * 2; 192 break; 193 case 0x0b: 194 m->cpuhz = (m->clkin >> 1) * 5; 195 break; 196 default: 197 case 0x0d: 198 m->cpuhz = m->clkin * 3; 199 break; 200 case 0x14: 201 m->cpuhz = (m->clkin >> 1) * 7; 202 break; 203 case 0x1c: 204 m->cpuhz = m->clkin * 4; 205 break; 206 } 207 208 m->cyclefreq = m->bushz / 4; 209 210 /* Expect: 211 intfreq 133 m->cpuhz 212 busfreq 33 m->bushz 213 cpmfreq 99 m->cpmhz 214 brgfreq 49.5 m->brghz 215 vco 198 216 */ 217 218 active.machs = 1; 219 active.exiting = 0; 220 221 putmsr(getmsr() | MSR_ME); 222 223 /* 224 * turn on data cache before instruction cache; 225 * for some reason which I don't understand, 226 * you can't turn on both caches at once 227 */ 228 icacheenb(); 229 dcacheenb(); 230 231 kfpinit(); 232 233 /* Plan9.ini location in flash is FLASHMEM+PLAN9INI 234 * if PLAN9INI == ~0, it's not stored in flash or there is no flash 235 * if *cp == 0xff, flash memory is not initialized 236 */ 237 if (PLAN9INI == ~0 || 238 (uchar)*(plan9inistr = (char*)(FLASHMEM+PLAN9INI)) == 0xff){ 239 /* No plan9.ini in flash */ 240 plan9inistr = 241 "console=0\n" 242 "ether0=type=fcc port=0 ea=00601d051dd8\n" 243 "flash0=mem=0xfe000000\n" 244 "fs=135.104.9.42\n" 245 "auth=135.104.9.7\n" 246 "authdom=cs.bell-labs.com\n" 247 "sys=blast\n" 248 "ntp=135.104.9.52\n"; 249 } 250 } 251 252 void 253 fpgareset(void) 254 { 255 print("fpga reset\n"); 256 257 ioplock(); 258 259 iomem->port[1].pdat &= ~Pin4; /* force reset signal to 0 */ 260 delay(100); 261 iomem->port[1].pdat |= Pin4; /* force reset signal back to one */ 262 263 iopunlock(); 264 } 265 266 void 267 hwintrinit(void) 268 { 269 iomem->sicr = 2 << 8; 270 /* Write ones into most bits of the interrupt pending registers to clear interrupts */ 271 iomem->sipnr_h = ~7; 272 iomem->sipnr_h = ~1; 273 /* Clear the interrupt masks, thereby disabling all interrupts */ 274 iomem->simr_h = 0; 275 iomem->simr_l = 0; 276 277 iomem->sypcr &= ~2; /* cause a machine check interrupt on memory timeout */ 278 279 /* Initialize fpga reset pin */ 280 iomem->port[1].pdir |= Pin4; /* 1 is an output */ 281 iomem->port[1].ppar &= ~Pin4; 282 iomem->port[1].pdat |= Pin4; /* force reset signal back to one */ 283 } 284 285 int 286 vectorenable(Vctl *v) 287 { 288 ulong hi, lo; 289 290 if (v->irq & ~0x3f){ 291 print("m8260enable: interrupt vector %d out of range\n", v->irq); 292 return -1; 293 } 294 hi = vec2mask[v->irq].hi; 295 lo = vec2mask[v->irq].lo; 296 if (hi == 0 && lo == 0){ 297 print("m8260enable: nonexistent vector %d\n", v->irq); 298 return -1; 299 } 300 ioplock(); 301 /* Clear the interrupt before enabling */ 302 iomem->sipnr_h |= hi; 303 iomem->sipnr_l |= lo; 304 /* Enable */ 305 iomem->simr_h |= hi; 306 iomem->simr_l |= lo; 307 iopunlock(); 308 return v->irq; 309 } 310 311 void 312 vectordisable(Vctl *v) 313 { 314 ulong hi, lo; 315 316 if (v->irq & ~0x3f){ 317 print("m8260disable: interrupt vector %d out of range\n", v->irq); 318 return; 319 } 320 hi = vec2mask[v->irq].hi; 321 lo = vec2mask[v->irq].lo; 322 if (hi == 0 && lo == 0){ 323 print("m8260disable: nonexistent vector %d\n", v->irq); 324 return; 325 } 326 ioplock(); 327 iomem->simr_h &= ~hi; 328 iomem->simr_l &= ~lo; 329 iopunlock(); 330 } 331 332 int 333 intvec(void) 334 { 335 return iomem->sivec >> 26; 336 } 337 338 void 339 intend(int vno) 340 { 341 /* Clear interrupt */ 342 ioplock(); 343 iomem->sipnr_h |= vec2mask[vno].hi; 344 iomem->sipnr_l |= vec2mask[vno].lo; 345 iopunlock(); 346 } 347 348 int 349 m8260eoi(int) 350 { 351 return 0; 352 } 353 354 int 355 m8260isr(int) 356 { 357 return 0; 358 } 359 360 void 361 flashprogpower(int) 362 { 363 } 364 365 enum { 366 TgcrCas = 0x80, 367 TgcrGm = 0x08, 368 TgcrStp = 0x2, /* There are two of these, timer-2 bits are bits << 4 */ 369 TgcrRst = 0x1, 370 371 TmrIclkCasc = 0x00<<1, 372 TmrIclkIntclock = 0x01<<1, 373 TmrIclkIntclock16 = 0x02<<1, 374 TmrIclkTin = 0x03<<1, 375 TmrCERising = 0x1 << 6, 376 TmrCEFalling = 0x2 << 6, 377 TmrCEAny = 0x3 << 6, 378 TmrFrr = SBIT(12), 379 TmrOri = SBIT(11), 380 381 TerRef = SBIT(14), 382 TerCap = SBIT(15), 383 }; 384 385 uvlong 386 fastticks(uvlong *hz) 387 { 388 ulong count; 389 static Lock fasttickslock; 390 391 if (hz) 392 *hz = m->clkin>>1; 393 ilock(&fasttickslock); 394 count = iomem->tcnl1; 395 if (count < ticks.lo) 396 ticks.hi += 1; 397 ticks.lo = count; 398 iunlock(&fasttickslock); 399 return ticks.val; 400 } 401 402 ulong multiplier; 403 404 ulong 405 µs(void) 406 { 407 uvlong x; 408 409 if(multiplier == 0){ 410 multiplier = (uvlong)(1000000LL << 16) / m->cyclefreq; 411 print("µs: multiplier %ld, cyclefreq %lld, shifter %d\n", multiplier, m->cyclefreq, 16); 412 } 413 cycles(&x); 414 return (x*multiplier) >> 16; 415 } 416 417 void 418 timerset(Tval next) 419 { 420 long offset; 421 uvlong now; 422 static int cnt; 423 424 now = fastticks(nil); 425 offset = next - now; 426 if (offset < 2500) 427 next = now + 2500; /* 10000 instructions */ 428 else if (offset > m->clkin / HZ){ 429 print("too far in the future: offset %llux, now %llux\n", next, now); 430 next = now + m->clkin / HZ; 431 } 432 iomem->trrl1 = next; 433 } 434 435 void 436 m8260timerintr(Ureg *u, void*) 437 { 438 iomem->ter2 |= TerRef | TerCap; /* Clear interrupt */ 439 timerintr(u, 0); 440 } 441 442 void 443 timerinit(void) 444 { 445 446 iomem->tgcr1 = TgcrCas | TgcrGm; /* cascade timers 1 & 2, normal gate mode */ 447 iomem->tcnl1 = 0; 448 iomem->trrl1 = m->clkin / HZ; /* first capture in 1/HZ seconds */ 449 iomem->tmr1 = TmrIclkCasc; 450 iomem->tmr2 = TmrIclkIntclock | TmrOri; 451 intrenable(13, m8260timerintr, nil, "timer"); /* Timer 2 interrupt is on 13 */ 452 iomem->tgcr1 |= TgcrRst << 4; 453 } 454 455 static void 456 addseg(char *name, ulong start, ulong length) 457 { 458 Physseg segbuf; 459 460 memset(&segbuf, 0, sizeof(segbuf)); 461 segbuf.attr = SG_PHYSICAL; 462 kstrdup(&segbuf.name, name); 463 segbuf.pa = start; 464 segbuf.size = length; 465 if (addphysseg(&segbuf) == -1) { 466 print("addphysseg: %s\n", name); 467 return; 468 } 469 } 470 471 void 472 sharedseginit(void) 473 { 474 int i, j; 475 ulong base, size; 476 char name[16], *a, *b, *s; 477 static char *segnames[] = { 478 "fpga", 479 "dsp", 480 }; 481 482 for (j = 0; j < nelem(segnames); j++){ 483 for (i = 0; i < 8; i++){ 484 snprint(name, sizeof name, "%s%d", segnames[j], i); 485 if ((a = getconf(name)) == nil) 486 continue; 487 if ((b = strstr(a, "mem=")) == nil){ 488 print("blastseginit: %s: no base\n", name); 489 continue; 490 } 491 b += 4; 492 base = strtoul(b, nil, 0); 493 if (base == 0){ 494 print("blastseginit: %s: bad base: %s\n", name, b); 495 continue; 496 } 497 if ((s = strstr(a, "size=")) == nil){ 498 print("blastseginit: %s: no size\n", name); 499 continue; 500 } 501 s += 5; 502 size = strtoul(s, nil, 0); 503 if (size == 0){ 504 print("blastseginit: %s: bad size: %s\n", name, s); 505 continue; 506 } 507 addseg(name, base, size); 508 } 509 } 510 } 511 512 void 513 cpmop(int op, int dev, int mcn) 514 { 515 ioplock(); 516 eieio(); 517 while(iomem->cpcr & 0x10000) 518 eieio(); 519 iomem->cpcr = dev<<(31-10) | mcn<<(31-25) | op | 0x10000; 520 eieio(); 521 while(iomem->cpcr & 0x10000) 522 eieio(); 523 iopunlock(); 524 } 525 526 /* 527 * connect SCCx clocks in NSMI mode (x=1 for USB) 528 */ 529 void 530 sccnmsi(int x, int rcs, int tcs) 531 { 532 ulong v; 533 int sh; 534 535 sh = (x-1)*8; /* each SCCx field in sicr is 8 bits */ 536 v = (((rcs&7)<<3) | (tcs&7)) << sh; 537 iomem->sicr = (iomem->sicr & ~(0xFF<<sh)) | v; 538 } 539 540 /* 541 * lock the shared IO memory and return a reference to it 542 */ 543 void 544 ioplock(void) 545 { 546 ilock(&cpmlock); 547 } 548 549 /* 550 * release the lock on the shared IO memory 551 */ 552 void 553 iopunlock(void) 554 { 555 eieio(); 556 iunlock(&cpmlock); 557 } 558 559 BD* 560 bdalloc(int n) 561 { 562 static BD *palloc = ((Imap*)INTMEM)->bd; 563 BD *p; 564 565 p = palloc; 566 if (palloc > ((Imap*)INTMEM)->bd + nelem(((Imap*)INTMEM)->bd)){ 567 print("bdalloc: out of BDs\n"); 568 return nil; 569 } 570 palloc += n; 571 return p; 572 } 573 574 /* 575 * Initialise receive and transmit buffer rings. Only used for FCC 576 * Ethernet now. 577 * 578 * Ioringinit will allocate the buffer descriptors in normal memory 579 * and NOT in Dual-Ported Ram, as prescribed by the MPC8260 580 * PowerQUICC II manual (Section 28.6). When they are allocated 581 * in DPram and the Dcache is enabled, the processor will hang. 582 * This has been observed for the FCCs, it may or may not be true 583 * for SCCs or DMA. 584 * The SMC Uart buffer descriptors are not allocated here; (1) they 585 * can ONLY be in DPram and (2) they are not configured as a ring. 586 */ 587 int 588 ioringinit(Ring* r, int nrdre, int ntdre, int bufsize) 589 { 590 int i, x; 591 static uchar *dpmallocaddr; 592 static uchar *dpmallocend; 593 594 if (dpmallocaddr == nil){ 595 dpmallocaddr = m->imap->dpram1; 596 dpmallocend = dpmallocaddr + sizeof(m->imap->dpram1); 597 } 598 /* the ring entries must be aligned on sizeof(BD) boundaries */ 599 r->nrdre = nrdre; 600 if(r->rdr == nil) 601 r->rdr = xspanalloc(nrdre*sizeof(BD), 0, 8); 602 if(r->rdr == nil) 603 return -1; 604 if(r->rrb == nil && bufsize){ 605 r->rrb = xspanalloc(nrdre*bufsize, 0, CACHELINESZ); 606 if(r->rrb == nil) 607 return -1; 608 } 609 x = bufsize ? PADDR(r->rrb) : 0; 610 for(i = 0; i < nrdre; i++){ 611 r->rdr[i].length = 0; 612 r->rdr[i].addr = x; 613 r->rdr[i].status = BDEmpty|BDInt; 614 x += bufsize; 615 } 616 r->rdr[i-1].status |= BDWrap; 617 r->rdrx = 0; 618 619 r->ntdre = ntdre; 620 if(r->tdr == nil) 621 r->tdr = xspanalloc(ntdre*sizeof(BD), 0, 8); 622 if(r->txb == nil) 623 r->txb = xspanalloc(ntdre*sizeof(Block*), 0, CACHELINESZ); 624 if(r->tdr == nil || r->txb == nil) 625 return -1; 626 for(i = 0; i < ntdre; i++){ 627 r->txb[i] = nil; 628 r->tdr[i].addr = 0; 629 r->tdr[i].length = 0; 630 r->tdr[i].status = 0; 631 } 632 r->tdr[i-1].status |= BDWrap; 633 r->tdrh = 0; 634 r->tdri = 0; 635 r->ntq = 0; 636 return 0; 637 } 638 639 void 640 trapinit(void) 641 { 642 int i; 643 644 /* 645 * set all exceptions to trap 646 */ 647 for(i = 0x0; i < 0x2000; i += 0x100) 648 sethvec(i, trapvec); 649 650 setmvec(0x1000, imiss, tlbvec); 651 setmvec(0x1100, dmiss, tlbvec); 652 setmvec(0x1200, dmiss, tlbvec); 653 654 /* Useful for avoiding assembler miss handling: 655 sethvec(0x1000, tlbvec); 656 sethvec(0x1100, tlbvec); 657 sethvec(0x1200, tlbvec); 658 /* */ 659 dcflush(KADDR(0), 0x2000); 660 icflush(KADDR(0), 0x2000); 661 662 putmsr(getmsr() & ~MSR_IP); 663 } 664 665 void 666 reboot(void*, void*, ulong) 667 { 668 ulong *p; 669 int x; 670 671 p = (ulong*)0x90000000; 672 x = splhi(); 673 iomem->sypcr |= 0xc0; 674 print("iomem->sypcr = 0x%lux\n", iomem->sypcr); 675 *p = 0; 676 print("still alive\n"); 677 splx(x); 678 } 679