6 #include "../port/lib.h"
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 */
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 */
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 */
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 */
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)
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)
115 * CS7: E0000000 -> E0FFFFFF (16 M FPGA)
118 IMM* iomem = (IMM*)IOMEM;
127 extern char* plan9inistr;
129 memset(m, 0, sizeof(*m));
130 m->cputype = getpvr()>>16; /* pvr = 0x00810101 for the 8260 */
131 m->imap = (Imap*)INTMEM;
135 /* Make sure Ethernet is disabled (boot code may have buffers allocated anywhere in memory) */
136 iomem->fcc[0].gfmr &= ~(BIT(27)|BIT(26));
137 iomem->fcc[1].gfmr &= ~(BIT(27)|BIT(26));
138 iomem->fcc[2].gfmr &= ~(BIT(27)|BIT(26));
140 /* Flashed CS configuration is wrong for DSP2. It's set to 64 bits, should be 16 */
141 iomem->bank[3].br = 0x04001001; /* Set 16-bit port */
144 * FPGA is capable of doing 64-bit transfers. To use these, set br to 0xe0000001.
145 * Currently we use 32-bit transfers, because the 8260 does not easily do 64-bit operations.
147 iomem->bank[6].br = 0xe0001801;
148 iomem->bank[6].or = 0xff000830; /* Was 0xff000816 */
151 * All systems with rev. A.1 (0K26N) silicon had serious problems when doing
152 * DMA transfers with data cache enabled (usually this shows when using
153 * one of the FCC's with some traffic on the ethernet). Allocating FCC buffer
154 * descriptors in main memory instead of DP ram solves this problem.
157 /* Guess at clocks based upon the PLL configuration from the
162 /* The EST8260 is typically run using either 33 or 66 MHz
163 * external clock. The configuration byte in the Flash will
164 * tell us which is configured. The blast appears to be slightly
165 * overclocked at 72 MHz (if set to 66 MHz, the uart runs too fast)
170 pllmf = scmr & 0xfff;
172 /* This is arithmetic from the 8260 manual, section 9.4.1. */
174 /* Collect the bits from the scmr.
176 m->vco_out = m->clkin * (pllmf + 1);
177 if (scmr & BIT(19)) /* plldf (division factor is 1 or 2) */
180 m->cpmhz = m->vco_out >> 1; /* cpm hz is half of vco_out */
181 m->brghz = m->vco_out >> (2 * ((iomem->sccr & 0x3) + 1));
182 m->bushz = m->vco_out / (((scmr & 0x00f00000) >> 20) + 1);
184 /* Serial init sets BRG clock....I don't know how to compute
185 * core clock from core configuration, but I think I know the
188 switch(scmr >> (31-7)){
190 m->cpuhz = m->clkin * 2;
193 m->cpuhz = (m->clkin >> 1) * 5;
197 m->cpuhz = m->clkin * 3;
200 m->cpuhz = (m->clkin >> 1) * 7;
203 m->cpuhz = m->clkin * 4;
207 m->cyclefreq = m->bushz / 4;
213 brgfreq 49.5 m->brghz
220 putmsr(getmsr() | MSR_ME);
223 * turn on data cache before instruction cache;
224 * for some reason which I don't understand,
225 * you can't turn on both caches at once
232 /* Plan9.ini location in flash is FLASHMEM+PLAN9INI
233 * if PLAN9INI == ~0, it's not stored in flash or there is no flash
234 * if *cp == 0xff, flash memory is not initialized
236 if (PLAN9INI == ~0 || *(plan9inistr = (char*)(FLASHMEM+PLAN9INI)) == 0xff){
237 /* No plan9.ini in flash */
240 "ether0=type=fcc port=0 ea=00601d051dd8\n"
241 "flash0=mem=0xfe000000\n"
244 "authdom=cs.bell-labs.com\n"
246 "ntp=135.104.9.52\n";
253 print("fpga reset\n");
257 iomem->port[1].pdat &= ~Pin4; /* force reset signal to 0 */
259 iomem->port[1].pdat |= Pin4; /* force reset signal back to one */
267 iomem->sicr = 2 << 8;
268 /* Write ones into most bits of the interrupt pending registers to clear interrupts */
271 /* Clear the interrupt masks, thereby disabling all interrupts */
275 iomem->sypcr &= ~2; /* cause a machine check interrupt on memory timeout */
277 /* Initialize fpga reset pin */
278 iomem->port[1].pdir |= Pin4; /* 1 is an output */
279 iomem->port[1].ppar &= ~Pin4;
280 iomem->port[1].pdat |= Pin4; /* force reset signal back to one */
284 vectorenable(Vctl *v)
289 print("m8260enable: interrupt vector %d out of range\n", v->irq);
292 hi = vec2mask[v->irq].hi;
293 lo = vec2mask[v->irq].lo;
294 if (hi == 0 && lo == 0){
295 print("m8260enable: nonexistent vector %d\n", v->irq);
299 /* Clear the interrupt before enabling */
300 iomem->sipnr_h |= hi;
301 iomem->sipnr_l |= lo;
310 vectordisable(Vctl *v)
315 print("m8260disable: interrupt vector %d out of range\n", v->irq);
318 hi = vec2mask[v->irq].hi;
319 lo = vec2mask[v->irq].lo;
320 if (hi == 0 && lo == 0){
321 print("m8260disable: nonexistent vector %d\n", v->irq);
325 iomem->simr_h &= ~hi;
326 iomem->simr_l &= ~lo;
333 return iomem->sivec >> 26;
339 /* Clear interrupt */
341 iomem->sipnr_h |= vec2mask[vno].hi;
342 iomem->sipnr_l |= vec2mask[vno].lo;
366 TgcrStp = 0x2, /* There are two of these, timer-2 bits are bits << 4 */
369 TmrIclkCasc = 0x00<<1,
370 TmrIclkIntclock = 0x01<<1,
371 TmrIclkIntclock16 = 0x02<<1,
372 TmrIclkTin = 0x03<<1,
373 TmrCERising = 0x1 << 6,
374 TmrCEFalling = 0x2 << 6,
384 fastticks(uvlong *hz)
387 static Lock fasttickslock;
391 ilock(&fasttickslock);
392 count = iomem->tcnl1;
393 if (count < ticks.lo)
396 iunlock(&fasttickslock);
401 timerset(uvlong next)
407 now = fastticks(nil);
410 next = now + 2500; /* 10000 instructions */
411 else if (offset > m->clkin / HZ){
412 print("too far in the future: offset %llux, now %llux\n", next, now);
413 next = now + m->clkin / HZ;
419 m8260timerintr(Ureg *u, void*)
421 iomem->ter2 |= TerRef | TerCap; /* Clear interrupt */
429 iomem->tgcr1 = TgcrCas | TgcrGm; /* cascade timers 1 & 2, normal gate mode */
431 iomem->trrl1 = m->clkin / HZ; /* first capture in 1/HZ seconds */
432 iomem->tmr1 = TmrIclkCasc;
433 iomem->tmr2 = TmrIclkIntclock | TmrOri;
434 intrenable(13, m8260timerintr, nil, "timer"); /* Timer 2 interrupt is on 13 */
435 iomem->tgcr1 |= TgcrRst << 4;
439 addseg(char *name, ulong start, ulong length)
443 memset(&segbuf, 0, sizeof(segbuf));
444 segbuf.attr = SG_PHYSICAL | SG_DEVICE | SG_NOEXEC;
445 kstrdup(&segbuf.name, name);
447 segbuf.size = length;
448 if (addphysseg(&segbuf) == nil) {
449 print("addphysseg: %s\n", name);
459 char name[16], *a, *b, *s;
460 static char *segnames[] = {
465 for (j = 0; j < nelem(segnames); j++){
466 for (i = 0; i < 8; i++){
467 snprint(name, sizeof name, "%s%d", segnames[j], i);
468 if ((a = getconf(name)) == nil)
470 if ((b = strstr(a, "mem=")) == nil){
471 print("blastseginit: %s: no base\n", name);
475 base = strtoul(b, nil, 0);
477 print("blastseginit: %s: bad base: %s\n", name, b);
480 if ((s = strstr(a, "size=")) == nil){
481 print("blastseginit: %s: no size\n", name);
485 size = strtoul(s, nil, 0);
487 print("blastseginit: %s: bad size: %s\n", name, s);
490 addseg(name, base, size);
496 cpmop(int op, int dev, int mcn)
500 while(iomem->cpcr & 0x10000)
502 iomem->cpcr = dev<<(31-10) | mcn<<(31-25) | op | 0x10000;
504 while(iomem->cpcr & 0x10000)
510 * connect SCCx clocks in NSMI mode (x=1 for USB)
513 sccnmsi(int x, int rcs, int tcs)
518 sh = (x-1)*8; /* each SCCx field in sicr is 8 bits */
519 v = (((rcs&7)<<3) | (tcs&7)) << sh;
520 iomem->sicr = (iomem->sicr & ~(0xFF<<sh)) | v;
524 * lock the shared IO memory and return a reference to it
533 * release the lock on the shared IO memory
545 static BD *palloc = ((Imap*)INTMEM)->bd;
549 if (palloc > ((Imap*)INTMEM)->bd + nelem(((Imap*)INTMEM)->bd)){
550 print("bdalloc: out of BDs\n");
558 * Initialise receive and transmit buffer rings. Only used for FCC
561 * Ioringinit will allocate the buffer descriptors in normal memory
562 * and NOT in Dual-Ported Ram, as prescribed by the MPC8260
563 * PowerQUICC II manual (Section 28.6). When they are allocated
564 * in DPram and the Dcache is enabled, the processor will hang.
565 * This has been observed for the FCCs, it may or may not be true
567 * The SMC Uart buffer descriptors are not allocated here; (1) they
568 * can ONLY be in DPram and (2) they are not configured as a ring.
571 ioringinit(Ring* r, int nrdre, int ntdre, int bufsize)
574 static uchar *dpmallocaddr;
575 static uchar *dpmallocend;
577 if (dpmallocaddr == nil){
578 dpmallocaddr = m->imap->dpram1;
579 dpmallocend = dpmallocaddr + sizeof(m->imap->dpram1);
581 /* the ring entries must be aligned on sizeof(BD) boundaries */
584 r->rdr = xspanalloc(nrdre*sizeof(BD), 0, 8);
587 if(r->rrb == nil && bufsize){
588 r->rrb = xspanalloc(nrdre*bufsize, 0, CACHELINESZ);
592 x = bufsize ? PADDR(r->rrb) : 0;
593 for(i = 0; i < nrdre; i++){
594 r->rdr[i].length = 0;
596 r->rdr[i].status = BDEmpty|BDInt;
599 r->rdr[i-1].status |= BDWrap;
604 r->tdr = xspanalloc(ntdre*sizeof(BD), 0, 8);
606 r->txb = xspanalloc(ntdre*sizeof(Block*), 0, CACHELINESZ);
607 if(r->tdr == nil || r->txb == nil)
609 for(i = 0; i < ntdre; i++){
612 r->tdr[i].length = 0;
613 r->tdr[i].status = 0;
615 r->tdr[i-1].status |= BDWrap;
628 * set all exceptions to trap
630 for(i = 0x0; i < 0x2000; i += 0x100)
633 setmvec(0x1000, imiss, tlbvec);
634 setmvec(0x1100, dmiss, tlbvec);
635 setmvec(0x1200, dmiss, tlbvec);
637 /* Useful for avoiding assembler miss handling:
638 sethvec(0x1000, tlbvec);
639 sethvec(0x1100, tlbvec);
640 sethvec(0x1200, tlbvec);
642 dcflush(KADDR(0), 0x2000);
643 icflush(KADDR(0), 0x2000);
645 putmsr(getmsr() & ~MSR_IP);
649 reboot(void*, void*, ulong)
654 p = (ulong*)0x90000000;
656 iomem->sypcr |= 0xc0;
657 print("iomem->sypcr = 0x%lux\n", iomem->sypcr);
659 print("still alive\n");