xref: /netbsd-src/sys/arch/evbppc/walnut/machdep.c (revision d20841bb642898112fe68f0ad3f7b26dddf56f07)
1 /*	$NetBSD: machdep.c,v 1.19 2003/12/30 12:33:16 pk Exp $	*/
2 
3 /*
4  * Copyright 2001, 2002 Wasabi Systems, Inc.
5  * All rights reserved.
6  *
7  * Written by Eduardo Horvath and Simon Burge for Wasabi Systems, Inc.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed for the NetBSD Project by
20  *      Wasabi Systems, Inc.
21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22  *    or promote products derived from this software without specific prior
23  *    written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 /*
39  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
40  * Copyright (C) 1995, 1996 TooLs GmbH.
41  * All rights reserved.
42  *
43  * Redistribution and use in source and binary forms, with or without
44  * modification, are permitted provided that the following conditions
45  * are met:
46  * 1. Redistributions of source code must retain the above copyright
47  *    notice, this list of conditions and the following disclaimer.
48  * 2. Redistributions in binary form must reproduce the above copyright
49  *    notice, this list of conditions and the following disclaimer in the
50  *    documentation and/or other materials provided with the distribution.
51  * 3. All advertising materials mentioning features or use of this software
52  *    must display the following acknowledgement:
53  *	This product includes software developed by TooLs GmbH.
54  * 4. The name of TooLs GmbH may not be used to endorse or promote products
55  *    derived from this software without specific prior written permission.
56  *
57  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
58  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
59  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
60  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
61  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
62  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
63  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
64  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
65  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
66  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
67  */
68 
69 #include <sys/cdefs.h>
70 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.19 2003/12/30 12:33:16 pk Exp $");
71 
72 #include "opt_compat_netbsd.h"
73 #include "opt_ddb.h"
74 #include "opt_ipkdb.h"
75 
76 #include <sys/param.h>
77 #include <sys/buf.h>
78 #include <sys/exec.h>
79 #include <sys/malloc.h>
80 #include <sys/mbuf.h>
81 #include <sys/mount.h>
82 #include <sys/msgbuf.h>
83 #include <sys/proc.h>
84 #include <sys/reboot.h>
85 #include <sys/sa.h>
86 #include <sys/syscallargs.h>
87 #include <sys/syslog.h>
88 #include <sys/systm.h>
89 #include <sys/kernel.h>
90 #include <sys/user.h>
91 #include <sys/boot_flag.h>
92 #include <sys/properties.h>
93 #include <sys/ksyms.h>
94 
95 #include <uvm/uvm_extern.h>
96 
97 #include <net/netisr.h>
98 
99 #include <machine/bus.h>
100 #include <machine/powerpc.h>
101 #include <machine/trap.h>
102 #include <machine/walnut.h>
103 
104 #include <powerpc/spr.h>
105 #include <powerpc/ibm4xx/dcr405gp.h>
106 #include <machine/bus.h>
107 
108 #include <dev/cons.h>
109 
110 #include "ksyms.h"
111 
112 #if defined(DDB)
113 #include <machine/db_machdep.h>
114 #include <ddb/db_extern.h>
115 #endif
116 
117 /*
118  * Global variables used here and there
119  */
120 struct vm_map *exec_map = NULL;
121 struct vm_map *mb_map = NULL;
122 struct vm_map *phys_map = NULL;
123 
124 /*
125  * This should probably be in autoconf!				XXX
126  */
127 char cpu_model[80];
128 char machine[] = MACHINE;		/* from <machine/param.h> */
129 char machine_arch[] = MACHINE_ARCH;	/* from <machine/param.h> */
130 
131 extern struct user *proc0paddr;
132 
133 char bootpath[256];
134 paddr_t msgbuf_paddr;
135 vaddr_t msgbuf_vaddr;
136 
137 #if NKSYMS || defined(DDB) || defined(LKM)
138 void *startsym, *endsym;
139 #endif
140 
141 int lcsplx(int);
142 void initppc(u_int, u_int, char *, void *);
143 
144 static void dumpsys(void);
145 static void install_extint(void (*)(void));
146 
147 #define MEMREGIONS	8
148 struct mem_region physmemr[MEMREGIONS];		/* Hard code memory */
149 struct mem_region availmemr[MEMREGIONS];	/* Who's supposed to set these up? */
150 
151 struct board_cfg_data board_data;
152 struct propdb *board_info = NULL;
153 
154 void
155 initppc(u_int startkernel, u_int endkernel, char *args, void *info_block)
156 {
157 	extern int defaulttrap, defaultsize;
158 	extern int sctrap, scsize;
159 	extern int alitrap, alisize;
160 	extern int dsitrap, dsisize;
161 	extern int isitrap, isisize;
162 	extern int mchktrap, mchksize;
163 	extern int tlbimiss4xx, tlbim4size;
164 	extern int tlbdmiss4xx, tlbdm4size;
165 	extern int pitfitwdog, pitfitwdogsize;
166 	extern int debugtrap, debugsize;
167 	extern int errata51handler, errata51size;
168 #ifdef DDB
169 	extern int ddblow, ddbsize;
170 #endif
171 #ifdef IPKDB
172 	extern int ipkdblow, ipkdbsize;
173 #endif
174 	int exc;
175 	struct cpu_info * const ci = curcpu();
176 
177 	/* Disable all external interrupts */
178 	mtdcr(DCR_UIC0_ER, 0);
179 
180         /* Initialize cache info for memcpy, etc. */
181         cpu_probe_cache();
182 
183 	/* Save info block */
184 	memcpy(&board_data, info_block, sizeof(board_data));
185 
186 	memset(physmemr, 0, sizeof physmemr);
187 	memset(availmemr, 0, sizeof availmemr);
188 	physmemr[0].start = 0;
189 	physmemr[0].size = board_data.mem_size & ~PGOFSET;
190 	/* Lower memory reserved by eval board BIOS */
191 	availmemr[0].start = startkernel;
192 	availmemr[0].size = board_data.mem_size - availmemr[0].start;
193 
194 	/*
195 	 * Initialize lwp0 and current pcb and pmap pointers.
196 	 */
197 	lwp0.l_cpu = ci;
198 	lwp0.l_addr = proc0paddr;
199 	memset(lwp0.l_addr, 0, sizeof *lwp0.l_addr);
200 
201 	curpcb = &proc0paddr->u_pcb;
202 	curpcb->pcb_pm = pmap_kernel();
203 
204 	/*
205 	 * Set up trap vectors
206 	 */
207 	for (exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100)
208 		switch (exc) {
209 		default:
210 			memcpy((void *)exc, &defaulttrap, (size_t)&defaultsize);
211 			break;
212 		case EXC_EXI:
213 			/*
214 			 * This one is (potentially) installed during autoconf
215 			 */
216 			break;
217 		case EXC_SC:
218 			memcpy((void *)EXC_SC, &sctrap, (size_t)&scsize);
219 			break;
220 		case EXC_ALI:
221 			memcpy((void *)EXC_ALI, &alitrap, (size_t)&alisize);
222 			break;
223 		case EXC_DSI:
224 			memcpy((void *)EXC_DSI, &dsitrap, (size_t)&dsisize);
225 			break;
226 		case EXC_ISI:
227 			memcpy((void *)EXC_ISI, &isitrap, (size_t)&isisize);
228 			break;
229 		case EXC_MCHK:
230 			memcpy((void *)EXC_MCHK, &mchktrap, (size_t)&mchksize);
231 			break;
232 		case EXC_ITMISS:
233 			memcpy((void *)EXC_ITMISS, &tlbimiss4xx,
234 				(size_t)&tlbim4size);
235 			break;
236 		case EXC_DTMISS:
237 			memcpy((void *)EXC_DTMISS, &tlbdmiss4xx,
238 				(size_t)&tlbdm4size);
239 			break;
240 		/*
241 		 * EXC_PIT, EXC_FIT, EXC_WDOG handlers
242 		 * are spaced by 0x10 bytes only..
243 		 */
244 		case EXC_PIT:
245 			memcpy((void *)EXC_PIT, &pitfitwdog,
246 				(size_t)&pitfitwdogsize);
247 			break;
248 		case EXC_DEBUG:
249 			memcpy((void *)EXC_DEBUG, &debugtrap,
250 				(size_t)&debugsize);
251 			break;
252 		case EXC_DTMISS|EXC_ALI:
253                         /* PPC405GP Rev D errata item 51 */
254 			memcpy((void *)(EXC_DTMISS|EXC_ALI), &errata51handler,
255 				(size_t)&errata51size);
256 			break;
257 #if defined(DDB) || defined(IPKDB)
258 		case EXC_PGM:
259 #if defined(DDB)
260 			memcpy((void *)exc, &ddblow, (size_t)&ddbsize);
261 #elif defined(IPKDB)
262 			memcpy((void *)exc, &ipkdblow, (size_t)&ipkdbsize);
263 #endif
264 #endif /* DDB | IPKDB */
265 			break;
266 		}
267 
268 	__syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100);
269 	mtspr(SPR_EVPR, 0);		/* Set Exception vector base */
270 	consinit();
271 
272 	/* Handle trap instruction as PGM exception */
273 	{
274 	  int dbcr0;
275 	  asm volatile("mfspr %0,%1":"=r"(dbcr0):"K"(SPR_DBCR0));
276 	  asm volatile("mtspr %0,%1"::"K"(SPR_DBCR0),"r"(dbcr0 & ~DBCR0_TDE));
277 	}
278 
279 	/*
280 	 * external interrupt handler install
281 	 */
282 	install_extint(ext_intr);
283 
284 	/*
285 	 * Now enable translation (and machine checks/recoverable interrupts).
286 	 */
287 	asm volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0; isync"
288 		      : : "r"(0), "K"(PSL_IR|PSL_DR));
289 	/* XXXX PSL_ME - With ME set kernel gets stuck... */
290 
291 	uvm_setpagesize();
292 
293 	/*
294 	 * Initialize pmap module.
295 	 */
296 	pmap_bootstrap(startkernel, endkernel);
297 
298 #ifdef DEBUG
299 	printf("Board config data:\n");
300 	printf("  usr_config_ver = %s\n", board_data.usr_config_ver);
301 	printf("  rom_sw_ver = %s\n", board_data.rom_sw_ver);
302 	printf("  mem_size = %u\n", board_data.mem_size);
303 	printf("  mac_address_local = %02x:%02x:%02x:%02x:%02x:%02x\n",
304 	    board_data.mac_address_local[0], board_data.mac_address_local[1],
305 	    board_data.mac_address_local[2], board_data.mac_address_local[3],
306 	    board_data.mac_address_local[4], board_data.mac_address_local[5]);
307 	printf("  mac_address_pci = %02x:%02x:%02x:%02x:%02x:%02x\n",
308 	    board_data.mac_address_pci[0], board_data.mac_address_pci[1],
309 	    board_data.mac_address_pci[2], board_data.mac_address_pci[3],
310 	    board_data.mac_address_pci[4], board_data.mac_address_pci[5]);
311 	printf("  processor_speed = %u\n", board_data.processor_speed);
312 	printf("  plb_speed = %u\n", board_data.plb_speed);
313 	printf("  pci_speed = %u\n", board_data.pci_speed);
314 #endif
315 
316 #if NKSYMS || defined(DDB) || defined(LKM)
317 	ksyms_init((int)((u_int)endsym - (u_int)startsym), startsym, endsym);
318 #endif
319 #ifdef DDB
320 	if (boothowto & RB_KDB)
321 		Debugger();
322 #endif
323 #ifdef IPKDB
324 	/*
325 	 * Now trap to IPKDB
326 	 */
327 	ipkdb_init();
328 	if (boothowto & RB_KDB)
329 		ipkdb_connect(0);
330 #endif
331 }
332 
333 static void
334 install_extint(void (*handler)(void))
335 {
336 	extern int extint, extsize;
337 	extern u_long extint_call;
338 	u_long offset = (u_long)handler - (u_long)&extint_call;
339 	int msr;
340 
341 #ifdef	DIAGNOSTIC
342 	if (offset > 0x1ffffff)
343 		panic("install_extint: too far away");
344 #endif
345 	asm volatile ("mfmsr %0; wrteei 0" : "=r"(msr));
346 	extint_call = (extint_call & 0xfc000003) | offset;
347 	memcpy((void *)EXC_EXI, &extint, (size_t)&extsize);
348 	__syncicache((void *)&extint_call, sizeof extint_call);
349 	__syncicache((void *)EXC_EXI, (int)&extsize);
350 	asm volatile ("mtmsr %0" :: "r"(msr));
351 }
352 
353 /*
354  * Machine dependent startup code.
355  */
356 
357 char msgbuf[MSGBUFSIZE];
358 
359 void
360 cpu_startup(void)
361 {
362 	vaddr_t minaddr, maxaddr;
363 	char pbuf[9];
364 
365 	/*
366 	 * Initialize error message buffer (at end of core).
367 	 */
368 #if 0	/* For some reason this fails... --Artem
369 	 * Besides, do we really have to put it at the end of core?
370 	 * Let's use static buffer for now
371 	 */
372 	if (!(msgbuf_vaddr = uvm_km_alloc(kernel_map, round_page(MSGBUFSIZE))))
373 		panic("startup: no room for message buffer");
374 	for (i = 0; i < btoc(MSGBUFSIZE); i++)
375 		pmap_kenter_pa(msgbuf_vaddr + i * PAGE_SIZE,
376 		    msgbuf_paddr + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE);
377 	initmsgbuf((caddr_t)msgbuf_vaddr, round_page(MSGBUFSIZE));
378 #else
379 	initmsgbuf((caddr_t)msgbuf, round_page(MSGBUFSIZE));
380 #endif
381 
382 	printf("%s", version);
383 	printf("Walnut PowerPC 405GP Evaluation Board\n");
384 
385 	format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
386 	printf("total memory = %s\n", pbuf);
387 
388 	minaddr = 0;
389 	/*
390 	 * Allocate a submap for exec arguments.  This map effectively
391 	 * limits the number of processes exec'ing at any time.
392 	 */
393 	exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
394 				 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
395 
396 	/*
397 	 * Allocate a submap for physio
398 	 */
399 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
400 				 VM_PHYS_SIZE, 0, FALSE, NULL);
401 
402 	/*
403 	 * No need to allocate an mbuf cluster submap.  Mbuf clusters
404 	 * are allocated via the pool allocator, and we use direct-mapped
405 	 * pool pages.
406 	 */
407 
408 	format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
409 	printf("avail memory = %s\n", pbuf);
410 
411 	/*
412 	 * Set up the board properties database.
413 	 */
414 	if (!(board_info = propdb_create("board info")))
415 		panic("Cannot create board info database");
416 
417 	if (board_info_set("mem-size", &board_data.mem_size,
418 		sizeof(&board_data.mem_size), PROP_CONST, 0))
419 		panic("setting mem-size");
420 	if (board_info_set("sip0-mac-addr", &board_data.mac_address_pci,
421 		sizeof(&board_data.mac_address_pci), PROP_CONST, 0))
422 		panic("setting sip0-mac-addr");
423 	if (board_info_set("processor-frequency", &board_data.processor_speed,
424 		sizeof(&board_data.processor_speed), PROP_CONST, 0))
425 		panic("setting processor-frequency");
426 
427 	/*
428 	 * Now that we have VM, malloc()s are OK in bus_space.
429 	 */
430 	bus_space_mallocok();
431 	fake_mapiodev = 0;
432 }
433 
434 
435 static void
436 dumpsys(void)
437 {
438 
439 	printf("dumpsys: TBD\n");
440 }
441 
442 /*
443  * Soft networking interrupts.
444  */
445 void
446 softnet(void)
447 {
448 	int isr;
449 
450 	isr = netisr;
451 	netisr = 0;
452 
453 #define DONETISR(bit, fn) do {		\
454 	if (isr & (1 << bit))		\
455 		fn();			\
456 } while (0)
457 
458 #include <net/netisr_dispatch.h>
459 
460 #undef DONETISR
461 
462 }
463 
464 /*
465  * Soft tty interrupts.
466  */
467 #include "com.h"
468 void
469 softserial(void)
470 {
471 #if NCOM > 0
472 	void comsoft(void);	/* XXX from dev/ic/com.c */
473 
474 	comsoft();
475 #endif
476 }
477 
478 /*
479  * Halt or reboot the machine after syncing/dumping according to howto.
480  */
481 void
482 cpu_reboot(int howto, char *what)
483 {
484 	static int syncing;
485 	static char str[256];
486 	char *ap = str, *ap1 = ap;
487 
488 	boothowto = howto;
489 	if (!cold && !(howto & RB_NOSYNC) && !syncing) {
490 		syncing = 1;
491 		vfs_shutdown();		/* sync */
492 		resettodr();		/* set wall clock */
493 	}
494 
495 	splhigh();
496 
497 	if (!cold && (howto & RB_DUMP))
498 		dumpsys();
499 
500 	doshutdownhooks();
501 
502 	if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
503 	  /* Power off here if we know how...*/
504 	}
505 
506 	if (howto & RB_HALT) {
507 		printf("halted\n\n");
508 
509 		goto reboot;	/* XXX for now... */
510 
511 #ifdef DDB
512 		printf("dropping to debugger\n");
513 		while(1)
514 			Debugger();
515 #endif
516 	}
517 
518 	printf("rebooting\n\n");
519 	if (what && *what) {
520 		if (strlen(what) > sizeof str - 5)
521 			printf("boot string too large, ignored\n");
522 		else {
523 			strcpy(str, what);
524 			ap1 = ap = str + strlen(str);
525 			*ap++ = ' ';
526 		}
527 	}
528 	*ap++ = '-';
529 	if (howto & RB_SINGLE)
530 		*ap++ = 's';
531 	if (howto & RB_KDB)
532 		*ap++ = 'd';
533 	*ap++ = 0;
534 	if (ap[-2] == '-')
535 		*ap1 = 0;
536 
537 	/* flush cache for msgbuf */
538 	__syncicache((void *)msgbuf_paddr, round_page(MSGBUFSIZE));
539 
540  reboot:
541 	ppc4xx_reset();
542 
543 	printf("ppc4xx_reset() failed!\n");
544 #ifdef DDB
545 	while(1)
546 		Debugger();
547 #else
548 	while (1)
549 		/* nothing */;
550 #endif
551 }
552 
553 int
554 lcsplx(int ipl)
555 {
556 
557 	return spllower(ipl); 	/* XXX */
558 }
559 
560 void
561 mem_regions(struct mem_region **mem, struct mem_region **avail)
562 {
563 
564 	*mem = physmemr;
565 	*avail = availmemr;
566 }
567