xref: /netbsd-src/sys/arch/evbmips/alchemy/machdep.c (revision 4e6df137e8e14049b5a701d249962c480449c141)
1 /* $NetBSD: machdep.c,v 1.47 2010/02/08 19:02:27 joerg Exp $ */
2 
3 /*-
4  * Copyright (c) 2006 Itronix Inc.
5  * All rights reserved.
6  *
7  * Portions written by Garrett D'Amore for Itronix 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. The name of Itronix Inc. may not be used to endorse
18  *    or promote products derived from this software without specific
19  *    prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
25  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28  * ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 /*
34  * Copyright (c) 1992, 1993
35  *	The Regents of the University of California.  All rights reserved.
36  *
37  * This code is derived from software contributed to Berkeley by
38  * the Systems Programming Group of the University of Utah Computer
39  * Science Department, The Mach Operating System project at
40  * Carnegie-Mellon University and Ralph Campbell.
41  *
42  * Redistribution and use in source and binary forms, with or without
43  * modification, are permitted provided that the following conditions
44  * are met:
45  * 1. Redistributions of source code must retain the above copyright
46  *    notice, this list of conditions and the following disclaimer.
47  * 2. Redistributions in binary form must reproduce the above copyright
48  *    notice, this list of conditions and the following disclaimer in the
49  *    documentation and/or other materials provided with the distribution.
50  * 3. Neither the name of the University nor the names of its contributors
51  *    may be used to endorse or promote products derived from this software
52  *    without specific prior written permission.
53  *
54  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64  * SUCH DAMAGE.
65  *
66  *	@(#)machdep.c	8.3 (Berkeley) 1/12/94
67  * 	from: Utah Hdr: machdep.c 1.63 91/04/24
68  */
69 /*
70  * Copyright (c) 1988 University of Utah.
71  *
72  * This code is derived from software contributed to Berkeley by
73  * the Systems Programming Group of the University of Utah Computer
74  * Science Department, The Mach Operating System project at
75  * Carnegie-Mellon University and Ralph Campbell.
76  *
77  * Redistribution and use in source and binary forms, with or without
78  * modification, are permitted provided that the following conditions
79  * are met:
80  * 1. Redistributions of source code must retain the above copyright
81  *    notice, this list of conditions and the following disclaimer.
82  * 2. Redistributions in binary form must reproduce the above copyright
83  *    notice, this list of conditions and the following disclaimer in the
84  *    documentation and/or other materials provided with the distribution.
85  * 3. All advertising materials mentioning features or use of this software
86  *    must display the following acknowledgement:
87  *	This product includes software developed by the University of
88  *	California, Berkeley and its contributors.
89  * 4. Neither the name of the University nor the names of its contributors
90  *    may be used to endorse or promote products derived from this software
91  *    without specific prior written permission.
92  *
93  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
94  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
95  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
96  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
97  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
98  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
99  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
101  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
102  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
103  * SUCH DAMAGE.
104  *
105  *	@(#)machdep.c	8.3 (Berkeley) 1/12/94
106  * 	from: Utah Hdr: machdep.c 1.63 91/04/24
107  */
108 
109 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
110 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.47 2010/02/08 19:02:27 joerg Exp $");
111 
112 #include "opt_ddb.h"
113 #include "opt_kgdb.h"
114 
115 #include "opt_memsize.h"
116 #include "opt_modular.h"
117 #include "opt_ethaddr.h"
118 
119 #include <sys/param.h>
120 #include <sys/systm.h>
121 #include <sys/kernel.h>
122 #include <sys/buf.h>
123 #include <sys/reboot.h>
124 #include <sys/mount.h>
125 #include <sys/kcore.h>
126 #include <sys/boot_flag.h>
127 #include <sys/termios.h>
128 #include <sys/ksyms.h>
129 #include <sys/device.h>
130 
131 #include <net/if.h>
132 #include <net/if_ether.h>
133 
134 #include <uvm/uvm_extern.h>
135 
136 #include <dev/cons.h>
137 
138 #include "ksyms.h"
139 
140 #if NKSYMS || defined(DDB) || defined(MODULAR)
141 #include <machine/db_machdep.h>
142 #include <ddb/db_extern.h>
143 #endif
144 
145 #include <mips/cache.h>
146 #include <mips/locore.h>
147 #include <machine/yamon.h>
148 
149 #include <evbmips/alchemy/board.h>
150 #include <mips/alchemy/dev/aupcivar.h>
151 #include <mips/alchemy/dev/aupcmciavar.h>
152 #include <mips/alchemy/dev/auspivar.h>
153 #include <mips/alchemy/include/aureg.h>
154 #include <mips/alchemy/include/auvar.h>
155 #include <mips/alchemy/include/aubusvar.h>
156 
157 #include "com.h"
158 #if NCOM > 0
159 
160 int	aucomcnrate = 0;
161 #endif /* NAUCOM > 0 */
162 
163 #include "ohci.h"
164 
165 /* Our exported CPU info; we can have only one. */
166 struct cpu_info cpu_info_store;
167 
168 /* Maps for VM objects. */
169 struct vm_map *phys_map = NULL;
170 
171 int maxmem;			/* max memory per process */
172 
173 int mem_cluster_cnt;
174 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
175 
176 yamon_env_var *yamon_envp;
177 struct mips_bus_space alchemy_cpuregt;
178 
179 void	mach_init(int, char **, yamon_env_var *, u_long); /* XXX */
180 
181 void
182 mach_init(int argc, char **argv, yamon_env_var *envp, u_long memsize)
183 {
184 	bus_space_handle_t sh;
185 	void *kernend;
186 	const char *cp;
187 	u_long first, last;
188 	int freqok, howto, i;
189 	const struct alchemy_board *board;
190 
191 	extern char edata[], end[];	/* XXX */
192 
193 	board = board_info();
194 	KASSERT(board != NULL);
195 
196 	/* clear the BSS segment */
197 	kernend = (void *)mips_round_page(end);
198 	memset(edata, 0, (char *)kernend - edata);
199 
200 	/* set CPU model info for sysctl_hw */
201 	strcpy(cpu_model, board->ab_name);
202 
203 	/* save the yamon environment pointer */
204 	yamon_envp = envp;
205 
206 	/* Use YAMON callbacks for early console I/O */
207 	cn_tab = &yamon_promcd;
208 
209 	/*
210 	 * Set up the exception vectors and CPU-specific function
211 	 * vectors early on.  We need the wbflush() vector set up
212 	 * before comcnattach() is called (or at least before the
213 	 * first printf() after that is called).
214 	 * Sets up mips_cpu_flags that may be queried by other
215 	 * functions called during startup.
216 	 * Also clears the I+D caches.
217 	 */
218 	mips_vector_init();
219 
220 	/*
221 	 * Set the VM page size.
222 	 */
223 	uvm_setpagesize();
224 
225 	/*
226 	 * Use YAMON's CPU frequency if available.
227 	 */
228 	freqok = yamon_setcpufreq(1);
229 
230 	/*
231 	 * Initialize bus space tags.
232 	 */
233 	au_cpureg_bus_mem_init(&alchemy_cpuregt, &alchemy_cpuregt);
234 	aubus_st = &alchemy_cpuregt;
235 
236 	/*
237 	 * Calibrate the timer if YAMON failed to tell us.
238 	 */
239 	if (!freqok) {
240 		bus_space_map(aubus_st, PC_BASE, PC_SIZE, 0, &sh);
241 		au_cal_timers(aubus_st, sh);
242 		bus_space_unmap(aubus_st, sh, PC_SIZE);
243 	}
244 
245 	/*
246 	 * Perform board-specific initialization.
247 	 */
248 	board->ab_init();
249 
250 	/*
251 	 * Bring up the console.
252 	 */
253 #if NCOM > 0
254 #ifdef CONSPEED
255 	if (aucomcnrate == 0)
256 		aucomcnrate = CONSPEED;
257 #else /* !CONSPEED */
258 	/*
259 	 * Learn default console speed.  We use the YAMON environment,
260 	 * though we could probably also figure it out by checking the
261 	 * aucom registers directly.
262 	 */
263 	if ((aucomcnrate == 0) && ((cp = yamon_getenv("modetty0")) != NULL))
264 		aucomcnrate = strtoul(cp, NULL, 0);
265 
266 	if (aucomcnrate == 0) {
267 		printf("FATAL: `modetty0' YAMON variable not set.  Set it\n");
268 		printf("       to the speed of the console and try again.\n");
269 		printf("       Or, build a kernel with the `CONSPEED' "
270 		    "option.\n");
271 		panic("mach_init");
272 	}
273 #endif /* CONSPEED */
274 
275 	/*
276 	 * Delay to allow firmware putchars to complete.
277 	 * FIFO depth * character time.
278 	 * character time = (1000000 / (defaultrate / 10))
279 	 */
280 	delay(160000000 / aucomcnrate);
281 	if (com_aubus_cnattach(UART0_BASE, aucomcnrate) != 0)
282 		panic("mach_init: unable to initialize serial console");
283 
284 #else /* NCOM > 0 */
285 	panic("mach_init: not configured to use serial console");
286 #endif /* NAUCOM > 0 */
287 
288 	/*
289 	 * Look at arguments passed to us and compute boothowto.
290 	 */
291 	boothowto = RB_AUTOBOOT;
292 #ifdef KADB
293 	boothowto |= RB_KDB;
294 #endif
295 	for (i = 1; i < argc; i++) {
296 		for (cp = argv[i]; *cp; cp++) {
297 			/* Ignore superfluous '-', if there is one */
298 			if (*cp == '-')
299 				continue;
300 
301 			howto = 0;
302 			BOOT_FLAG(*cp, howto);
303 			if (! howto)
304 				printf("bootflag '%c' not recognised\n", *cp);
305 			else
306 				boothowto |= howto;
307 		}
308 	}
309 
310 	/*
311 	 * Determine the memory size.  Use the `memsize' PMON
312 	 * variable.  If that's not available, panic.
313 	 *
314 	 * Note: Reserve the first page!  That's where the trap
315 	 * vectors are located.
316 	 */
317 
318 #if defined(MEMSIZE)
319 	memsize = MEMSIZE;
320 #else
321 	if (memsize == 0) {
322 		if ((cp = yamon_getenv("memsize")) != NULL)
323 			memsize = strtoul(cp, NULL, 0);
324 		else {
325 			printf("FATAL: `memsize' YAMON variable not set.  Set it to\n");
326 			printf("       the amount of memory (in MB) and try again.\n");
327 			printf("       Or, build a kernel with the `MEMSIZE' "
328 			    "option.\n");
329 			panic("mach_init");
330 		}
331 	}
332 #endif /* MEMSIZE */
333 	printf("Memory size: 0x%08lx\n", memsize);
334 	physmem = btoc(memsize);
335 
336 	mem_clusters[mem_cluster_cnt].start = PAGE_SIZE;
337 	mem_clusters[mem_cluster_cnt].size =
338 	    memsize - mem_clusters[mem_cluster_cnt].start;
339 	mem_cluster_cnt++;
340 
341 	/*
342 	 * Load the rest of the available pages into the VM system.
343 	 */
344 	first = round_page(MIPS_KSEG0_TO_PHYS(kernend));
345 	last = mem_clusters[0].start + mem_clusters[0].size;
346 	uvm_page_physload(atop(first), atop(last), atop(first), atop(last),
347 	    VM_FREELIST_DEFAULT);
348 
349 	/*
350 	 * Initialize message buffer (at end of core).
351 	 */
352 	mips_init_msgbuf();
353 
354 	/*
355 	 * Initialize the virtual memory system.
356 	 */
357 	pmap_bootstrap();
358 
359 	/*
360 	 * Allocate uarea page for lwp0 and set it.
361 	 */
362 	mips_init_lwp0_uarea();
363 
364 	/*
365 	 * Initialize debuggers, and break into them, if appropriate.
366 	 */
367 #ifdef DDB
368 	if (boothowto & RB_KDB)
369 		Debugger();
370 #endif
371 }
372 
373 void
374 consinit(void)
375 {
376 
377 	/*
378 	 * Everything related to console initialization is done
379 	 * in mach_init().
380 	 */
381 }
382 
383 void
384 cpu_startup(void)
385 {
386 	char pbuf[9];
387 	vaddr_t minaddr, maxaddr;
388 #ifdef DEBUG
389 	extern int pmapdebug;		/* XXX */
390 	int opmapdebug = pmapdebug;
391 
392 	pmapdebug = 0;		/* Shut up pmap debug during bootstrap */
393 #endif
394 
395 	/*
396 	 * Good {morning,afternoon,evening,night}.
397 	 */
398 	printf("%s%s", copyright, version);
399 	printf("%s\n", cpu_model);
400 	format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
401 	printf("total memory = %s\n", pbuf);
402 
403 	minaddr = 0;
404 
405 	/*
406 	 * Allocate a submap for physio
407 	 */
408 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
409 	    VM_PHYS_SIZE, 0, false, NULL);
410 
411 	/*
412 	 * No need to allocate an mbuf cluster submap.  Mbuf clusters
413 	 * are allocated via the pool allocator, and we use KSEG to
414 	 * map those pages.
415 	 */
416 
417 #ifdef DEBUG
418 	pmapdebug = opmapdebug;
419 #endif
420 	format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
421 	printf("avail memory = %s\n", pbuf);
422 }
423 
424 void
425 cpu_reboot(int howto, char *bootstr)
426 {
427 	static int waittime = -1;
428 	const struct alchemy_board *board;
429 
430 	/* Take a snapshot before clobbering any registers. */
431 	if (curproc)
432 		savectx(curpcb);
433 
434 	board = board_info();
435 	KASSERT(board != NULL);
436 
437 	/* If "always halt" was specified as a boot flag, obey. */
438 	if (boothowto & RB_HALT)
439 		howto |= RB_HALT;
440 
441 	boothowto = howto;
442 
443 	/* If system is cold, just halt. */
444 	if (cold) {
445 		boothowto |= RB_HALT;
446 		goto haltsys;
447 	}
448 
449 	if ((boothowto & RB_NOSYNC) == 0 && waittime < 0) {
450 		waittime = 0;
451 
452 		/*
453 		 * Synchronize the disks....
454 		 */
455 		vfs_shutdown();
456 
457 		/*
458 		 * If we've been adjusting the clock, the todr
459 		 * will be out of synch; adjust it now.
460 		 */
461 		resettodr();
462 	}
463 
464 	/* Disable interrupts. */
465 	splhigh();
466 
467 	if (boothowto & RB_DUMP)
468 		dumpsys();
469 
470  haltsys:
471 	/* Run any shutdown hooks. */
472 	doshutdownhooks();
473 
474 	pmf_system_shutdown(boothowto);
475 
476 	if ((boothowto & RB_POWERDOWN) == RB_POWERDOWN)
477 		if (board && board->ab_poweroff)
478 			board->ab_poweroff();
479 
480 	/*
481 	 * YAMON may autoboot (depending on settings), and we cannot pass
482 	 * flags to it (at least I haven't figured out how to yet), so
483 	 * we "pseudo-halt" now.
484 	 */
485 	if (boothowto & RB_HALT) {
486 		printf("\n");
487 		printf("The operating system has halted.\n");
488 		printf("Please press any key to reboot.\n\n");
489 		cnpollc(1);	/* For proper keyboard command handling */
490 		cngetc();
491 		cnpollc(0);
492 	}
493 
494 	printf("reseting board...\n\n");
495 
496 	/*
497 	 * Try to use board-specific reset logic, which might involve a better
498 	 * hardware reset.
499 	 */
500 	if (board->ab_reboot)
501 		board->ab_reboot();
502 
503 #if 1
504 	/* XXX
505 	 * For some reason we are leaving the ethernet MAC in a state where
506 	 * YAMON isn't happy with it.  So just call the reset vector (grr,
507 	 * Alchemy YAMON doesn't have a "reset" command).
508 	 */
509 	mips_icache_sync_all();
510 	mips_dcache_wbinv_all();
511 	__asm volatile("jr	%0" :: "r"(MIPS_RESET_EXC_VEC));
512 #else
513 	printf("%s\n\n", ((howto & RB_HALT) != 0) ? "halted." : "rebooting...");
514 	yamon_exit(boothowto);
515 	printf("Oops, back from yamon_exit()\n\nSpinning...");
516 #endif
517 	for (;;)
518 		/* spin forever */ ;	/* XXX */
519 	/*NOTREACHED*/
520 }
521 
522 /*
523  * Export our interrupt map function so aupci can find it.
524  */
525 int
526 aupci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
527 {
528 	const struct alchemy_board *board;
529 
530 	board = board_info();
531 	if (board->ab_pci_intr_map != NULL)
532 		return (board->ab_pci_intr_map(pa, ihp));
533 	return 1;
534 }
535 
536 struct aupcmcia_machdep *
537 aupcmcia_machdep(void)
538 {
539 	const struct alchemy_board *board;
540 
541 	board = board_info();
542 	return (board->ab_pcmcia);
543 }
544 
545 const struct auspi_machdep *
546 auspi_machdep(bus_addr_t ba)
547 {
548 	const struct alchemy_board *board;
549 
550 	board = board_info();
551 	if (board->ab_spi != NULL)
552 		return (board->ab_spi(ba));
553 	return NULL;
554 }
555