1/*	$NetBSD: machdep.c,v 1.61 2012/01/14 19:39:25 phx Exp $	*/
2
3/*
4 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5 * Copyright (C) 1995, 1996 TooLs GmbH.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by TooLs GmbH.
19 * 4. The name of TooLs GmbH may not be used to endorse or promote products
20 *    derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.61 2012/01/14 19:39:25 phx Exp $");
36
37#include "opt_compat_netbsd.h"
38#include "opt_ddb.h"
39#include "opt_ipkdb.h"
40#include "opt_interrupt.h"
41#include "opt_modular.h"
42
43#include <sys/param.h>
44#include <sys/buf.h>
45#include <sys/bus.h>
46#include <sys/conf.h>
47#include <sys/device.h>
48#include <sys/exec.h>
49#include <sys/extent.h>
50#include <sys/intr.h>
51#include <sys/kernel.h>
52#include <sys/ksyms.h>
53#include <sys/malloc.h>
54#include <sys/mbuf.h>
55#include <sys/module.h>
56#include <sys/mount.h>
57#include <sys/msgbuf.h>
58#include <sys/proc.h>
59#include <sys/reboot.h>
60#include <sys/syscallargs.h>
61#include <sys/sysctl.h>
62#include <sys/syslog.h>
63#include <sys/systm.h>
64
65#include <uvm/uvm_extern.h>
66
67#include <machine/powerpc.h>
68#include <machine/bootinfo.h>
69
70#include <powerpc/pmap.h>
71#include <powerpc/trap.h>
72
73#include <powerpc/oea/bat.h>
74#include <powerpc/openpic.h>
75#include <powerpc/pic/picvar.h>
76
77#ifdef DDB
78#include <powerpc/db_machdep.h>
79#include <ddb/db_extern.h>
80#endif
81
82#include <dev/cons.h>
83#include <sys/termios.h>
84
85#include "com.h"
86#if (NCOM > 0)
87#include <dev/ic/comreg.h>
88#include <dev/ic/comvar.h>
89#endif
90
91#include "com_eumb.h"
92#if (NCOM_EUMB > 0)
93#include <sandpoint/sandpoint/eumbvar.h>
94#endif
95
96#include "pcib.h"
97#include "ksyms.h"
98
99char bootinfo[BOOTINFO_MAXSIZE];
100void (*md_reboot)(int);
101
102void initppc(u_int, u_int, u_int, void *);
103void consinit(void);
104void sandpoint_bus_space_init(void);
105size_t mpc107memsize(void);
106
107/* we support single chunk of memory */
108struct mem_region physmemr[2], availmemr[2];
109
110paddr_t avail_end;
111struct pic_ops *isa_pic = NULL;
112extern int primary_pic;
113
114#if NKSYMS || defined(DDB) || defined(MODULAR)
115extern void *startsym, *endsym;
116#endif
117
118#if 1
119extern struct consdev kcomcons;
120#endif
121
122void
123initppc(u_int startkernel, u_int endkernel, u_int args, void *btinfo)
124{
125	extern u_long ticks_per_sec, ns_per_tick;
126	struct btinfo_magic *bi_magic = btinfo;
127	struct btinfo_memory *meminfo;
128	struct btinfo_clock *clockinfo;
129	size_t memsize;
130	u_long ticks;
131
132	if ((unsigned)btinfo != 0 && (unsigned)btinfo < startkernel
133	    && bi_magic->magic == BOOTINFO_MAGIC)
134		memcpy(bootinfo, btinfo, sizeof(bootinfo));
135	else
136		args = RB_SINGLE;	/* boot via S-record loader */
137
138	meminfo = lookup_bootinfo(BTINFO_MEMORY);
139	if (meminfo)
140		memsize = meminfo->memsize & ~PGOFSET;
141	else
142		memsize = mpc107memsize();
143	physmemr[0].start = 0;
144	physmemr[0].size = memsize;
145	physmemr[1].size = 0;
146	availmemr[0].start = (endkernel + PGOFSET) & ~PGOFSET;
147	availmemr[0].size = memsize - availmemr[0].start;
148	availmemr[1].size = 0;
149	avail_end = physmemr[0].start + physmemr[0].size; /* XXX */
150
151	clockinfo = lookup_bootinfo(BTINFO_CLOCK);
152	if (clockinfo)
153		ticks = clockinfo->ticks_per_sec;
154	else {
155		ticks = 1000000000;	/* 100 MHz */
156		ticks /= 4;		/* 4 cycles per DEC tick */
157	}
158	ticks_per_sec = ticks;
159	ns_per_tick = 1000000000 / ticks_per_sec;
160
161	/*
162	 * boothowto
163	 */
164	boothowto = args;
165
166	/*
167	 * Now setup fixed bat registers
168	 * We setup a pair of BAT to have "Map B" layout, one for the
169	 * PCI memory space, another to cover many; MPC107/MPC824x EUMB,
170	 * ISA mem, PCI/ISA I/O, PCI configuration, PCI interrupt
171	 * acknowledge and flash/ROM space.
172	 */
173	oea_batinit(
174	    0x80000000, BAT_BL_256M,	/* SANDPOINT_BUS_SPACE_MEM */
175	    0xfc000000, BAT_BL_64M,	/* _EUMB|_IO */
176	    0x70000000, BAT_BL_8M,	/* only for NH230 board control */
177	    0);
178
179	/* Install vectors and interrupt handler */
180	oea_init(NULL);
181
182#if 1 /* bumpy ride in pre-dawn time, for people knows what he/she is doing */
183	cn_tab = &kcomcons;
184	(*cn_tab->cn_init)(&kcomcons);
185
186#if NKSYMS || defined(DDB) || defined(MODULAR)
187	ksyms_addsyms_elf((int)((u_int)endsym - (u_int)startsym), startsym, endsym);
188#endif
189#ifdef DDB
190	if (boothowto & RB_KDB)
191		Debugger();
192#endif
193#endif
194
195	/* Initialize bus_space */
196	sandpoint_bus_space_init();
197
198	/* Initialize the console */
199	consinit();
200
201	/* Set the page size */
202	uvm_setpagesize();
203
204	/* Initialize pmap module */
205	pmap_bootstrap(startkernel, endkernel);
206
207#if 0 /* NKSYMS || defined(DDB) || defined(MODULAR) */
208	ksyms_addsyms_elf((int)((u_int)endsym - (u_int)startsym), startsym, endsym);
209#endif
210#ifdef IPKDB
211	/*
212	 * Now trap to IPKDB
213	 */
214	ipkdb_init();
215	if (boothowto & RB_KDB)
216		ipkdb_connect(0);
217#endif
218}
219
220void
221mem_regions(struct mem_region **mem, struct mem_region **avail)
222{
223
224	*mem = physmemr;
225	*avail = availmemr;
226}
227
228/*
229 * Machine dependent startup code.
230 */
231void
232cpu_startup(void)
233{
234	struct btinfo_prodfamily *bi_prod;
235	void *baseaddr;
236	int msr;
237
238	/*
239	 * Do common startup.
240	 */
241	bi_prod = lookup_bootinfo(BTINFO_PRODFAMILY);
242	oea_startup(bi_prod != NULL ? bi_prod->name : NULL);
243
244	/*
245	 * Prepare EPIC and install external interrupt handler.
246	 *  0..15	used by South bridge i8259 PIC if exists.
247	 *  16..39/41	EPIC interrupts, 24 source or 26 source.
248	 */
249	baseaddr = (void *)(SANDPOINT_BUS_SPACE_EUMB + 0x40000);
250	pic_init();
251
252#ifdef PIC_I8259
253	isa_pic = setup_i8259();
254	(void)setup_mpcpic(baseaddr);
255	primary_pic = 1;
256	/*
257	 * set up i8259 as a cascade on EPIC irq 0.
258	 * XXX exceptional SP2 has 17
259	 */
260	intr_establish(16, IST_LEVEL, IPL_NONE, pic_handle_intr, isa_pic);
261#else
262	mpcpic_reserv16();
263	(void)setup_mpcpic(baseaddr);
264	primary_pic = 0;
265#endif
266
267	oea_install_extint(pic_ext_intr);
268
269	/*
270	 * Now that we have VM, malloc()s are OK in bus_space.
271	 */
272	bus_space_mallocok();
273
274	/*
275	 * Now allow hardware interrupts.
276	 */
277	splraise(-1);
278	__asm volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0"
279	    :	"=r"(msr)
280	    :	"K"(PSL_EE));
281}
282
283#if (NPCIB > 0)
284struct btinfo_console bi_cons = { { 0, 0 },  "com", 0x3f8, 38400 };
285#else
286struct btinfo_console bi_cons = { { 0, 0 },  "eumb", 0x4600, 57600 };
287#endif
288
289/*
290 * lookup_bootinfo:
291 * Look up information in bootinfo of boot loader.
292 */
293void *
294lookup_bootinfo(int type)
295{
296	struct btinfo_common *bt;
297	struct btinfo_common *help = (struct btinfo_common *)bootinfo;
298
299	if (help->next == 0)
300		return (NULL);	/* bootinfo[] was not made */
301	do {
302		bt = help;
303		if (bt->type == type)
304			return (help);
305		help = (struct btinfo_common *)((char*)help + bt->next);
306	} while (bt->next &&
307		(size_t)help < (size_t)bootinfo + BOOTINFO_MAXSIZE);
308
309	return (NULL);
310}
311
312/*
313 * consinit
314 * Initialize system console.
315 */
316void
317consinit(void)
318{
319	struct btinfo_console *bi;
320	static int initted;
321
322	if (initted)
323		return;
324	initted = 1;
325
326	bi = lookup_bootinfo(BTINFO_CONSOLE);
327	if (bi == NULL)
328		bi = &bi_cons;
329
330#if (NCOM > 0)
331	if (strcmp(bi->devname, "com") == 0) {
332		bus_space_tag_t tag = &genppc_isa_io_space_tag;
333		if (comcnattach(tag, bi->addr, bi->speed,
334		    COM_FREQ, COM_TYPE_NORMAL,
335		    ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8)))
336			panic("can't init com serial console");
337		return;
338	}
339#endif
340#if (NCOM_EUMB > 0)
341	if (strcmp(bi->devname, "eumb") == 0) {
342		bus_space_tag_t tag = &sandpoint_eumb_space_tag;
343		extern u_long ticks_per_sec;
344
345		if (eumbcnattach(tag, bi->addr, bi->speed,
346		    4 * ticks_per_sec, COM_TYPE_NORMAL,
347		    ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8)))
348			panic("can't init eumb serial console");
349		return;
350	}
351#endif
352	panic("console device missing -- serial console not in kernel");
353	/* Of course, this is moot if there is no console... */
354}
355
356/*
357 * Halt or reboot the machine after syncing/dumping according to howto.
358 */
359void
360cpu_reboot(int howto, char *what)
361{
362	extern void jump_to_ppc_reset_entry(void);	/* from locore.S */
363	static int syncing;
364	register_t msr;
365
366	boothowto = howto;
367	if ((howto & RB_NOSYNC) == 0 && syncing == 0) {
368		syncing = 1;
369		vfs_shutdown();		/* sync */
370		resettodr();		/* set wall clock */
371	}
372
373	/* Disable intr */
374	/* splhigh(); */
375
376	/* Do dump if requested */
377	if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP)
378		oea_dumpsys();
379
380	doshutdownhooks();
381
382	pmf_system_shutdown(boothowto);
383
384	if ((howto & RB_POWERDOWN) == RB_HALT) {
385		printf("\n");
386		printf("The operating system has halted.\n");
387		printf("Please press any key to reboot.\n\n");
388		cnpollc(1);	/* for proper keyboard command handling */
389		cngetc();
390		cnpollc(0);
391		howto = RB_AUTOBOOT;
392	}
393
394	if (md_reboot != NULL)
395		(*md_reboot)(howto);
396
397	/*
398	 * No reboot method defined. So we disable the MMU and jump
399	 * through the firmware's reset vector.
400	 */
401	msr = mfmsr();
402	msr &= ~PSL_EE;
403	mtmsr(msr);
404	__asm volatile("mtspr %0,%1" : : "K"(81), "r"(0));
405	msr &= ~(PSL_ME | PSL_DR | PSL_IR);
406	mtmsr(msr);
407	jump_to_ppc_reset_entry();
408	for (;;);
409}
410
411#ifdef MODULAR
412void
413module_init_md(void)
414{
415        struct btinfo_modulelist *module;
416	struct bi_modulelist_entry *bi, *biend;
417
418        module = lookup_bootinfo(BTINFO_MODULELIST);
419        if (module == NULL)
420		return;
421	bi = (struct bi_modulelist_entry *)(module + 1);
422	biend = bi + module->num;
423	while (bi < biend) {
424		printf("module %s at 0x%08x size %x\n",
425		    bi->kmod, bi->base, bi->len);
426		/* module_prime(bi->kmod, (void *)bi->base, bi->len); */
427		bi += 1;
428	}
429}
430#endif /* MODULAR */
431
432struct powerpc_bus_space sandpoint_io_space_tag = {
433	_BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_IO_TYPE,
434	0xfe000000, 0x00000000, 0x00c00000,
435};
436struct powerpc_bus_space genppc_isa_io_space_tag = {
437	_BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_IO_TYPE,
438	0xfe000000, 0x00000000, 0x00010000,
439};
440struct powerpc_bus_space sandpoint_mem_space_tag = {
441	_BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE,
442	0x00000000, 0x80000000, 0xfc000000,
443};
444struct powerpc_bus_space genppc_isa_mem_space_tag = {
445	_BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE,
446	0x00000000, 0xfd000000, 0xfe000000,
447};
448struct powerpc_bus_space sandpoint_eumb_space_tag = {
449	_BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE,
450	0xfc000000, 0x00000000, 0x00100000,
451};
452struct powerpc_bus_space sandpoint_flash_space_tag = {
453	_BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE,
454	0x00000000, 0xff000000, 0x00000000,
455};
456struct powerpc_bus_space sandpoint_nhgpio_space_tag = {
457	_BUS_SPACE_BIG_ENDIAN|_BUS_SPACE_MEM_TYPE,
458	0x70000000, 0x00000000, 0x00001000,
459};
460
461static char ex_storage[7][EXTENT_FIXED_STORAGE_SIZE(8)]
462    __attribute__((aligned(8)));
463
464void
465sandpoint_bus_space_init(void)
466{
467	int error;
468
469	error = bus_space_init(&sandpoint_io_space_tag, "ioport",
470	    ex_storage[0], sizeof(ex_storage[0]));
471	if (error)
472		panic("sandpoint_bus_space_init: can't init io tag");
473
474	error = extent_alloc_region(sandpoint_io_space_tag.pbs_extent,
475	    0x10000, 0x7fffff, EX_NOWAIT);
476	if (error)
477		panic("sandpoint_bus_space_init: can't block out reserved I/O"
478		    " space 0x10000-0x7fffff: error=%d", error);
479
480	error = bus_space_init(&sandpoint_mem_space_tag, "iomem",
481	    ex_storage[1], sizeof(ex_storage[1]));
482	if (error)
483		panic("sandpoint_bus_space_init: can't init mem tag");
484
485	error = bus_space_init(&genppc_isa_io_space_tag, "isa-ioport",
486	    ex_storage[2], sizeof(ex_storage[2]));
487	if (error)
488		panic("sandpoint_bus_space_init: can't init isa io tag");
489
490	error = bus_space_init(&genppc_isa_mem_space_tag, "isa-iomem",
491	    ex_storage[3], sizeof(ex_storage[3]));
492	if (error)
493		panic("sandpoint_bus_space_init: can't init isa mem tag");
494
495	error = bus_space_init(&sandpoint_eumb_space_tag, "eumb",
496	    ex_storage[4], sizeof(ex_storage[4]));
497	if (error)
498		panic("sandpoint_bus_space_init: can't init eumb tag");
499
500	error = bus_space_init(&sandpoint_flash_space_tag, "flash",
501	    ex_storage[5], sizeof(ex_storage[5]));
502	if (error)
503		panic("sandpoint_bus_space_init: can't init flash tag");
504
505	/* NH230/231 only: extended ROM space at 0x70000000 for GPIO */
506	error = bus_space_init(&sandpoint_nhgpio_space_tag, "nh23x-gpio",
507	    ex_storage[6], sizeof(ex_storage[6]));
508	if (error)
509		panic("sandpoint_bus_space_init: can't init nhgpio tag");
510}
511
512#define MPC107_EUMBBAR		0x78	/* Eumb base address */
513#define MPC107_MEMENDADDR1	0x90	/* Memory ending address 1 */
514#define MPC107_EXTMEMENDADDR1	0x98	/* Extd. memory ending address 1 */
515#define MPC107_MEMEN		0xa0	/* Memory enable */
516
517size_t
518mpc107memsize(void)
519{
520	/*
521	 * assumptions here;
522	 * - first 4 sets of SDRAM controlling register have been
523	 * set right in the ascending order.
524	 * - total SDRAM size is the last valid SDRAM address +1.
525	 */
526	unsigned val, n, bankn, end;
527
528	out32rb(0xfec00000, (1U<<31) | MPC107_MEMEN);
529	val = in32rb(0xfee00000);
530	if ((val & 0xf) == 0)
531		return 32 * 1024 * 1024; /* eeh? */
532
533	bankn = 0;
534	for (n = 0; n < 4; n++) {
535		if ((val & (1U << n)) == 0)
536			break;
537		bankn = n;
538	}
539	bankn = bankn * 8;
540
541	/* the format is "00 xx xxxxxxxx << 20" */
542	out32rb(0xfec00000, (1U<<31) | MPC107_EXTMEMENDADDR1); /* bit 29:28 */
543	val = in32rb(0xfee00000);
544	end =  ((val >> bankn) & 0x03) << 28;
545	out32rb(0xfec00000, (1U<<31) | MPC107_MEMENDADDR1);    /* bit 27:20 */
546	val = in32rb(0xfee00000);
547	end |= ((val >> bankn) & 0xff) << 20;
548	end |= 0xfffff;					       /* bit 19:00 */
549
550	return (end + 1); /* recognize this as the amount of SDRAM */
551}
552
553/* XXX XXX debug purpose only XXX XXX */
554
555static dev_type_cninit(kcomcninit);
556static dev_type_cngetc(kcomcngetc);
557static dev_type_cnputc(kcomcnputc);
558static dev_type_cnpollc(kcomcnpollc);
559
560struct consdev kcomcons = {
561	NULL, kcomcninit, kcomcngetc, kcomcnputc, kcomcnpollc, NULL,
562	NULL, NULL, NODEV, CN_NORMAL
563};
564
565#define THR		0
566#define RBR		0
567#define LSR		5
568#define LSR_THRE	0x20
569#define UART_READ(r)		*(volatile char *)(uartbase + (r))
570#define UART_WRITE(r, v)	*(volatile char *)(uartbase + (r)) = (v)
571#define LSR_RFE		0x80
572#define LSR_TXEMPTY		0x20
573#define LSR_BE			0x10
574#define LSR_FE			0x08
575#define LSR_PE			0x04
576#define LSR_OE			0x02
577#define LSR_RXREADY		0x01
578#define LSR_ANYE		(LSR_OE|LSR_PE|LSR_FE|LSR_BE)
579
580static unsigned uartbase = 0xfe0003f8;
581
582static void
583kcomcninit(struct consdev *cn)
584{
585	struct btinfo_console *bi = lookup_bootinfo(BTINFO_CONSOLE);
586
587	if (bi == NULL)
588		bi = &bi_cons;
589	if (strcmp(bi->devname, "com") == 0)
590		uartbase = 0xfe000000 + bi->addr;
591	else if (strcmp(bi->devname, "eumb") == 0)
592		uartbase = 0xfc000000 + bi->addr;
593	/*
594	 * we do not touch UART operating parameters since bootloader
595	 * is supposed to have done well.
596	 */
597}
598
599static int
600kcomcngetc(dev_t dev)
601{
602	unsigned lsr;
603	int s, c;
604
605	s = splserial();
606#if 1
607	do {
608		lsr = UART_READ(LSR);
609	} while ((lsr & LSR_ANYE) || (lsr & LSR_RXREADY) == 0);
610#else
611    again:
612	do {
613		lsr = UART_READ(LSR);
614	} while ((lsr & LSR_RXREADY) == 0);
615	if (lsr & (LSR_BE | LSR_FE | LSR_PE)) {
616		(void)UART_READ(RBR);
617		goto again;
618	}
619#endif
620	c = UART_READ(RBR);
621	splx(s);
622	return c & 0xff;
623}
624
625static void
626kcomcnputc(dev_t dev, int c)
627{
628	unsigned lsr, timo;
629	int s;
630
631	s = splserial();
632	timo = 150000;
633	do {
634		lsr = UART_READ(LSR);
635	} while (timo-- > 0 && (lsr & LSR_TXEMPTY) == 0);
636	if (timo > 0)
637		UART_WRITE(THR, c);
638	splx(s);
639}
640
641static void
642kcomcnpollc(dev_t dev, int on)
643{
644}
645
646SYSCTL_SETUP(sysctl_machdep_prodfamily, "sysctl machdep prodfamily")
647{
648	const struct sysctlnode *mnode, *node;
649	struct btinfo_prodfamily *pfam;
650
651	pfam = lookup_bootinfo(BTINFO_PRODFAMILY);
652	if (pfam != NULL) {
653		sysctl_createv(NULL, 0, NULL, &mnode,
654		    CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL,
655		    NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL);
656
657		sysctl_createv(NULL, 0, &mnode, &node,
658		    CTLFLAG_PERMANENT, CTLTYPE_STRING, "prodfamily",
659		    SYSCTL_DESCR("Board family name."),
660		    NULL, 0, pfam->name, 0,
661		    CTL_CREATE, CTL_EOL);
662	}
663}
664