Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

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