]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/teg2/archtegra.c
bcm, bcm64: add support for device tree parameter passing
[plan9front.git] / sys / src / 9 / teg2 / archtegra.c
1 /*
2  * nvidia tegra 2 architecture-specific stuff
3  */
4
5 #include "u.h"
6 #include "../port/lib.h"
7 #include "mem.h"
8 #include "dat.h"
9 #include "fns.h"
10 #include "../port/error.h"
11 #include "io.h"
12 #include "arm.h"
13
14 #include "../port/netif.h"
15 #include "../port/etherif.h"
16 #include "../port/flashif.h"
17
18 enum {
19         /* hardware limits imposed by register contents or layouts */
20         Maxcpus         = 4,
21         Maxflowcpus     = 2,
22
23         Debug   = 0,
24 };
25
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;
31
32 struct Clkrst {
33         ulong   rstsrc;
34         ulong   rstdevl;
35         ulong   rstdevh;
36         ulong   rstdevu;
37
38         ulong   clkoutl;
39         ulong   clkouth;
40         ulong   clkoutu;
41
42         uchar   _pad0[0x24-0x1c];
43         ulong   supcclkdiv;             /* super cclk divider */
44         ulong   _pad1;
45         ulong   supsclkdiv;             /* super sclk divider */
46
47         uchar   _pad4[0x4c-0x30];
48         ulong   clkcpu;
49
50         uchar   _pad1[0xe0-0x50];
51         ulong   pllxbase;               /* pllx controls CPU clock speed */
52         ulong   pllxmisc;
53         ulong   pllebase;               /* plle is dedicated to pcie */
54         ulong   pllemisc;
55
56         uchar   _pad2[0x340-0xf0];
57         ulong   cpuset;
58         ulong   cpuclr;
59 };
60
61 enum {
62         /* rstsrc bits */
63         Wdcpurst =      1<<0,
64         Wdcoprst =      1<<1,
65         Wdsysrst =      1<<2,
66         Wdsel =         1<<4,           /* tmr1 or tmr2? */
67         Wdena =         1<<5,
68
69         /* devl bits */
70         Sysreset =      1<<2,
71
72         /* clkcpu bits */
73         Cpu1stop =      1<<9,
74         Cpu0stop =      1<<8,
75
76         /* cpu* bits */
77         Cpu1dbgreset =  1<<13,
78         Cpu0dbgreset =  1<<12,
79         Cpu1wdreset =   1<<9,
80         Cpu0wdreset =   1<<8,
81         Cpu1dereset =   1<<5,
82         Cpu0dereset =   1<<4,
83         Cpu1reset =     1<<1,
84         Cpu0reset =     1<<0,
85 };
86
87 struct Power {
88         ulong   ctl;                    /* mainly for rtc clock signals */
89         ulong   secregdis;
90         ulong   swrst;
91
92         ulong   wakevmask;
93         ulong   waklvl;
94         ulong   waksts;
95         ulong   swwaksts;
96
97         ulong   dpdpadsovr;             /* deep power down pads override */
98         ulong   dpdsample;
99         ulong   dpden;
100
101         ulong   gatetimroff;
102         ulong   gatetimron;
103         ulong   toggle;
104         ulong   unclamp;
105         ulong   gatests;                /* ro */
106
107         ulong   goodtmr;
108         ulong   blinktmr;
109
110         ulong   noiopwr;
111         ulong   detect;
112         ulong   detlatch;
113
114         ulong   scratch[24];
115         ulong   secscratch[6];
116
117         ulong   cpupwrgoodtmr;
118         ulong   cpupwrofftmr;
119
120         ulong   pgmask[2];
121
122         ulong   autowaklvl;
123         ulong   autowaklvlmask;
124         ulong   wakdelay;
125
126         ulong   detval;
127         ulong   ddr;
128         ulong   usbdebdel;      /* usb de-bounce delay */
129         ulong   usbao;
130         ulong   cryptoop;
131         ulong   pllpwb0ovr;
132         ulong   scratch24[42-24+1];
133         ulong   boundoutmirr[3];
134         ulong   sys33ven;
135         ulong   boundoutmirracc;
136         ulong   gate;
137 };
138
139 enum {
140         /* toggle bits */
141         Start   = 1<<8,
142         /* partition ids */
143         Partpcie= 3,
144         Partl2  = 4,
145 };
146
147 struct Scu {
148         ulong   ctl;
149         ulong   cfg;                    /* ro */
150         ulong   cpupwrsts;
151         ulong   inval;
152
153         uchar   _pad0[0x40-0x10];
154         ulong   filtstart;
155         ulong   filtend;
156
157         uchar   _pad1[0x50-0x48];
158         ulong   accctl;                 /* initially 0 */
159         ulong   nsaccctl;
160 };
161
162 enum {
163         /* ctl bits */
164         Scuenable =     1<<0,
165         Filter =        1<<1,
166         Scuparity =     1<<2,
167         Specfill =      1<<3,           /* only for PL310 */
168         Allport0 =      1<<4,
169         Standby =       1<<5,
170         Icstandby =     1<<6,
171 };
172
173 struct Flow {
174         ulong   haltcpu0;
175         ulong   haltcop;
176         ulong   cpu0;
177         ulong   cop;
178         ulong   xrq;
179         ulong   haltcpu1;
180         ulong   cpu1;
181 };
182
183 enum {
184         /* haltcpu* bits */
185         Stop =  2<<29,
186
187         /* cpu* bits */
188         Event =                 1<<14,  /* w1c */
189         Waitwfebitsshift =      4,
190         Waitwfebitsmask =       MASK(2),
191         Eventenable =           1<<1,
192         Cpuenable =             1<<0,
193 };
194
195 struct Diag {
196         Cacheline c0;
197         Lock;
198         Ref     cnt;
199         Ref     sync;
200         Cacheline c1;
201 };
202
203 extern ulong testmem;
204
205 /*
206  * number of cpus available.  contrast with conf.nmach, which is number
207  * of running cpus.
208  */
209 int navailcpus;
210 Isolated l1ptstable;
211
212 Soc soc = {
213         .clkrst = 0x60006000,           /* clock & reset signals */
214         .power  = 0x7000e400,
215         .exceptvec = PHYSEVP,           /* undocumented magic */
216         .sema   = 0x60001000,
217         .l2cache= PHYSL2BAG,            /* pl310 bag on the side */
218         .flow   = 0x60007000,
219
220         /* 4 non-gic controllers */
221 //      .intr   = { 0x60004000, 0x60004100, 0x60004200, 0x60004300, },
222
223         /* private memory region */
224         .scu    = 0x50040000,
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,
230
231         .uart   = { 0x70006000, 0x70006040,
232                     0x70006200, 0x70006300, 0x70006400, },
233
234         .rtc    = 0x7000e000,
235         .tmr    = { 0x60005000, 0x60005008, 0x60005050, 0x60005058, },
236         .µs    = 0x60005010,
237
238         .pci    = 0x80000000,
239         .ether  = 0xa0024000,
240
241         .nand   = 0x70008000,
242         .nor    = 0x70009000,           /* also VIRTNOR */
243
244         .ehci   = P2VAHB(0xc5000000),   /* 1st of 3 */
245         .ide    = P2VAHB(0xc3000000),
246
247         .gpio   = { 0x6000d000, 0x6000d080, 0x6000d100, 0x6000d180,
248                             0x6000d200, 0x6000d280, 0x6000d300, },
249         .spi    = { 0x7000d400, 0x7000d600, 0x7000d800, 0x7000da00, },
250         .twsi   = 0x7000c000,
251         .mmc    = { P2VAHB(0xc8000000), P2VAHB(0xc8000200),
252                     P2VAHB(0xc8000400), P2VAHB(0xc8000600), },
253 };
254
255 static volatile Diag diag;
256 static int missed;
257
258 void
259 dumpcpuclks(void)               /* run CPU at full speed */
260 {
261         Clkrst *clk = (Clkrst *)soc.clkrst;
262
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);
267 }
268
269 static char *
270 devidstr(ulong)
271 {
272         return "ARM Cortex-A9";
273 }
274
275 void
276 archtegralink(void)
277 {
278 }
279
280 /* convert AddrDevid register to a string in buf and return buf */
281 char *
282 cputype2name(char *buf, int size)
283 {
284         ulong r;
285
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));
290         return buf;
291 }
292
293 static void
294 errata(void)
295 {
296         ulong reg, r, p;
297
298         /* apply cortex-a9 errata workarounds */
299         r = cpidget();                  /* main id register */
300         assert((r >> 24) == 'A');
301         p = r & MASK(4);                /* minor revision */
302         r >>= 20;
303         r &= MASK(4);                   /* major revision */
304
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 */
311         if (r < 3)
312                 reg |= 1<<11;                   /* 751472 */
313         cpwrsc(0, CpDTLB, 0, 1, reg);
314 }
315
316 void
317 archconfinit(void)
318 {
319         char *p;
320         ulong hz;
321
322         assert(m != nil);
323         m->cpuhz = 1000 * Mhz;                  /* trimslice speed */
324         p = getconf("*cpumhz");
325         if (p) {
326                 hz = atoi(p) * Mhz;
327                 if (hz >= 100*Mhz && hz <= 3600UL*Mhz)
328                         m->cpuhz = hz;
329         }
330         m->delayloop = m->cpuhz/2000;           /* initial estimate */
331         errata();
332 }
333
334 int
335 archether(unsigned ctlrno, Ether *ether)
336 {
337         switch(ctlrno) {
338         case 0:
339                 ether->type = "rtl8169";                /* pci-e ether */
340                 ether->ctlrno = ctlrno;
341                 ether->irq = Pcieirq;                   /* non-msi pci-e intr */
342                 ether->nopt = 0;
343                 ether->mbps = 1000;
344                 return 1;
345         }
346         return -1;
347 }
348
349 void
350 dumpscustate(void)
351 {
352         Scu *scu = (Scu *)soc.scu;
353
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);
358 }
359
360 void
361 scuon(void)
362 {
363         Scu *scu = (Scu *)soc.scu;
364
365         if (scu->ctl & Scuenable)
366                 return;
367         scu->inval = MASK(16);
368         coherence();
369         scu->ctl = Scuparity | Scuenable | Specfill;
370         coherence();
371 }
372
373 int
374 getncpus(void)
375 {
376         int n;
377         char *p;
378         Scu *scu;
379
380         if (navailcpus == 0) {
381                 scu = (Scu *)soc.scu;
382                 navailcpus = (scu->cfg & MASK(2)) + 1;
383                 if (navailcpus > MAXMACH)
384                         navailcpus = MAXMACH;
385
386                 p = getconf("*ncpu");
387                 if (p && *p) {
388                         n = atoi(p);
389                         if (n > 0 && n < navailcpus)
390                                 navailcpus = n;
391                 }
392         }
393         return navailcpus;
394 }
395
396 void
397 cpuidprint(void)
398 {
399         char name[64];
400
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");
406 }
407
408 static void
409 clockson(void)
410 {
411         Clkrst *clk = (Clkrst *)soc.clkrst;
412
413         /* enable all by clearing resets */
414         clk->rstdevl = clk->rstdevh = clk->rstdevu = 0;
415         coherence();
416         clk->clkoutl = clk->clkouth = clk->clkoutu = ~0; /* enable all clocks */
417         coherence();
418
419         clk->rstsrc = Wdcpurst | Wdcoprst | Wdsysrst | Wdena;
420         coherence();
421 }
422
423 /* we could be shutting down ourself (if cpu == m->machno), so take care. */
424 void
425 stopcpu(uint cpu)
426 {
427         Flow *flow = (Flow *)soc.flow;
428         Clkrst *clk = (Clkrst *)soc.clkrst;
429
430         if (cpu == 0) {
431                 iprint("stopcpu: may not stop cpu0\n");
432                 return;
433         }
434
435         machoff(cpu);
436         lock(&active);
437         active.stopped |= 1 << cpu;
438         unlock(&active);
439         l1cache->wb();
440
441         /* shut down arm7 avp coproc so it can't cause mischief. */
442         /* could try watchdog without stopping avp. */
443         flow->haltcop = Stop;
444         coherence();
445         flow->cop = 0;                                  /* no Cpuenable */
446         coherence();
447         delay(10);
448
449         assert(cpu < Maxflowcpus);
450         *(cpu == 0? &flow->haltcpu0: &flow->haltcpu1) = Stop;
451         coherence();
452         *(cpu == 0? &flow->cpu0: &flow->cpu1) = 0;      /* no Cpuenable */
453         coherence();
454         delay(10);
455
456         /* cold reset */
457         assert(cpu < Maxcpus);
458         clk->cpuset = (Cpu0reset | Cpu0dbgreset | Cpu0dereset) << cpu;
459         coherence();
460         delay(1);
461
462         l1cache->wb();
463 }
464
465 static void
466 synccpus(Ref *cntp, int n)
467 {
468         incref(cntp);
469         while (cntp->ref < n)
470                 ;
471         /* all cpus should now be here */
472 }
473
474 static void
475 pass1(int pass, volatile Diag *dp)
476 {
477         int i;
478
479         if(m->machno == 0)
480                 iprint(" %d", pass);
481         for (i = 1000*1000; --i > 0; ) {
482                 incref(&dp->cnt);
483                 incref(&dp->cnt);
484         }
485
486         synccpus(&dp->sync, navailcpus);
487         /* all cpus are now here */
488
489         ilock(dp);
490         if(dp->cnt.ref != 0)
491                 panic("cpu%d: diag: failed w count %ld", m->machno, dp->cnt.ref);
492         iunlock(dp);
493
494         synccpus(&dp->sync, 2 * navailcpus);
495         /* all cpus are now here */
496         decref(&dp->sync);
497         decref(&dp->sync);
498 }
499
500 /*
501  * try to confirm coherence of l1 caches.
502  * assume that all available cpus will be started.
503  */
504 void
505 l1diag(void)
506 {
507         int pass;
508         volatile Diag *dp;
509
510         if (!Debug)
511                 return;
512
513         l1cache->wb();
514
515         /*
516          * synchronise and print
517          */
518         dp = &diag;
519         ilock(dp);
520         if (m->machno == 0)
521                 iprint("l1: waiting for %d cpus... ", navailcpus);
522         iunlock(dp);
523
524         synccpus(&dp->sync, navailcpus);
525
526         ilock(dp);
527         if (m->machno == 0)
528                 iprint("cache coherency pass");
529         iunlock(dp);
530
531         synccpus(&dp->sync, 2 * navailcpus);
532         decref(&dp->sync);
533         decref(&dp->sync);
534
535         /*
536          * cpus contend
537          */
538         for (pass = 0; pass < 3; pass++)
539                 pass1(pass, dp);
540
541         /*
542          * synchronise and check sanity
543          */
544         synccpus(&dp->sync, navailcpus);
545
546         if(dp->sync.ref < navailcpus || dp->sync.ref >= 2 * navailcpus)
547                 panic("cpu%d: diag: failed w dp->sync %ld", m->machno,
548                         dp->sync.ref);
549         if(dp->cnt.ref != 0)
550                 panic("cpu%d: diag: failed w dp->cnt %ld", m->machno,
551                         dp->cnt.ref);
552
553         ilock(dp);
554         iprint(" cpu%d ok", m->machno);
555         iunlock(dp);
556
557         synccpus(&dp->sync, 2 * navailcpus);
558         decref(&dp->sync);
559         decref(&dp->sync);
560         l1cache->wb();
561
562         /*
563          * all done, print
564          */
565         ilock(dp);
566         if (m->machno == 0)
567                 iprint("\n");
568         iunlock(dp);
569 }
570
571 static void
572 unfreeze(uint cpu)
573 {
574         Clkrst *clk = (Clkrst *)soc.clkrst;
575         Flow *flow = (Flow *)soc.flow;
576
577         assert(cpu < Maxcpus);
578
579         clk->clkcpu &= ~(Cpu0stop << cpu);
580         coherence();
581         /* out of reset */
582         clk->cpuclr = (Cpu0reset | Cpu0wdreset | Cpu0dbgreset | Cpu0dereset) <<
583                 cpu;
584         coherence();
585
586         assert(cpu < Maxflowcpus);
587         *(cpu == 0? &flow->cpu0: &flow->cpu1) = 0;
588         coherence();
589         *(cpu == 0? &flow->haltcpu0: &flow->haltcpu1) = 0; /* normal operat'n */
590         coherence();
591 }
592
593 /*
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.
598  */
599 int
600 startcpu(uint cpu)
601 {
602         int i, r;
603         ulong oldvec, rstaddr;
604         ulong *evp = (ulong *)soc.exceptvec;    /* magic */
605
606         r = 0;
607         if (getncpus() < 2 || cpu == m->machno ||
608             cpu >= MAXMACH || cpu >= navailcpus)
609                 return -1;
610
611         oldvec = *evp;
612         l1cache->wb();                  /* start next cpu w same view of ram */
613         *evp = rstaddr = PADDR(_vrst);  /* will start cpu executing at _vrst */
614         coherence();
615         l1cache->wb();
616         unfreeze(cpu);
617
618         for (i = 2000; i > 0 && *evp == rstaddr; i--)
619                 delay(1);
620         if (i <= 0 || *evp != cpu) {
621                 iprint("cpu%d: didn't start!\n", cpu);
622                 stopcpu(cpu);           /* make sure it's stopped */
623                 r = -1;
624         }
625         *evp = oldvec;
626         return r;
627 }
628
629 static void
630 cksecure(void)
631 {
632         ulong db;
633         extern ulong getdebug(void);
634
635         if (getscr() & 1)
636                 panic("cpu%d: running non-secure", m->machno);
637         db = getdebug();
638         if (db)
639                 iprint("cpu%d: debug enable reg %#lux\n", m->machno, db);
640 }
641
642 ulong
643 smpon(void)
644 {
645         ulong aux;
646
647         /* cortex-a9 model-specific configuration */
648         aux = getauxctl();
649         putauxctl(aux | CpACsmp | CpACmaintbcast);
650         return aux;
651 }
652
653 void
654 cortexa9cachecfg(void)
655 {
656         /* cortex-a9 model-specific configuration */
657         putauxctl(getauxctl() | CpACparity | CpAClwr0line | CpACl2pref);
658 }
659
660 /*
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.
667  */
668 void
669 cpustart(void)
670 {
671         int ms;
672         ulong *evp;
673         Power *pwr;
674
675         up = nil;
676         if (active.machs[m->machno]) {
677                 serialputc('?');
678                 serialputc('r');
679                 panic("cpu%d: resetting after start", m->machno);
680         }
681         assert(m->machno != 0);
682
683         errata();
684         cortexa9cachecfg();
685         memdiag(&testmem);
686
687         machinit();                     /* bumps nmach, adds bit to machs */
688         machoff(m->machno);             /* not ready to go yet */
689
690         /* clock signals and scu are system-wide and already on */
691         clockshutdown();                /* kill any watch-dog timer */
692
693         trapinit();
694         clockinit();                    /* sets loop delay */
695         timersinit();
696         cpuidprint();
697
698         /*
699          * notify cpu0 that we're up so it can proceed to l1diag.
700          */
701         evp = (ulong *)soc.exceptvec;   /* magic */
702         *evp = m->machno;
703         coherence();
704
705         l1diag();               /* contend with other cpus to verify sanity */
706
707         /*
708          * pwr->noiopwr == 0
709          * pwr->detect == 0x1ff (default, all disabled)
710          */
711         pwr = (Power *)soc.power;
712         assert(pwr->gatests == MASK(7)); /* everything has power */
713
714         /*
715          * 8169 has to initialise before we get past this, thus cpu0
716          * has to schedule processes first.
717          */
718         if (Debug)
719                 iprint("cpu%d: waiting for 8169\n", m->machno);
720         for (ms = 0; !l1ptstable.word && ms < 5000; ms += 10) {
721                 delay(10);
722                 cachedinvse(&l1ptstable.word, sizeof l1ptstable.word);
723         }
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 */
727
728         mmuinit();                      /* update our l1 pt from cpu0's */
729         fpon();
730         machon(m->machno);              /* now ready to go and be scheduled */
731
732         if (Debug)
733                 iprint("cpu%d: scheding\n", m->machno);
734         schedinit();
735         panic("cpu%d: schedinit returned", m->machno);
736 }
737
738 /* mainly used to break out of wfi */
739 void
740 sgintr(Ureg *ureg, void *)
741 {
742         iprint("cpu%d: got sgi\n", m->machno);
743         /* try to prod cpu1 into life when it gets stuck */
744         if (m->machno != 0)
745                 clockprod(ureg);
746 }
747
748 void
749 archreset(void)
750 {
751         static int beenhere;
752
753         if (beenhere)
754                 return;
755         beenhere = 1;
756
757         /* conservative temporary values until archconfinit runs */
758         m->cpuhz = 1000 * Mhz;                  /* trimslice speed */
759         m->delayloop = m->cpuhz/2000;           /* initial estimate */
760
761         prcachecfg();
762
763         clockson();
764         /* all partitions were powered up by u-boot, so needn't do anything */
765         archconfinit();
766 //      resetusb();
767         fpon();
768
769         if (irqtooearly)
770                 panic("archreset: too early for irqenable");
771         irqenable(Cpu0irq, sgintr, nil, "cpu0");
772         irqenable(Cpu1irq, sgintr, nil, "cpu1");
773         /* ... */
774 }
775
776 void
777 archreboot(void)
778 {
779         Clkrst *clk = (Clkrst *)soc.clkrst;
780
781         assert(m->machno == 0);
782         iprint("archreboot: reset!\n");
783         delay(20);
784
785         clk->rstdevl |= Sysreset;
786         coherence();
787         delay(500);
788
789         /* shouldn't get here */
790         splhi();
791         iprint("awaiting reset");
792         for(;;) {
793                 delay(1000);
794                 print(".");
795         }
796 }
797
798 void
799 kbdinit(void)
800 {
801 }
802
803 static void
804 missing(ulong addr, char *name)
805 {
806         static int firstmiss = 1;
807
808         if (addr == 0) {
809                 iprint("address zero for %s\n", name);
810                 return;
811         }
812         if (probeaddr(addr) >= 0)
813                 return;
814         missed++;
815         if (firstmiss) {
816                 iprint("missing:");
817                 firstmiss = 0;
818         } else
819                 iprint(",\n\t");
820         iprint(" %s at %#lux", name, addr);
821 }
822
823 /* verify that all the necessary device registers are accessible */
824 void
825 chkmissing(void)
826 {
827         delay(10);
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");
836         if (missed)
837                 iprint("\n");
838         delay(10);
839 }
840
841 void
842 archflashwp(Flash*, int)
843 {
844 }
845
846 /*
847  * for ../port/devflash.c:/^flashreset
848  * retrieve flash type, virtual base and length and return 0;
849  * return -1 on error (no flash)
850  */
851 int
852 archflashreset(int bank, Flash *f)
853 {
854         if(bank != 0)
855                 return -1;
856 panic("archflashreset: rewrite for nor & nand flash on ts");
857         /*
858          * this is set up for the igepv2 board.
859          */
860         f->type = "onenand";
861         f->addr = (void*)VIRTNOR;               /* mapped here by archreset */
862         f->size = 0;                            /* done by probe */
863         f->width = 1;
864         f->interleave = 0;
865         return 0;
866 }