xref: /plan9-contrib/sys/src/9/vt5/archvt5.c (revision 1c9d674cbfa2c1924558af05e99c43e5c5cd4845)
1*1c9d674cSDavid du Colombier /*
2*1c9d674cSDavid du Colombier  * rae's virtex5 ml510 ppc440x5
3*1c9d674cSDavid du Colombier  * similar to the ml410 but only 4 leds, not 8.
4*1c9d674cSDavid du Colombier  */
5*1c9d674cSDavid du Colombier 
6*1c9d674cSDavid du Colombier #include	"u.h"
7*1c9d674cSDavid du Colombier #include	"../port/lib.h"
8*1c9d674cSDavid du Colombier #include	"mem.h"
9*1c9d674cSDavid du Colombier #include	"dat.h"
10*1c9d674cSDavid du Colombier #include	"fns.h"
11*1c9d674cSDavid du Colombier 
12*1c9d674cSDavid du Colombier #include	"io.h"
13*1c9d674cSDavid du Colombier #include	"../port/netif.h"
14*1c9d674cSDavid du Colombier #include	"etherif.h"
15*1c9d674cSDavid du Colombier #include	"../ip/ip.h"
16*1c9d674cSDavid du Colombier 
17*1c9d674cSDavid du Colombier #include "reboot.h"
18*1c9d674cSDavid du Colombier 
19*1c9d674cSDavid du Colombier enum {
20*1c9d674cSDavid du Colombier 	Ledmask = (1<<4) - 1,	/* for 4 bits */
21*1c9d674cSDavid du Colombier };
22*1c9d674cSDavid du Colombier 
23*1c9d674cSDavid du Colombier typedef struct Gpioregs Gpioregs;
24*1c9d674cSDavid du Colombier 
25*1c9d674cSDavid du Colombier struct Gpioregs {
26*1c9d674cSDavid du Colombier 	ulong	data;		/* write only? */
27*1c9d674cSDavid du Colombier 	ulong	tri;		/* tri-state */
28*1c9d674cSDavid du Colombier 	ulong	data2;		/* 2nd channel */
29*1c9d674cSDavid du Colombier 	ulong	tri2;
30*1c9d674cSDavid du Colombier 
31*1c9d674cSDavid du Colombier 	/* silly bits */
32*1c9d674cSDavid du Colombier 	ulong	pad[67];	/* sheesh */
33*1c9d674cSDavid du Colombier 	ulong	gie;		/* global intr enable */
34*1c9d674cSDavid du Colombier 	ulong	ier;		/* intr enable */
35*1c9d674cSDavid du Colombier 	ulong	isr;		/* intr status */
36*1c9d674cSDavid du Colombier };
37*1c9d674cSDavid du Colombier 
38*1c9d674cSDavid du Colombier void	machninit(int);
39*1c9d674cSDavid du Colombier 
40*1c9d674cSDavid du Colombier static void	twinkle(void);
41*1c9d674cSDavid du Colombier 
42*1c9d674cSDavid du Colombier void	(*archclocktick)(void) = twinkle;
43*1c9d674cSDavid du Colombier /* ether= for sys=anguish */
44*1c9d674cSDavid du Colombier uchar mymac[Eaddrlen] = { 0x00, 0x0A, 0x35, 0x01, 0xE1, 0x48 };
45*1c9d674cSDavid du Colombier uintptr memsz;
46*1c9d674cSDavid du Colombier 
47*1c9d674cSDavid du Colombier void
startcpu(int machno)48*1c9d674cSDavid du Colombier startcpu(int machno)
49*1c9d674cSDavid du Colombier {
50*1c9d674cSDavid du Colombier 	machninit(machno);
51*1c9d674cSDavid du Colombier 	mmuinit();
52*1c9d674cSDavid du Colombier 	/*
53*1c9d674cSDavid du Colombier 	 * can't print normally on cpu1 until we move shared locks
54*1c9d674cSDavid du Colombier 	 * into uncached sram and change synchronisation between
55*1c9d674cSDavid du Colombier 	 * the cpus fairly drastically.  cpu1 will then be a slave.
56*1c9d674cSDavid du Colombier 	 */
57*1c9d674cSDavid du Colombier uartlputc('Z');
58*1c9d674cSDavid du Colombier uartlputc('Z');
59*1c9d674cSDavid du Colombier uartlputc('0'+machno);
60*1c9d674cSDavid du Colombier 	splhi();
61*1c9d674cSDavid du Colombier 	for(;;) {
62*1c9d674cSDavid du Colombier 		putmsr(getmsr() | MSR_WE);
63*1c9d674cSDavid du Colombier 		barriers();
64*1c9d674cSDavid du Colombier 	}
65*1c9d674cSDavid du Colombier }
66*1c9d674cSDavid du Colombier 
67*1c9d674cSDavid du Colombier void
uncinit(void)68*1c9d674cSDavid du Colombier uncinit(void)
69*1c9d674cSDavid du Colombier {
70*1c9d674cSDavid du Colombier }
71*1c9d674cSDavid du Colombier 
72*1c9d674cSDavid du Colombier void
archreset(void)73*1c9d674cSDavid du Colombier archreset(void)
74*1c9d674cSDavid du Colombier {
75*1c9d674cSDavid du Colombier 	m->cpuhz = 400000000;
76*1c9d674cSDavid du Colombier 	m->opbhz = 66600000;
77*1c9d674cSDavid du Colombier 	m->clockgen = m->cpuhz;		/* it's the internal cpu clock */
78*1c9d674cSDavid du Colombier }
79*1c9d674cSDavid du Colombier 
80*1c9d674cSDavid du Colombier void
archvt5link(void)81*1c9d674cSDavid du Colombier archvt5link(void)
82*1c9d674cSDavid du Colombier {
83*1c9d674cSDavid du Colombier }
84*1c9d674cSDavid du Colombier 
85*1c9d674cSDavid du Colombier int
cmpswap(long * addr,long old,long new)86*1c9d674cSDavid du Colombier cmpswap(long *addr, long old, long new)
87*1c9d674cSDavid du Colombier {
88*1c9d674cSDavid du Colombier 	return cas32(addr, old, new);
89*1c9d674cSDavid du Colombier }
90*1c9d674cSDavid du Colombier 
91*1c9d674cSDavid du Colombier /*
92*1c9d674cSDavid du Colombier  * only use of GPIO now is access to LEDs
93*1c9d674cSDavid du Colombier  */
94*1c9d674cSDavid du Colombier 
95*1c9d674cSDavid du Colombier //static int leds;
96*1c9d674cSDavid du Colombier static uchar oldbits;
97*1c9d674cSDavid du Colombier static Lock lightlck;
98*1c9d674cSDavid du Colombier 
99*1c9d674cSDavid du Colombier static void
setleds(void)100*1c9d674cSDavid du Colombier setleds(void)
101*1c9d674cSDavid du Colombier {
102*1c9d674cSDavid du Colombier 	((Gpioregs*)Gpio)->data = ~oldbits & Ledmask;	/* 0 == lit */
103*1c9d674cSDavid du Colombier 	barriers();
104*1c9d674cSDavid du Colombier }
105*1c9d674cSDavid du Colombier 
106*1c9d674cSDavid du Colombier static void
ledinit(void)107*1c9d674cSDavid du Colombier ledinit(void)
108*1c9d674cSDavid du Colombier {
109*1c9d674cSDavid du Colombier 	Gpioregs *g;
110*1c9d674cSDavid du Colombier 
111*1c9d674cSDavid du Colombier 	/* set access to LED */
112*1c9d674cSDavid du Colombier 	g = (Gpioregs*)Gpio;
113*1c9d674cSDavid du Colombier /*	g->gie = 0;		/* wouldn't use intrs even if we had them */
114*1c9d674cSDavid du Colombier 	g->tri = 0;		/* outputs */
115*1c9d674cSDavid du Colombier 	barriers();
116*1c9d674cSDavid du Colombier 	setleds();
117*1c9d674cSDavid du Colombier }
118*1c9d674cSDavid du Colombier 
119*1c9d674cSDavid du Colombier uchar
lightstate(int state)120*1c9d674cSDavid du Colombier lightstate(int state)
121*1c9d674cSDavid du Colombier {
122*1c9d674cSDavid du Colombier 	int r;
123*1c9d674cSDavid du Colombier 
124*1c9d674cSDavid du Colombier 	if (m->machno != 0)
125*1c9d674cSDavid du Colombier 		return oldbits;
126*1c9d674cSDavid du Colombier 	ilock(&lightlck);
127*1c9d674cSDavid du Colombier 	r = oldbits;
128*1c9d674cSDavid du Colombier 	oldbits &= ~(Ledtrap|Ledkern|Leduser|Ledidle);
129*1c9d674cSDavid du Colombier 	oldbits |= state & (Ledtrap|Ledkern|Leduser|Ledidle);
130*1c9d674cSDavid du Colombier 	iunlock(&lightlck);
131*1c9d674cSDavid du Colombier 	setleds();
132*1c9d674cSDavid du Colombier 	return r;
133*1c9d674cSDavid du Colombier }
134*1c9d674cSDavid du Colombier 
135*1c9d674cSDavid du Colombier uchar
lightbiton(int bit)136*1c9d674cSDavid du Colombier lightbiton(int bit)
137*1c9d674cSDavid du Colombier {
138*1c9d674cSDavid du Colombier 	int r;
139*1c9d674cSDavid du Colombier 
140*1c9d674cSDavid du Colombier 	if (m->machno != 0)
141*1c9d674cSDavid du Colombier 		return oldbits;
142*1c9d674cSDavid du Colombier 	ilock(&lightlck);
143*1c9d674cSDavid du Colombier 	r = oldbits;
144*1c9d674cSDavid du Colombier 	oldbits |= bit;
145*1c9d674cSDavid du Colombier 	iunlock(&lightlck);
146*1c9d674cSDavid du Colombier 	setleds();
147*1c9d674cSDavid du Colombier 	return r;
148*1c9d674cSDavid du Colombier }
149*1c9d674cSDavid du Colombier 
150*1c9d674cSDavid du Colombier uchar
lightbitoff(int bit)151*1c9d674cSDavid du Colombier lightbitoff(int bit)
152*1c9d674cSDavid du Colombier {
153*1c9d674cSDavid du Colombier 	int r;
154*1c9d674cSDavid du Colombier 
155*1c9d674cSDavid du Colombier 	if (m->machno != 0)
156*1c9d674cSDavid du Colombier 		return oldbits;
157*1c9d674cSDavid du Colombier 	ilock(&lightlck);
158*1c9d674cSDavid du Colombier 	r = oldbits;
159*1c9d674cSDavid du Colombier 	oldbits &= ~bit;
160*1c9d674cSDavid du Colombier 	iunlock(&lightlck);
161*1c9d674cSDavid du Colombier 	setleds();
162*1c9d674cSDavid du Colombier 	return r;
163*1c9d674cSDavid du Colombier }
164*1c9d674cSDavid du Colombier 
165*1c9d674cSDavid du Colombier static void
twinkle(void)166*1c9d674cSDavid du Colombier twinkle(void)
167*1c9d674cSDavid du Colombier {
168*1c9d674cSDavid du Colombier 	static int bit;
169*1c9d674cSDavid du Colombier 
170*1c9d674cSDavid du Colombier 	if (m->machno != 0)
171*1c9d674cSDavid du Colombier 		return;
172*1c9d674cSDavid du Colombier 	if(m->ticks % (HZ/4) == 0) {
173*1c9d674cSDavid du Colombier 		bit ^= 1;
174*1c9d674cSDavid du Colombier 		if (bit)
175*1c9d674cSDavid du Colombier 			lightbiton(Ledpulse);
176*1c9d674cSDavid du Colombier 		else
177*1c9d674cSDavid du Colombier 			lightbitoff(Ledpulse);
178*1c9d674cSDavid du Colombier 		barriers();
179*1c9d674cSDavid du Colombier 	}
180*1c9d674cSDavid du Colombier 
181*1c9d674cSDavid du Colombier 	if(securemem)
182*1c9d674cSDavid du Colombier 		qtmclock();
183*1c9d674cSDavid du Colombier 	if(m->ticks % HZ == 0) {
184*1c9d674cSDavid du Colombier 		intrs1sec = 0;
185*1c9d674cSDavid du Colombier 		etherclock();
186*1c9d674cSDavid du Colombier 	}
187*1c9d674cSDavid du Colombier 	barriers();
188*1c9d674cSDavid du Colombier }
189*1c9d674cSDavid du Colombier 
190*1c9d674cSDavid du Colombier /*
191*1c9d674cSDavid du Colombier  * size by watching for bus errors (machine checks), but avoid
192*1c9d674cSDavid du Colombier  * tlb faults for unmapped memory beyond the maximum we expect.
193*1c9d674cSDavid du Colombier  */
194*1c9d674cSDavid du Colombier static uintptr
memsize(void)195*1c9d674cSDavid du Colombier memsize(void)
196*1c9d674cSDavid du Colombier {
197*1c9d674cSDavid du Colombier 	int fault;
198*1c9d674cSDavid du Colombier 	uintptr sz;
199*1c9d674cSDavid du Colombier 
200*1c9d674cSDavid du Colombier 	/* try powers of two */
201*1c9d674cSDavid du Colombier 	fault = 0;
202*1c9d674cSDavid du Colombier 	for (sz = MB; sz != 0 && sz < MAXMEM; sz <<= 1)
203*1c9d674cSDavid du Colombier 		if (probeaddr(KZERO|sz) < 0) {
204*1c9d674cSDavid du Colombier 			fault = 1;
205*1c9d674cSDavid du Colombier 			break;
206*1c9d674cSDavid du Colombier 		}
207*1c9d674cSDavid du Colombier 	if (sz >= MAXMEM && !fault)
208*1c9d674cSDavid du Colombier 		/* special handling for maximum size */
209*1c9d674cSDavid du Colombier 		if (probeaddr(KZERO|MEMTOP(sz)) < 0)
210*1c9d674cSDavid du Colombier 			sz >>= 1;
211*1c9d674cSDavid du Colombier 
212*1c9d674cSDavid du Colombier 	return securemem? MEMTOP(sz): sz;
213*1c9d674cSDavid du Colombier }
214*1c9d674cSDavid du Colombier 
215*1c9d674cSDavid du Colombier void
meminit(void)216*1c9d674cSDavid du Colombier meminit(void)
217*1c9d674cSDavid du Colombier {
218*1c9d674cSDavid du Colombier 	securemem = gotsecuremem();
219*1c9d674cSDavid du Colombier 
220*1c9d674cSDavid du Colombier 	/* size memory */
221*1c9d674cSDavid du Colombier 	memsz = memsize();
222*1c9d674cSDavid du Colombier 	conf.mem[0].npage = memsz / BY2PG;
223*1c9d674cSDavid du Colombier 	conf.mem[0].base = PGROUND(PADDR(end));
224*1c9d674cSDavid du Colombier 	conf.mem[0].npage -= conf.mem[0].base/BY2PG;
225*1c9d674cSDavid du Colombier 
226*1c9d674cSDavid du Colombier 	/* avoid clobbering bootstrap's stack in case cpu1 is using it */
227*1c9d674cSDavid du Colombier }
228*1c9d674cSDavid du Colombier 
229*1c9d674cSDavid du Colombier void
ioinit(void)230*1c9d674cSDavid du Colombier ioinit(void)
231*1c9d674cSDavid du Colombier {
232*1c9d674cSDavid du Colombier 	ledinit();
233*1c9d674cSDavid du Colombier 	addconf("console", "0");
234*1c9d674cSDavid du Colombier 	addconf("nobootprompt", "tcp");
235*1c9d674cSDavid du Colombier }
236*1c9d674cSDavid du Colombier 
237*1c9d674cSDavid du Colombier int
archether(int ctlno,Ether * ether)238*1c9d674cSDavid du Colombier archether(int ctlno, Ether *ether)
239*1c9d674cSDavid du Colombier {
240*1c9d674cSDavid du Colombier 	if(ctlno > 0)
241*1c9d674cSDavid du Colombier 		return -1;
242*1c9d674cSDavid du Colombier 
243*1c9d674cSDavid du Colombier 	if (probeaddr(Temac) >= 0) {
244*1c9d674cSDavid du Colombier 		ether->type = "lltemac";
245*1c9d674cSDavid du Colombier 		ether->port = ctlno;
246*1c9d674cSDavid du Colombier 		return 1;
247*1c9d674cSDavid du Colombier 	}
248*1c9d674cSDavid du Colombier 	return -1;
249*1c9d674cSDavid du Colombier }
250*1c9d674cSDavid du Colombier 
251*1c9d674cSDavid du Colombier void
clrmchk(void)252*1c9d674cSDavid du Colombier clrmchk(void)
253*1c9d674cSDavid du Colombier {
254*1c9d674cSDavid du Colombier 	putmcsr(~0);			/* clear machine check causes */
255*1c9d674cSDavid du Colombier 	sync();
256*1c9d674cSDavid du Colombier 	isync();
257*1c9d674cSDavid du Colombier 	putesr(0);			/* clears machine check */
258*1c9d674cSDavid du Colombier }
259*1c9d674cSDavid du Colombier 
260*1c9d674cSDavid du Colombier /*
261*1c9d674cSDavid du Colombier  * the new kernel is already loaded at address `code'
262*1c9d674cSDavid du Colombier  * of size `size' and (virtual) entry point `entry'.
263*1c9d674cSDavid du Colombier  */
264*1c9d674cSDavid du Colombier void
reboot(void * entry,void * code,ulong size)265*1c9d674cSDavid du Colombier reboot(void *entry, void *code, ulong size)
266*1c9d674cSDavid du Colombier {
267*1c9d674cSDavid du Colombier 	int cpu;
268*1c9d674cSDavid du Colombier 	void (*f)(ulong, ulong, ulong);
269*1c9d674cSDavid du Colombier 
270*1c9d674cSDavid du Colombier 	writeconf();
271*1c9d674cSDavid du Colombier 	shutdown(0);
272*1c9d674cSDavid du Colombier 
273*1c9d674cSDavid du Colombier 	/*
274*1c9d674cSDavid du Colombier 	 * should be the only processor running now
275*1c9d674cSDavid du Colombier 	 */
276*1c9d674cSDavid du Colombier 	cpu = getpir();
277*1c9d674cSDavid du Colombier 	if (cpu != 0)
278*1c9d674cSDavid du Colombier 		panic("rebooting on cpu %d", cpu);
279*1c9d674cSDavid du Colombier 
280*1c9d674cSDavid du Colombier 	print("shutting down...\n");
281*1c9d674cSDavid du Colombier 	delay(200);
282*1c9d674cSDavid du Colombier 
283*1c9d674cSDavid du Colombier 	splhi();
284*1c9d674cSDavid du Colombier 
285*1c9d674cSDavid du Colombier 	/* turn off buffered serial console */
286*1c9d674cSDavid du Colombier //	serialoq = nil;
287*1c9d674cSDavid du Colombier 
288*1c9d674cSDavid du Colombier 	/* shutdown devices */
289*1c9d674cSDavid du Colombier 	devtabshutdown();
290*1c9d674cSDavid du Colombier 	splhi();		/* device shutdowns could have lowered pl */
291*1c9d674cSDavid du Colombier 	intrshutdown();
292*1c9d674cSDavid du Colombier 	putmsr(getmsr() & ~MSR_DE);	/* disable debug facilities */
293*1c9d674cSDavid du Colombier 	putdbsr(~0);
294*1c9d674cSDavid du Colombier 
295*1c9d674cSDavid du Colombier 	/* setup reboot trampoline function */
296*1c9d674cSDavid du Colombier 	f = (void*)REBOOTADDR;
297*1c9d674cSDavid du Colombier 	sync();
298*1c9d674cSDavid du Colombier 	memmove(f, rebootcode, sizeof(rebootcode));
299*1c9d674cSDavid du Colombier 	sync();
300*1c9d674cSDavid du Colombier 	dcflush(PTR2UINT(f), sizeof rebootcode);
301*1c9d674cSDavid du Colombier 	icflush(PTR2UINT(f), sizeof rebootcode);
302*1c9d674cSDavid du Colombier 
303*1c9d674cSDavid du Colombier 	iprint("restart: entry %#p code %#p size %ld; trampoline %#p",
304*1c9d674cSDavid du Colombier 		entry, code, size, f);
305*1c9d674cSDavid du Colombier 	delay(100);		/* wait for uart to quiesce */
306*1c9d674cSDavid du Colombier 
307*1c9d674cSDavid du Colombier 	/* off we go - never to return */
308*1c9d674cSDavid du Colombier 	dcflush(PTR2UINT(entry), size);
309*1c9d674cSDavid du Colombier 	icflush(PTR2UINT(entry), size);
310*1c9d674cSDavid du Colombier 	/*
311*1c9d674cSDavid du Colombier 	 * trampoline code now at REBOOTADDR will copy code to entry,
312*1c9d674cSDavid du Colombier 	 * then jump to entry.
313*1c9d674cSDavid du Colombier 	 */
314*1c9d674cSDavid du Colombier 	iprint("\n");
315*1c9d674cSDavid du Colombier 	delay(10);
316*1c9d674cSDavid du Colombier 	(*f)((uintptr)entry, (uintptr)code, size);
317*1c9d674cSDavid du Colombier 
318*1c9d674cSDavid du Colombier 	/* never reached */
319*1c9d674cSDavid du Colombier 	iprint("new kernel returned!\n");
320*1c9d674cSDavid du Colombier 	archreboot();
321*1c9d674cSDavid du Colombier }
322