2 * nvidia tegra 2 architecture-specific stuff
6 #include "../port/lib.h"
10 #include "../port/error.h"
14 #include "../port/netif.h"
15 #include "../port/etherif.h"
16 #include "../port/flashif.h"
19 /* hardware limits imposed by register contents or layouts */
26 typedef struct Clkrst Clkrst;
27 typedef struct Diag Diag;
28 typedef struct Flow Flow;
29 typedef struct Scu Scu;
30 typedef struct Power Power;
42 uchar _pad0[0x24-0x1c];
43 ulong supcclkdiv; /* super cclk divider */
45 ulong supsclkdiv; /* super sclk divider */
47 uchar _pad4[0x4c-0x30];
50 uchar _pad1[0xe0-0x50];
51 ulong pllxbase; /* pllx controls CPU clock speed */
53 ulong pllebase; /* plle is dedicated to pcie */
56 uchar _pad2[0x340-0xf0];
66 Wdsel = 1<<4, /* tmr1 or tmr2? */
88 ulong ctl; /* mainly for rtc clock signals */
97 ulong dpdpadsovr; /* deep power down pads override */
105 ulong gatests; /* ro */
123 ulong autowaklvlmask;
128 ulong usbdebdel; /* usb de-bounce delay */
132 ulong scratch24[42-24+1];
133 ulong boundoutmirr[3];
135 ulong boundoutmirracc;
153 uchar _pad0[0x40-0x10];
157 uchar _pad1[0x50-0x48];
158 ulong accctl; /* initially 0 */
167 Specfill = 1<<3, /* only for PL310 */
188 Event = 1<<14, /* w1c */
189 Waitwfebitsshift = 4,
190 Waitwfebitsmask = MASK(2),
203 extern ulong testmem;
206 * number of cpus available. contrast with conf.nmach, which is number
213 .clkrst = 0x60006000, /* clock & reset signals */
215 .exceptvec = PHYSEVP, /* undocumented magic */
217 .l2cache= PHYSL2BAG, /* pl310 bag on the side */
220 /* 4 non-gic controllers */
221 // .intr = { 0x60004000, 0x60004100, 0x60004200, 0x60004300, },
223 /* private memory region */
225 /* we got this address from the `cortex-a series programmer's guide'. */
226 .intr = 0x50040100, /* per-cpu interface */
227 .glbtmr = 0x50040200,
228 .loctmr = 0x50040600,
229 .intrdist=0x50041000,
231 .uart = { 0x70006000, 0x70006040,
232 0x70006200, 0x70006300, 0x70006400, },
235 .tmr = { 0x60005000, 0x60005008, 0x60005050, 0x60005058, },
242 .nor = 0x70009000, /* also VIRTNOR */
244 .ehci = P2VAHB(0xc5000000), /* 1st of 3 */
245 .ide = P2VAHB(0xc3000000),
247 .gpio = { 0x6000d000, 0x6000d080, 0x6000d100, 0x6000d180,
248 0x6000d200, 0x6000d280, 0x6000d300, },
249 .spi = { 0x7000d400, 0x7000d600, 0x7000d800, 0x7000da00, },
251 .mmc = { P2VAHB(0xc8000000), P2VAHB(0xc8000200),
252 P2VAHB(0xc8000400), P2VAHB(0xc8000600), },
255 static volatile Diag diag;
259 dumpcpuclks(void) /* run CPU at full speed */
261 Clkrst *clk = (Clkrst *)soc.clkrst;
263 iprint("pllx base %#lux misc %#lux\n", clk->pllxbase, clk->pllxmisc);
264 iprint("plle base %#lux misc %#lux\n", clk->pllebase, clk->pllemisc);
265 iprint("super cclk divider %#lux\n", clk->supcclkdiv);
266 iprint("super sclk divider %#lux\n", clk->supsclkdiv);
272 return "ARM Cortex-A9";
280 /* convert AddrDevid register to a string in buf and return buf */
282 cputype2name(char *buf, int size)
286 r = cpidget(); /* main id register */
287 assert((r >> 24) == 'A');
288 seprint(buf, buf + size, "Cortex-A9 r%ldp%ld",
289 (r >> 20) & MASK(4), r & MASK(4));
298 /* apply cortex-a9 errata workarounds */
299 r = cpidget(); /* main id register */
300 assert((r >> 24) == 'A');
301 p = r & MASK(4); /* minor revision */
303 r &= MASK(4); /* major revision */
305 /* this is an undocumented `diagnostic register' that linux knows */
306 reg = cprdsc(0, CpDTLB, 0, 1);
307 if (r < 2 || r == 2 && p <= 2)
308 reg |= 1<<4; /* 742230 */
309 if (r == 2 && p <= 2)
310 reg |= 1<<6 | 1<<12 | 1<<22; /* 743622, 2×742231 */
312 reg |= 1<<11; /* 751472 */
313 cpwrsc(0, CpDTLB, 0, 1, reg);
323 m->cpuhz = 1000 * Mhz; /* trimslice speed */
324 p = getconf("*cpumhz");
327 if (hz >= 100*Mhz && hz <= 3600UL*Mhz)
330 m->delayloop = m->cpuhz/2000; /* initial estimate */
335 archether(unsigned ctlrno, Ether *ether)
339 ether->type = "rtl8169"; /* pci-e ether */
340 ether->ctlrno = ctlrno;
341 ether->irq = Pcieirq; /* non-msi pci-e intr */
352 Scu *scu = (Scu *)soc.scu;
354 print("cpu%d scu: accctl %#lux\n", m->machno, scu->accctl);
355 print("cpu%d scu: smp cpu bit map %#lo for %ld cpus; ", m->machno,
356 (scu->cfg >> 4) & MASK(4), (scu->cfg & MASK(2)) + 1);
357 print("cpus' power %#lux\n", scu->cpupwrsts);
363 Scu *scu = (Scu *)soc.scu;
365 if (scu->ctl & Scuenable)
367 scu->inval = MASK(16);
369 scu->ctl = Scuparity | Scuenable | Specfill;
380 if (navailcpus == 0) {
381 scu = (Scu *)soc.scu;
382 navailcpus = (scu->cfg & MASK(2)) + 1;
383 if (navailcpus > MAXMACH)
384 navailcpus = MAXMACH;
386 p = getconf("*ncpu");
389 if (n > 0 && n < navailcpus)
401 cputype2name(name, sizeof name);
402 delay(50); /* let uart catch up */
403 iprint("cpu%d: %lldMHz ARM %s %s-endian\n",
404 m->machno, m->cpuhz / Mhz, name,
405 getpsr() & PsrBigend? "big": "little");
411 Clkrst *clk = (Clkrst *)soc.clkrst;
413 /* enable all by clearing resets */
414 clk->rstdevl = clk->rstdevh = clk->rstdevu = 0;
416 clk->clkoutl = clk->clkouth = clk->clkoutu = ~0; /* enable all clocks */
419 clk->rstsrc = Wdcpurst | Wdcoprst | Wdsysrst | Wdena;
423 /* we could be shutting down ourself (if cpu == m->machno), so take care. */
427 Flow *flow = (Flow *)soc.flow;
428 Clkrst *clk = (Clkrst *)soc.clkrst;
431 iprint("stopcpu: may not stop cpu0\n");
437 active.stopped |= 1 << cpu;
441 /* shut down arm7 avp coproc so it can't cause mischief. */
442 /* could try watchdog without stopping avp. */
443 flow->haltcop = Stop;
445 flow->cop = 0; /* no Cpuenable */
449 assert(cpu < Maxflowcpus);
450 *(cpu == 0? &flow->haltcpu0: &flow->haltcpu1) = Stop;
452 *(cpu == 0? &flow->cpu0: &flow->cpu1) = 0; /* no Cpuenable */
457 assert(cpu < Maxcpus);
458 clk->cpuset = (Cpu0reset | Cpu0dbgreset | Cpu0dereset) << cpu;
466 synccpus(Ref *cntp, int n)
469 while (cntp->ref < n)
471 /* all cpus should now be here */
475 pass1(int pass, volatile Diag *dp)
481 for (i = 1000*1000; --i > 0; ) {
486 synccpus(&dp->sync, navailcpus);
487 /* all cpus are now here */
491 panic("cpu%d: diag: failed w count %ld", m->machno, dp->cnt.ref);
494 synccpus(&dp->sync, 2 * navailcpus);
495 /* all cpus are now here */
501 * try to confirm coherence of l1 caches.
502 * assume that all available cpus will be started.
516 * synchronise and print
521 iprint("l1: waiting for %d cpus... ", navailcpus);
524 synccpus(&dp->sync, navailcpus);
528 iprint("cache coherency pass");
531 synccpus(&dp->sync, 2 * navailcpus);
538 for (pass = 0; pass < 3; pass++)
542 * synchronise and check sanity
544 synccpus(&dp->sync, navailcpus);
546 if(dp->sync.ref < navailcpus || dp->sync.ref >= 2 * navailcpus)
547 panic("cpu%d: diag: failed w dp->sync %ld", m->machno,
550 panic("cpu%d: diag: failed w dp->cnt %ld", m->machno,
554 iprint(" cpu%d ok", m->machno);
557 synccpus(&dp->sync, 2 * navailcpus);
574 Clkrst *clk = (Clkrst *)soc.clkrst;
575 Flow *flow = (Flow *)soc.flow;
577 assert(cpu < Maxcpus);
579 clk->clkcpu &= ~(Cpu0stop << cpu);
582 clk->cpuclr = (Cpu0reset | Cpu0wdreset | Cpu0dbgreset | Cpu0dereset) <<
586 assert(cpu < Maxflowcpus);
587 *(cpu == 0? &flow->cpu0: &flow->cpu1) = 0;
589 *(cpu == 0? &flow->haltcpu0: &flow->haltcpu1) = 0; /* normal operat'n */
594 * this is all a bit magic. the soc.exceptvec register is effectively
595 * undocumented. we had to look at linux and experiment, alas. this is the
596 * sort of thing that should be standardised as part of the cortex mpcore spec.
597 * even intel document their equivalent procedure.
603 ulong oldvec, rstaddr;
604 ulong *evp = (ulong *)soc.exceptvec; /* magic */
607 if (getncpus() < 2 || cpu == m->machno ||
608 cpu >= MAXMACH || cpu >= navailcpus)
612 l1cache->wb(); /* start next cpu w same view of ram */
613 *evp = rstaddr = PADDR(_vrst); /* will start cpu executing at _vrst */
618 for (i = 2000; i > 0 && *evp == rstaddr; i--)
620 if (i <= 0 || *evp != cpu) {
621 iprint("cpu%d: didn't start!\n", cpu);
622 stopcpu(cpu); /* make sure it's stopped */
633 extern ulong getdebug(void);
636 panic("cpu%d: running non-secure", m->machno);
639 iprint("cpu%d: debug enable reg %#lux\n", m->machno, db);
647 /* cortex-a9 model-specific configuration */
649 putauxctl(aux | CpACsmp | CpACmaintbcast);
654 cortexa9cachecfg(void)
656 /* cortex-a9 model-specific configuration */
657 putauxctl(getauxctl() | CpACparity | CpAClwr0line | CpACl2pref);
661 * called on a cpu other than 0 from cpureset in l.s,
662 * from _vrst in lexception.s.
663 * mmu and l1 (and system-wide l2) caches and coherency (smpon) are on,
664 * but interrupts are disabled.
665 * our mmu is using an exact copy of cpu0's l1 page table
666 * as it was after userinit ran.
676 if (active.machs[m->machno]) {
679 panic("cpu%d: resetting after start", m->machno);
681 assert(m->machno != 0);
687 machinit(); /* bumps nmach, adds bit to machs */
688 machoff(m->machno); /* not ready to go yet */
690 /* clock signals and scu are system-wide and already on */
691 clockshutdown(); /* kill any watch-dog timer */
694 clockinit(); /* sets loop delay */
699 * notify cpu0 that we're up so it can proceed to l1diag.
701 evp = (ulong *)soc.exceptvec; /* magic */
705 l1diag(); /* contend with other cpus to verify sanity */
709 * pwr->detect == 0x1ff (default, all disabled)
711 pwr = (Power *)soc.power;
712 assert(pwr->gatests == MASK(7)); /* everything has power */
715 * 8169 has to initialise before we get past this, thus cpu0
716 * has to schedule processes first.
719 iprint("cpu%d: waiting for 8169\n", m->machno);
720 for (ms = 0; !l1ptstable.word && ms < 5000; ms += 10) {
722 cachedinvse(&l1ptstable.word, sizeof l1ptstable.word);
724 if (!l1ptstable.word)
725 iprint("cpu%d: 8169 unreasonably slow; proceeding\n", m->machno);
726 /* now safe to copy cpu0's l1 pt in mmuinit */
728 mmuinit(); /* update our l1 pt from cpu0's */
730 machon(m->machno); /* now ready to go and be scheduled */
733 iprint("cpu%d: scheding\n", m->machno);
735 panic("cpu%d: schedinit returned", m->machno);
738 /* mainly used to break out of wfi */
740 sgintr(Ureg *ureg, void *)
742 iprint("cpu%d: got sgi\n", m->machno);
743 /* try to prod cpu1 into life when it gets stuck */
757 /* conservative temporary values until archconfinit runs */
758 m->cpuhz = 1000 * Mhz; /* trimslice speed */
759 m->delayloop = m->cpuhz/2000; /* initial estimate */
764 /* all partitions were powered up by u-boot, so needn't do anything */
770 panic("archreset: too early for irqenable");
771 irqenable(Cpu0irq, sgintr, nil, "cpu0");
772 irqenable(Cpu1irq, sgintr, nil, "cpu1");
779 Clkrst *clk = (Clkrst *)soc.clkrst;
781 assert(m->machno == 0);
782 iprint("archreboot: reset!\n");
785 clk->rstdevl |= Sysreset;
789 /* shouldn't get here */
791 iprint("awaiting reset");
804 missing(ulong addr, char *name)
806 static int firstmiss = 1;
809 iprint("address zero for %s\n", name);
812 if (probeaddr(addr) >= 0)
820 iprint(" %s at %#lux", name, addr);
823 /* verify that all the necessary device registers are accessible */
828 missing(KZERO, "dram");
829 missing(soc.intr, "intr ctlr");
830 missing(soc.intrdist, "intr distrib");
831 missing(soc.tmr[0], "tegra timer1");
832 missing(soc.uart[0], "console uart");
833 missing(soc.pci, "pcie");
834 missing(soc.ether, "ether8169");
835 missing(soc.µs, "µs counter");
842 archflashwp(Flash*, int)
847 * for ../port/devflash.c:/^flashreset
848 * retrieve flash type, virtual base and length and return 0;
849 * return -1 on error (no flash)
852 archflashreset(int bank, Flash *f)
856 panic("archflashreset: rewrite for nor & nand flash on ts");
858 * this is set up for the igepv2 board.
861 f->addr = (void*)VIRTNOR; /* mapped here by archreset */
862 f->size = 0; /* done by probe */