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