xref: /netbsd/sys/arch/hpcsh/hpcsh/machdep.c (revision bf9ec67e)
1 /*	$NetBSD: machdep.c,v 1.38 2002/05/09 12:37:59 uch Exp $	*/
2 
3 /*-
4  * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *        This product includes software developed by the NetBSD
18  *        Foundation, Inc. and its contributors.
19  * 4. Neither the name of The NetBSD Foundation nor the names of its
20  *    contributors may be used to endorse or promote products derived
21  *    from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
24  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
27  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #include "opt_md.h"
37 #include "opt_ddb.h"
38 #include "opt_kgdb.h"
39 #include "fs_mfs.h"
40 #include "fs_nfs.h"
41 #include "biconsdev.h"
42 #include "opt_kloader_kernel_path.h"
43 #include "debug_hpc.h"
44 #include "hd64465if.h"
45 
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/kernel.h>
49 #include <sys/user.h>
50 
51 #include <sys/reboot.h>
52 #include <sys/mount.h>
53 #include <sys/sysctl.h>
54 #include <sys/kcore.h>
55 #include <sys/boot_flag.h>
56 
57 #include <ufs/mfs/mfs_extern.h>		/* mfs_initminiroot() */
58 
59 #include <sh3/cpu.h>
60 #include <sh3/exception.h>
61 #include <sh3/cache.h>
62 #include <sh3/clock.h>
63 #include <sh3/intcreg.h>
64 
65 #ifdef KGDB
66 #include <sys/kgdb.h>
67 #endif
68 #if defined(DDB) || defined(KGDB)
69 #include <machine/db_machdep.h>
70 #include <ddb/db_sym.h>
71 #include <ddb/db_extern.h>
72 #ifndef DB_ELFSIZE
73 #error Must define DB_ELFSIZE!
74 #endif
75 #define	ELFSIZE		DB_ELFSIZE
76 #include <sys/exec_elf.h>
77 #endif /* DDB || KGDB */
78 
79 #include <dev/cons.h> /* consdev */
80 #include <dev/md.h>
81 
82 #include <machine/bootinfo.h>
83 #include <machine/platid.h>
84 #include <machine/platid_mask.h>
85 #include <machine/autoconf.h>		/* makebootdev() */
86 #include <machine/kloader.h>
87 #include <machine/intr.h>
88 
89 #ifdef NFS
90 #include <nfs/rpcv2.h>
91 #include <nfs/nfsproto.h>
92 #include <nfs/nfs.h>
93 #include <nfs/nfsmount.h>
94 #endif
95 
96 #include <hpcsh/dev/hd6446x/hd6446xintcvar.h>
97 #include <hpcsh/dev/hd6446x/hd6446xintcreg.h>
98 #include <hpcsh/dev/hd64465/hd64465var.h>
99 
100 #ifdef DEBUG
101 #define	DPRINTF_ENABLE
102 #define	DPRINTF_DEBUG	machdep_debug
103 #endif /* DEBUG */
104 #include <machine/debug.h>
105 
106 /*
107  * D-RAM location (Windows CE machine specific)
108  *
109  * Jornada 690 (32MB model) SH7709A
110  *  + SH7709A split CS3 to 2 banks.
111  *
112  * CS3 (0x0c000000-0x0fffffff
113  * 0x0c000000 --- onboard   16MByte
114  * 0x0d000000 --- onboard   16MByte (shadow)
115  * 0x0e000000 --- extension 16MByte
116  * 0x0f000000 --- extension 16MByte (shadow)
117  *
118  * PERSONA HPW-650PA (16MB model) SH7750
119  * SH7750
120  *
121  * CS3 (0x0c000000-0x0fffffff
122  * 0x0c000000 --- onboard   16MByte
123  * 0x0d000000 --- onboard   16MByte (shadow)
124  * 0x0e000000 --- onboard   16MByte (shadow)
125  * 0x0f000000 --- onboard   16MByte (shadow)
126  */
127 
128 #define	SH_CS3_START			0x0c000000
129 #define	SH_CS3_END			(SH_CS3_START + 0x04000000)
130 
131 #define	SH7709_CS3_BANK0_START		0x0c000000
132 #define	SH7709_CS3_BANK0_END		(SH7709_CS3_BANK0_START + 0x02000000)
133 #define	SH7709_CS3_BANK1_START		0x0e000000
134 #define	SH7709_CS3_BANK1_END		(SH7709_CS3_BANK1_START + 0x02000000)
135 
136 /* Machine */
137 char machine[]		= MACHINE;
138 char machine_arch[]	= MACHINE_ARCH;
139 extern char cpu_model[];
140 struct bootinfo *bootinfo;
141 
142 /* Physical memory */
143 static int	mem_cluster_init(paddr_t);
144 static void	mem_cluster_load(void);
145 static void	__find_dram_shadow(paddr_t, paddr_t);
146 #ifdef NARLY_MEMORY_PROBE
147 static int	__check_dram(paddr_t, paddr_t);
148 #endif
149 int		mem_cluster_cnt;
150 phys_ram_seg_t	mem_clusters[VM_PHYSSEG_MAX];
151 
152 void main(void) __attribute__((__noreturn__));
153 void machine_startup(int, char *[], struct bootinfo *)
154 	__attribute__((__noreturn__));
155 
156 void
157 machine_startup(int argc, char *argv[], struct bootinfo *bi)
158 {
159 	extern char edata[], end[];
160 	vaddr_t kernend;
161 	size_t symbolsize;
162 	int i;
163 	char *p;
164 	/*
165 	 * this routines stack is never polluted since stack pointer
166 	 * is lower than kernel text segment, and at exiting, stack pointer
167 	 * is changed to proc0.
168 	 */
169 	struct kloader_bootinfo kbi;
170 
171 	/* Symbol table size */
172 	symbolsize = 0;
173 	if (memcmp(&end, ELFMAG, SELFMAG) == 0) {
174 		Elf_Ehdr *eh = (void *)end;
175 		Elf_Shdr *sh = (void *)(end + eh->e_shoff);
176 		for(i = 0; i < eh->e_shnum; i++, sh++)
177 			if (sh->sh_offset > 0 &&
178 			    (sh->sh_offset + sh->sh_size) > symbolsize)
179 				symbolsize = sh->sh_offset + sh->sh_size;
180 	}
181 
182 	/* Clear BSS */
183 	memset(edata, 0, end - edata);
184 
185 	/* Setup bootinfo */
186 	bootinfo = &kbi.bootinfo;
187 	memcpy(bootinfo, bi, sizeof(struct bootinfo));
188 	if (bootinfo->magic == BOOTINFO_MAGIC) {
189 		platid.dw.dw0 = bootinfo->platid_cpu;
190 		platid.dw.dw1 = bootinfo->platid_machine;
191 	}
192 
193 	/* CPU initialize */
194 	if (platid_match(&platid, &platid_mask_CPU_SH_3))
195 		sh_cpu_init(CPU_ARCH_SH3, CPU_PRODUCT_7709A);
196 	else if (platid_match(&platid, &platid_mask_CPU_SH_4))
197 		sh_cpu_init(CPU_ARCH_SH4, CPU_PRODUCT_7750);
198 
199 	/* Start to determine heap area */
200 	kernend = (vaddr_t)sh3_round_page(end + symbolsize);
201 
202 	/* Setup bootstrap options */
203 	makebootdev("wd0"); /* default boot device */
204 	boothowto = 0;
205 	for (i = 1; i < argc; i++) { /* skip 1st arg (kernel name). */
206 		char *cp = argv[i];
207 		switch (*cp) {
208 		case 'b':
209 			/* boot device: -b=sd0 etc. */
210 			p = cp + 2;
211 #ifdef NFS
212 			if (strcmp(p, "nfs") == 0)
213 				mountroot = nfs_mountroot;
214 			else
215 				makebootdev(p);
216 #else /* NFS */
217 			makebootdev(p);
218 #endif /* NFS */
219 			break;
220 		default:
221 			BOOT_FLAG(*cp, boothowto);
222 			break;
223 		}
224 	}
225 
226 #ifdef MFS
227 	/*
228 	 * Check to see if a mini-root was loaded into memory. It resides
229 	 * at the start of the next page just after the end of BSS.
230 	 */
231 	if (boothowto & RB_MINIROOT) {
232 		size_t fssz;
233 		fssz = sh3_round_page(mfs_initminiroot((void *)kernend));
234 #ifdef MEMORY_DISK_DYNAMIC
235 		md_root_setconf((caddr_t)kernend, fssz);
236 #endif
237 		kernend += fssz;
238 	}
239 #endif /* MFS */
240 
241 	/* Console */
242 	consinit();
243 #ifdef HPC_DEBUG_LCD
244 	dbg_lcd_test();
245 #endif
246 	/* copy boot parameter for kloader */
247 	kloader_bootinfo_set(&kbi, argc, argv, bi, TRUE);
248 
249 	/* Find memory cluster. and load to UVM */
250 	physmem = mem_cluster_init(SH3_P1SEG_TO_PHYS(kernend));
251 	_DPRINTF("total memory = %dMbyte\n", (int)(sh3_ptob(physmem) >> 20));
252 	mem_cluster_load();
253 
254 	/* Initialize proc0 u-area */
255 	sh_proc0_init();
256 
257 	/* Initialize pmap and start to address translation */
258 	pmap_bootstrap();
259 
260 	/* Debugger. */
261 #ifdef DDB
262 	if (symbolsize) {
263 		ddb_init(symbolsize, &end, end + symbolsize);
264 		_DPRINTF("symbol size = %d byte\n", symbolsize);
265 	}
266 	if (boothowto & RB_KDB)
267 		Debugger();
268 #endif /* DDB */
269 #ifdef KGDB
270 	if (boothowto & RB_KDB) {
271 		if (kgdb_dev == NODEV) {
272 			printf("no kgdb console.\n");
273 		} else {
274 			kgdb_debug_init = 1;
275 			kgdb_connect(1);
276 		}
277 	}
278 #endif /* KGDB */
279 
280 	/* Jump to main */
281 	__asm__ __volatile__(
282 		"jmp	@%0;"
283 		"mov	%1, sp"
284 		:: "r"(main),"r"(proc0.p_md.md_pcb->pcb_sf.sf_r7_bank));
285 	/* NOTREACHED */
286 	while (1)
287 		;
288 }
289 
290 void
291 cpu_startup()
292 {
293 	platid_t cpu;
294 	int cpuclock, pclock;
295 
296 	cpuclock = sh_clock_get_cpuclock();
297 	pclock = sh_clock_get_pclock();
298 
299 	sh_startup();
300 
301 	memcpy(&cpu, &platid, sizeof(platid_t));
302 	cpu.dw.dw1 = 0;	/* clear platform */
303 	sprintf(cpu_model, "[%s] %s", platid_name(&platid), platid_name(&cpu));
304 
305 #define	MHZ(x) ((x) / 1000000), (((x) % 1000000) / 1000)
306 	printf("%s %d.%02d MHz PCLOCK %d.%02d MHz\n", cpu_model,
307 	    MHZ(cpuclock), MHZ(pclock));
308 }
309 
310 int
311 cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
312     void *newp, size_t newlen, struct proc *p)
313 {
314 	/* all sysctl names at this level are terminal */
315 	if (namelen != 1)
316 		return (ENOTDIR);		/* overloaded */
317 
318 	switch (name[0]) {
319 	case CPU_CONSDEV:
320 		return (sysctl_rdstruct(oldp, oldlenp, newp, &cn_tab->cn_dev,
321 		    sizeof cn_tab->cn_dev));
322 	default:
323 	}
324 
325 	return (EOPNOTSUPP);
326 }
327 
328 void
329 cpu_reboot(int howto, char *bootstr)
330 {
331 
332 	/* take a snap shot before clobbering any registers */
333 	if (curproc)
334 		savectx(curpcb);
335 
336 	/* If system is cold, just halt. */
337 	if (cold) {
338 		howto |= RB_HALT;
339 		goto haltsys;
340 	}
341 
342 	/* If "always halt" was specified as a boot flag, obey. */
343 	if ((boothowto & RB_HALT) != 0) {
344 		howto |= RB_HALT;
345 	}
346 
347 #ifdef KLOADER_KERNEL_PATH
348 	if ((howto & RB_HALT) == 0)
349 		kloader_reboot_setup(KLOADER_KERNEL_PATH);
350 #endif
351 
352 	boothowto = howto;
353 	if ((howto & RB_NOSYNC) == 0) {
354 		/*
355 		 * Synchronize the disks....
356 		 */
357 		vfs_shutdown();
358 
359 		/*
360 		 * If we've been adjusting the clock, the todr
361 		 * will be out of synch; adjust it now.
362 		 */
363 		resettodr();
364 	}
365 
366 	/* Disable interrupts. */
367 	splhigh();
368 
369 	/* If rebooting and a dump is requested do it. */
370 #if notyet
371 	if (howto & RB_DUMP)
372 		dumpsys();
373 #endif
374 
375  haltsys:
376 	/* run any shutdown hooks */
377 	doshutdownhooks();
378 
379 	/* Finally, halt/reboot the system. */
380 	if (howto & RB_HALT) {
381 		printf("halted.\n");
382 	} else {
383 #ifdef KLOADER_KERNEL_PATH
384 		kloader_reboot();
385 		/* NOTREACHED */
386 #endif
387 	}
388 
389 #if NHD64465IF > 0
390 	hd64465_shutdown();
391 #endif
392 
393 	cpu_reset();
394 	/*NOTREACHED*/
395 	while(1)
396 		;
397 }
398 
399 /* return # of physical pages. */
400 int
401 mem_cluster_init(paddr_t addr)
402 {
403 	phys_ram_seg_t *seg;
404 	int npages, i;
405 
406 	/* cluster 0 is always kernel myself. */
407 	mem_clusters[0].start = SH_CS3_START;
408 	mem_clusters[0].size = addr - SH_CS3_START;
409 	mem_cluster_cnt = 1;
410 
411 	/* search CS3 */
412 #ifdef SH3
413 	/* SH7709A's CS3 is splited to 2 banks. */
414 	if (CPU_IS_SH3) {
415 		__find_dram_shadow(addr, SH7709_CS3_BANK0_END);
416 		__find_dram_shadow(SH7709_CS3_BANK1_START,
417 		    SH7709_CS3_BANK1_END);
418 	}
419 #endif
420 #ifdef SH4
421 	/* contig CS3 */
422 	if (CPU_IS_SH4) {
423 		__find_dram_shadow(addr, SH_CS3_END);
424 	}
425 #endif
426 	_DPRINTF("mem_cluster_cnt = %d\n", mem_cluster_cnt);
427 	npages = 0;
428 	for (i = 0, seg = mem_clusters; i < mem_cluster_cnt; i++, seg++) {
429 		_DPRINTF("mem_clusters[%d] = {0x%lx+0x%lx <0x%lx}", i,
430 		    (paddr_t)seg->start, (paddr_t)seg->size,
431 		    (paddr_t)seg->start + (paddr_t)seg->size);
432 		npages += sh3_btop(seg->size);
433 #ifdef NARLY_MEMORY_PROBE
434 		if (i == 0) {
435 			_DPRINTF(" don't check.\n");
436 			continue;
437 		}
438 		if (__check_dram((paddr_t)seg->start, (paddr_t)seg->start +
439 		    (paddr_t)seg->size) != 0)
440 			panic("D-RAM check failed.");
441 #else
442 		_DPRINTF("\n");
443 #endif /* NARLY_MEMORY_PROBE */
444 	}
445 
446 	return (npages);
447 }
448 
449 void
450 mem_cluster_load()
451 {
452 	paddr_t start, end;
453 	psize_t size;
454 	int i;
455 
456 	/* Cluster 0 is always the kernel, which doesn't get loaded. */
457 	sh_dcache_wbinv_all();
458 	for (i = 1; i < mem_cluster_cnt; i++) {
459 		start = (paddr_t)mem_clusters[i].start;
460 		size = (psize_t)mem_clusters[i].size;
461 
462 		_DPRINTF("loading 0x%lx,0x%lx\n", start, size);
463 		memset((void *)SH3_PHYS_TO_P1SEG(start), 0, size);
464 		end = atop(start + size);
465 		start = atop(start);
466 		uvm_page_physload(start, end, start, end, VM_FREELIST_DEFAULT);
467 	}
468 	sh_dcache_wbinv_all();
469 }
470 
471 void
472 __find_dram_shadow(paddr_t start, paddr_t end)
473 {
474 	vaddr_t page, startaddr, endaddr;
475 	int x;
476 
477 	_DPRINTF("search D-RAM from 0x%08lx for 0x%08lx\n", start, end);
478 	startaddr = SH3_PHYS_TO_P2SEG(start);
479 	endaddr = SH3_PHYS_TO_P2SEG(end);
480 
481 	page = startaddr;
482 
483 	x = random();
484 	*(volatile int *)(page + 0) = x;
485 	*(volatile int *)(page + 4) = ~x;
486 
487 	if (*(volatile int *)(page + 0) != x ||
488 	    *(volatile int *)(page + 4) != ~x)
489 		return;
490 
491 	for (page += NBPG; page < endaddr; page += NBPG) {
492 		if (*(volatile int *)(page + 0) == x &&
493 		    *(volatile int *)(page + 4) == ~x) {
494 			goto memend_found;
495 		}
496 	}
497 
498 	page -= NBPG;
499 	*(volatile int *)(page + 0) = x;
500 	*(volatile int *)(page + 4) = ~x;
501 
502 	if (*(volatile int *)(page + 0) != x ||
503 	    *(volatile int *)(page + 4) != ~x)
504 		return; /* no memory in this bank */
505 
506  memend_found:
507 	KASSERT(mem_cluster_cnt < VM_PHYSSEG_MAX);
508 
509 	mem_clusters[mem_cluster_cnt].start = start;
510 	mem_clusters[mem_cluster_cnt].size = page - startaddr;
511 
512 	/* skip kernel area */
513 	if (mem_cluster_cnt == 1)
514 		mem_clusters[1].size -= mem_clusters[0].size;
515 
516 	mem_cluster_cnt++;
517 }
518 
519 #ifdef NARLY_MEMORY_PROBE
520 int
521 __check_dram(paddr_t start, paddr_t end)
522 {
523 	u_int8_t *page;
524 	int i, x;
525 
526 	_DPRINTF(" checking...");
527 	for (; start < end; start += NBPG) {
528 		page = (u_int8_t *)SH3_PHYS_TO_P2SEG (start);
529 		x = random();
530 		for (i = 0; i < NBPG; i += 4)
531 			*(volatile int *)(page + i) = (x ^ i);
532 		for (i = 0; i < NBPG; i += 4)
533 			if (*(volatile int *)(page + i) != (x ^ i))
534 				goto bad;
535 		x = random();
536 		for (i = 0; i < NBPG; i += 4)
537 			*(volatile int *)(page + i) = (x ^ i);
538 		for (i = 0; i < NBPG; i += 4)
539 			if (*(volatile int *)(page + i) != (x ^ i))
540 				goto bad;
541 	}
542 	_DPRINTF("success.\n");
543 	return (0);
544  bad:
545 	_DPRINTF("failed.\n");
546 	return (1);
547 }
548 #endif /* NARLY_MEMORY_PROBE */
549 
550 void
551 intc_intr(int ssr, int spc, int ssp)
552 {
553 	struct intc_intrhand *ih;
554 	int evtcode;
555 	u_int16_t r;
556 
557 	evtcode = _reg_read_4(CPU_IS_SH3 ? SH7709_INTEVT2 : SH4_INTEVT);
558 
559 	ih = EVTCODE_IH(evtcode);
560 	KDASSERT(ih->ih_func);
561 	/*
562 	 * On entry, all interrrupts are disabled,
563 	 * and exception is enabled for P3 access. (kernel stack is P3,
564 	 * SH3 may or may not cause TLB miss when access stack.)
565 	 * Enable higher level interrupt here.
566 	 */
567 	r = _reg_read_2(HD6446X_NIRR);
568 
569 	splx(ih->ih_level);
570 
571 	if (evtcode == SH_INTEVT_TMU0_TUNI0) {
572 		struct clockframe cf;
573 		cf.spc = spc;
574 		cf.ssr = ssr;
575 		cf.ssp = ssp;
576 		(*ih->ih_func)(&cf);
577 		__dbg_heart_beat(HEART_BEAT_RED);
578 	} else if (evtcode ==
579 	    (CPU_IS_SH3 ? SH7709_INTEVT2_IRQ4 : SH_INTEVT_IRL11)) {
580 		int cause = r & hd6446x_ienable;
581 		struct hd6446x_intrhand *hh = &hd6446x_intrhand[ffs(cause) - 1];
582 		if (cause == 0) {
583 			printf("masked HD6446x interrupt.0x%04x\n", r);
584 			_reg_write_2(HD6446X_NIRR, 0x0000);
585 			return;
586 		}
587 		/* Enable higher level interrupt*/
588 		hd6446x_intr_resume(hh->hh_ipl);
589 		KDASSERT(hh->hh_func != NULL);
590 		(*hh->hh_func)(hh->hh_arg);
591 		__dbg_heart_beat(HEART_BEAT_GREEN);
592 	} else {
593 		(*ih->ih_func)(ih->ih_arg);
594 		__dbg_heart_beat(HEART_BEAT_BLUE);
595 	}
596 }
597 
598