xref: /netbsd-src/sys/arch/evbppc/explora/machdep.c (revision d710132b4b8ce7f7cccaaf660cb16aa16b4077a0)
1 /*	$NetBSD: machdep.c,v 1.2 2003/04/26 11:05:12 ragge Exp $	*/
2 
3 /*-
4  * Copyright (c) 2003 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Juergen Hannken-Illjes.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by the NetBSD
21  *      Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <sys/param.h>
40 #include <sys/buf.h>
41 #include <sys/msgbuf.h>
42 #include <sys/kernel.h>
43 #include <sys/mount.h>
44 #include <sys/proc.h>
45 #include <sys/user.h>
46 #include <sys/reboot.h>
47 #include <sys/properties.h>
48 #include <sys/ksyms.h>
49 
50 #include <uvm/uvm_extern.h>
51 
52 #include <net/netisr.h>
53 
54 #include <machine/explora.h>
55 #include <machine/bus.h>
56 #include <machine/powerpc.h>
57 #include <machine/trap.h>
58 
59 #include <powerpc/spr.h>
60 #include <powerpc/ibm4xx/dcr403cgx.h>
61 
62 #include "ksyms.h"
63 
64 #if NKSYMS || defined(DDB) || defined(LKM)
65 #include <machine/db_machdep.h>
66 #include <ddb/db_extern.h>
67 #endif
68 
69 #define MEMREGIONS	2
70 #define TLB_PG_SIZE	(16*1024*1024)
71 
72 char cpu_model[80];
73 char machine[] = MACHINE;		/* from <machine/param.h> */
74 char machine_arch[] = MACHINE_ARCH;	/* from <machine/param.h> */
75 
76 extern struct user *proc0paddr;
77 
78 struct propdb *board_info = NULL;
79 struct vm_map *phys_map = NULL;
80 struct vm_map *mb_map = NULL;
81 struct vm_map *exec_map = NULL;
82 char msgbuf[MSGBUFSIZE];
83 paddr_t msgbuf_paddr;
84 static unsigned cpuspeed = 66000000;
85 static unsigned memsize;
86 
87 static struct mem_region phys_mem[MEMREGIONS];
88 static struct mem_region avail_mem[MEMREGIONS];
89 
90 void		bootstrap(u_int, u_int);
91 static void	install_extint(void (*)(void));
92 int		lcsplx(int);
93 
94 /*
95  * Trap vectors
96  */
97 extern int defaulttrap, defaultsize;
98 extern int sctrap, scsize;
99 extern int alitrap, alisize;
100 extern int dsitrap, dsisize;
101 extern int isitrap, isisize;
102 extern int mchktrap, mchksize;
103 extern int tlbimiss4xx, tlbim4size;
104 extern int tlbdmiss4xx, tlbdm4size;
105 extern int pitfitwdog, pitfitwdogsize;
106 extern int debugtrap, debugsize;
107 extern int errata51handler, errata51size;
108 #ifdef DDB
109 extern int ddblow, ddbsize;
110 #endif
111 static struct {
112 	int vector;
113 	void *addr;
114 	void *size;
115 } trap_table[] = {
116 	{ EXC_SC,	&sctrap,	&scsize },
117 	{ EXC_ALI,	&alitrap,	&alisize },
118 	{ EXC_DSI,	&dsitrap,	&dsisize },
119 	{ EXC_ISI,	&isitrap,	&isisize },
120 	{ EXC_MCHK,	&mchktrap,	&mchksize },
121 	{ EXC_ITMISS,	&tlbimiss4xx,	&tlbim4size },
122 	{ EXC_DTMISS,	&tlbdmiss4xx,	&tlbdm4size },
123 	{ EXC_PIT,	&pitfitwdog,	&pitfitwdogsize },
124 	{ EXC_DEBUG,	&debugtrap,	&debugsize },
125 	{ (EXC_DTMISS|EXC_ALI), &errata51handler, &errata51size },
126 #if defined(DDB)
127 	{ EXC_PGM,	&ddblow,	&ddbsize },
128 #endif /* DDB */
129 };
130 
131 static void
132 set_tlb(int idx, u_int addr, u_int flags)
133 {
134 	u_int lo, hi;
135 
136 	addr &= ~(TLB_PG_SIZE-1);
137 
138 	lo = addr | TLB_EX | TLB_WR | flags;
139 #ifdef PPC_4XX_NOCACHE
140 	lo |= TLB_I;
141 #endif
142 	hi = addr | TLB_VALID | TLB_PG_16M;
143 
144 	asm volatile(
145 	    "	tlbwe %1,%0,1	\n"
146 	    "	tlbwe %2,%0,0	\n"
147 	    "	sync		\n"
148 	    : : "r" (idx), "r" (lo), "r" (hi) );
149 }
150 
151 void
152 bootstrap(u_int startkernel, u_int endkernel)
153 {
154 	u_int i, j, t, br[4];
155 	u_int maddr, msize, size;
156 	struct cpu_info * const ci = &cpu_info[0];
157 
158 	consinit();
159 
160 	br[0] = mfdcr(DCR_BR4);
161 	br[1] = mfdcr(DCR_BR5);
162 	br[2] = mfdcr(DCR_BR6);
163 	br[3] = mfdcr(DCR_BR7);
164 
165 	for (i = 0; i < 4; i++)
166 		for (j = i+1; j < 4; j++)
167 			if (br[j] < br[i])
168 				t = br[j], br[j] = br[i], br[i] = t;
169 
170 	for (i = 0, size = 0; i < 4; i++) {
171 		if (((br[i] >> 19) & 3) != 3)
172 			continue;
173 		maddr = ((br[i] >> 24) & 0xff) << 20;
174 		msize = 1 << (20 + ((br[i] >> 21) & 7));
175 		if (maddr+msize > size)
176 			size = maddr+msize;
177 	}
178 
179 	phys_mem[0].start = 0;
180 	phys_mem[0].size = size & ~PGOFSET;
181 	avail_mem[0].start = startkernel;
182 	avail_mem[0].size = size-startkernel;
183 
184 	asm volatile(
185 	    "	mtpid %0	\n"
186 	    "	sync		\n"
187 	    : : "r" (1) );
188 
189 	/*
190 	 * Setup initial tlbs.
191 	 * Physical memory is mapped into the first (reserved) tlbs.
192 	 * Memory of potential console devices is mapped into the
193 	 * last tlbs. They are only needed until the devices are configured.
194 	 */
195 
196 	t = 0;
197 	for (maddr = 0; maddr < phys_mem[0].size; maddr += TLB_PG_SIZE)
198 		set_tlb(t++, maddr, 0);
199 
200 	t = NTLB-1;
201 	set_tlb(t--, BASE_FB, TLB_I | TLB_G);
202 	set_tlb(t--, BASE_FB2, TLB_I | TLB_G);
203 	set_tlb(t--, BASE_COM, TLB_I | TLB_G);
204 
205 	/* Disable all external interrupts */
206 	mtdcr(DCR_EXIER, 0);
207 
208 	/* Disable all timer interrupts */
209 	mtspr(SPR_TCR, 0);
210 
211 	/* Initialize cache info for memcpy, etc. */
212 	cpu_probe_cache();
213 
214 	/*
215 	 * Initialize lwp0 and current pcb and pmap pointers.
216 	 */
217 	lwp0.l_cpu = ci;
218 	lwp0.l_addr = proc0paddr;
219 	memset(lwp0.l_addr, 0, sizeof *lwp0.l_addr);
220 
221 	curpcb = &proc0paddr->u_pcb;
222 	curpm = curpcb->pcb_pmreal = curpcb->pcb_pm = pmap_kernel();
223 
224 	/*
225 	 * Install trap vectors.
226 	 */
227 
228 	for (i = EXC_RSVD; i <= EXC_LAST; i += 0x100)
229 		memcpy((void *)i, &defaulttrap, (size_t)&defaultsize);
230 
231 	for (i = 0; i < sizeof(trap_table)/sizeof(trap_table[0]); i++) {
232 		memcpy((void *)trap_table[i].vector, trap_table[i].addr,
233 		    (size_t)trap_table[i].size);
234 	}
235 
236 	__syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100);
237 
238 	/*
239 	 * Set Exception vector base.
240 	 * Handle trap instruction as PGM exception.
241 	 */
242 
243 	mtspr(SPR_EVPR, 0);
244 
245 	t = mfspr(SPR_DBCR0);
246 	t &= ~DBCR0_TDE;
247 	mtspr(SPR_DBCR0, t);
248 
249 	/*
250 	 * External interrupt handler install.
251 	 */
252 
253 	install_extint(ext_intr);
254 
255 	/*
256 	 * Now enable translation (and machine checks/recoverable interrupts).
257 	 */
258 	asm volatile (
259 	    "	mfmsr %0	\n"
260 	    "	ori %0,%0,%1	\n"
261 	    "	mtmsr %0	\n"
262 	    "	sync		\n"
263 	    : : "r" (0), "K" (PSL_IR|PSL_DR|PSL_ME) );
264 
265 	uvm_setpagesize();
266 
267 	/*
268 	 * Initialize pmap module.
269 	 */
270 	pmap_bootstrap(startkernel, endkernel);
271 
272 #if NKSYMS || defined(DDB) || defined(LKM)
273 	ksyms_init(0, NULL, NULL);
274 #endif
275 
276 	fake_mapiodev = 0;
277 }
278 
279 static void
280 install_extint(void (*handler)(void))
281 {
282 	extern int extint, extsize;
283 	extern u_long extint_call;
284 	u_long offset = (u_long)handler - (u_long)&extint_call;
285 	int omsr, msr;
286 
287 #ifdef	DIAGNOSTIC
288 	if (offset > 0x1ffffff)
289 		panic("install_extint: too far away");
290 #endif
291 	asm volatile (
292 	    "	mfmsr %0	\n"
293 	    "	andi. %1,%0,%2	\n"
294 	    "	mtmsr %1	\n"
295 	    : "=r" (omsr), "=r" (msr) : "K" ((u_short)~PSL_EE) );
296 	extint_call = (extint_call & 0xfc000003) | offset;
297 	memcpy((void *)EXC_EXI, &extint, (size_t)&extsize);
298 	__syncicache((void *)&extint_call, sizeof extint_call);
299 	__syncicache((void *)EXC_EXI, (int)&extsize);
300 	asm volatile (
301 	    "	mtmsr %0	\n"
302 	    : : "r" (omsr) );
303 }
304 
305 void
306 cpu_startup(void)
307 {
308 	caddr_t v;
309 	vaddr_t minaddr, maxaddr;
310 	u_int sz, i, base, residual;
311 	char pbuf[9];
312 
313 	/*
314 	 * Initialize error message buffer (before start of kernel)
315 	 */
316 	initmsgbuf((caddr_t)msgbuf, round_page(MSGBUFSIZE));
317 
318 	printf("%s", version);
319 	printf("NCD Explora451\n");
320 
321 	memsize = ctob(physmem);
322 	format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
323 	printf("total memory = %s\n", pbuf);
324 
325 	/*
326 	 * Find out how much space we need, allocate it,
327 	 * and then give everything true virtual addresses.
328 	 */
329 	sz = (u_int)allocsys(NULL, NULL);
330 	if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0)
331 		panic("startup: no room for tables");
332 	if (allocsys(v, NULL) - v != sz)
333 		panic("startup: table size inconsistency");
334 
335 	/*
336 	 * Now allocate buffers proper.  They are different than the above
337 	 * in that they usually occupy more virtual memory than physical.
338 	 */
339 	sz = MAXBSIZE * nbuf;
340 	minaddr = 0;
341 	if (uvm_map(kernel_map, (vaddr_t *)&minaddr, round_page(sz),
342 		NULL, UVM_UNKNOWN_OFFSET, 0,
343 		UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
344 			    UVM_ADV_NORMAL, 0)) != 0)
345 		panic("startup: cannot allocate VM for buffers");
346 	buffers = (char *)minaddr;
347 	base = bufpages / nbuf;
348 	residual = bufpages % nbuf;
349 	if (base >= MAXBSIZE) {
350 		/* Don't want to alloc more physical mem than ever needed */
351 		base = MAXBSIZE;
352 		residual = 0;
353 	}
354 	for (i = 0; i < nbuf; i++) {
355 		vsize_t curbufsize;
356 		vaddr_t curbuf;
357 		struct vm_page *pg;
358 
359 		curbuf = (vaddr_t)buffers + i * MAXBSIZE;
360 		curbufsize = NBPG * (i < residual ? base + 1 : base);
361 
362 		while (curbufsize) {
363 			pg = uvm_pagealloc(NULL, 0, NULL, 0);
364 			if (pg == NULL)
365 				panic("cpu_startup: not enough memory for "
366 				    "buffer cache");
367 			pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg),
368 			    VM_PROT_READ | VM_PROT_WRITE);
369 			curbuf += PAGE_SIZE;
370 			curbufsize -= PAGE_SIZE;
371 		}
372 	}
373 
374 	/*
375 	 * Allocate a submap for exec arguments.  This map effectively
376 	 * limits the number of processes exec'ing at any time.
377 	 */
378 	exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
379 				 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
380 
381 	/*
382 	 * Allocate a submap for physio
383 	 */
384 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
385 				 VM_PHYS_SIZE, 0, FALSE, NULL);
386 
387 	/*
388 	 * No need to allocate an mbuf cluster submap.  Mbuf clusters
389 	 * are allocated via the pool allocator, and we use direct-mapped
390 	 * pool pages.
391 	 */
392 
393 	format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
394 	printf("avail memory = %s\n", pbuf);
395 	format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG);
396 	printf("using %u buffers containing %s of memory\n", nbuf, pbuf);
397 
398 	/*
399 	 * Set up the buffers.
400 	 */
401 	bufinit();
402 
403 	/*
404 	 * Set up the board properties database.
405 	 */
406 	if (!(board_info = propdb_create("board info")))
407 		panic("Cannot create board info database");
408 
409 	if (board_info_set("processor-frequency", &cpuspeed,
410 	    sizeof(&cpuspeed), PROP_CONST, 0))
411 		panic("setting processor-frequency");
412 	if (board_info_set("mem-size", &memsize,
413 	    sizeof(&memsize), PROP_CONST, 0))
414 		panic("setting mem-size");
415 }
416 
417 int
418 lcsplx(int ipl)
419 {
420 	return spllower(ipl);	/*XXX*/
421 }
422 
423 void
424 softnet(void)
425 {
426 	int isr;
427 
428 	isr = netisr;
429 	netisr = 0;
430 
431 #define DONETISR(bit, fn)		\
432 	do {				\
433 		if (isr & (1 << bit))	\
434 		fn();			\
435 	} while (0)
436 
437 #include <net/netisr_dispatch.h>
438 
439 #undef DONETISR
440 }
441 
442 #include "com.h"
443 void
444 softserial(void)
445 {
446 #if NCOM > 0
447 	void comsoft(void);	/* XXX from dev/ic/com.c */
448 
449 	comsoft();
450 #endif
451 }
452 
453 void
454 cpu_reboot(int howto, char *what)
455 {
456 	static int syncing = 0;
457 
458 	boothowto = howto;
459 	if (!cold && !(howto & RB_NOSYNC) && !syncing) {
460 		syncing = 1;
461 		vfs_shutdown();
462 		resettodr();
463 	}
464 
465 	splhigh();
466 
467 	if (!cold && (howto & RB_DUMP))
468 		/*XXX dumpsys()*/;
469 
470 	doshutdownhooks();
471 
472 	if (howto & RB_HALT) {
473 		printf("halted\n\n");
474 
475 		while (1)
476 			;
477 	}
478 
479 	printf("rebooting\n\n");
480 
481 	/* flush cache for msgbuf */
482 	__syncicache((void *)msgbuf_paddr, round_page(MSGBUFSIZE));
483 
484 	ppc4xx_reset();
485 
486 #ifdef DDB
487 	while (1)
488 		Debugger();
489 #else
490 	while (1)
491 		;
492 #endif
493 }
494 
495 void
496 inittodr(time_t base)
497 {
498 	if (base > 365*24*60*60 && time.tv_sec < 365*24*60*60)
499 		time.tv_sec = base;
500 }
501 
502 void
503 resettodr(void)
504 {
505 }
506 
507 void
508 mem_regions(struct mem_region **mem, struct mem_region **avail)
509 {
510 	*mem = phys_mem;
511 	*avail = avail_mem;
512 }
513