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