xref: /plan9-contrib/sys/src/9/vt5/archvt5.c (revision 1c9d674cbfa2c1924558af05e99c43e5c5cd4845)
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