xref: /netbsd-src/sys/arch/evbarm/mini2440/mini2440_machdep.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*-
2  * Copyright (c) 2012 The NetBSD Foundation, Inc.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to The NetBSD Foundation
6  * by Paul Fleischer <paul@xpg.dk>
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  *
17  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 /* This file is based on arch/evbarm/smdk2xx0/smdk2410_machdep.c */
30 /*
31  * Copyright (c) 2002, 2003 Fujitsu Component Limited
32  * Copyright (c) 2002, 2003, 2005 Genetec Corporation
33  * All rights reserved.
34  *
35  * Redistribution and use in source and binary forms, with or without
36  * modification, are permitted provided that the following conditions
37  * are met:
38  * 1. Redistributions of source code must retain the above copyright
39  *    notice, this list of conditions and the following disclaimer.
40  * 2. Redistributions in binary form must reproduce the above copyright
41  *    notice, this list of conditions and the following disclaimer in the
42  *    documentation and/or other materials provided with the distribution.
43  * 3. Neither the name of The Fujitsu Component Limited nor the name of
44  *    Genetec corporation may not be used to endorse or promote products
45  *    derived from this software without specific prior written permission.
46  *
47  * THIS SOFTWARE IS PROVIDED BY FUJITSU COMPONENT LIMITED AND GENETEC
48  * CORPORATION ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
49  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
50  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
51  * DISCLAIMED.  IN NO EVENT SHALL FUJITSU COMPONENT LIMITED OR GENETEC
52  * CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
53  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
54  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
55  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
56  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
57  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
58  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59  * SUCH DAMAGE.
60  */
61 /*
62  * Copyright (c) 2001,2002 ARM Ltd
63  * All rights reserved.
64  *
65  * Redistribution and use in source and binary forms, with or without
66  * modification, are permitted provided that the following conditions
67  * are met:
68  * 1. Redistributions of source code must retain the above copyright
69  *    notice, this list of conditions and the following disclaimer.
70  * 2. Redistributions in binary form must reproduce the above copyright
71  *    notice, this list of conditions and the following disclaimer in the
72  *    documentation and/or other materials provided with the distribution.
73  * 3. The name of the company may not be used to endorse or promote
74  *    products derived from this software without specific prior written
75  *    permission.
76  *
77  * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND
78  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
79  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
80  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ARM LTD
81  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
82  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
83  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
84  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
85  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
86  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
87  * POSSIBILITY OF SUCH DAMAGE.
88  *
89  */
90 
91 /*
92  * Copyright (c) 1997,1998 Mark Brinicombe.
93  * Copyright (c) 1997,1998 Causality Limited.
94  * All rights reserved.
95  *
96  * Redistribution and use in source and binary forms, with or without
97  * modification, are permitted provided that the following conditions
98  * are met:
99  * 1. Redistributions of source code must retain the above copyright
100  *    notice, this list of conditions and the following disclaimer.
101  * 2. Redistributions in binary form must reproduce the above copyright
102  *    notice, this list of conditions and the following disclaimer in the
103  *    documentation and/or other materials provided with the distribution.
104  * 3. All advertising materials mentioning features or use of this software
105  *    must display the following acknowledgement:
106  *	This product includes software developed by Mark Brinicombe
107  *	for the NetBSD Project.
108  * 4. The name of the company nor the name of the author may be used to
109  *    endorse or promote products derived from this software without specific
110  *    prior written permission.
111  *
112  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
113  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
114  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
115  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
116  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
117  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
118  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
119  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
120  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
121  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
122  * SUCH DAMAGE.
123  *
124  * Machine dependant functions for kernel setup for integrator board
125  *
126  * Created      : 24/11/97
127  */
128 
129 /*
130  * Machine dependant functions for kernel setup for FriendlyARM MINI2440
131  */
132 
133 #include <sys/cdefs.h>
134 __KERNEL_RCSID(0, "$NetBSD: mini2440_machdep.c,v 1.8 2014/03/14 21:39:48 matt Exp $");
135 
136 #include "opt_ddb.h"
137 #include "opt_kgdb.h"
138 #include "opt_pmap_debug.h"
139 #include "opt_md.h"
140 
141 #include <sys/param.h>
142 #include <sys/device.h>
143 #include <sys/systm.h>
144 #include <sys/kernel.h>
145 #include <sys/exec.h>
146 #include <sys/proc.h>
147 #include <sys/msgbuf.h>
148 #include <sys/reboot.h>
149 #include <sys/termios.h>
150 #include <sys/ksyms.h>
151 #include <sys/mount.h>
152 
153 #include <net/if.h>
154 #include <net/if_ether.h>
155 #include <net/if_media.h>
156 
157 #include <uvm/uvm_extern.h>
158 
159 #include <dev/cons.h>
160 #include <dev/md.h>
161 
162 #include <machine/db_machdep.h>
163 #include <ddb/db_sym.h>
164 #include <ddb/db_extern.h>
165 #ifdef KGDB
166 #include <sys/kgdb.h>
167 #endif
168 
169 #include <sys/exec_elf.h>
170 
171 #include <sys/bus.h>
172 #include <machine/cpu.h>
173 #include <machine/frame.h>
174 #include <machine/intr.h>
175 #include <arm/undefined.h>
176 
177 #include <machine/autoconf.h>
178 
179 #include <arm/locore.h>
180 #include <arm/arm32/machdep.h>
181 
182 #include <arm/s3c2xx0/s3c2440reg.h>
183 #include <arm/s3c2xx0/s3c2440var.h>
184 
185 #include <arch/evbarm/mini2440/mini2440_bootinfo.h>
186 
187 #include "ksyms.h"
188 
189 #ifndef	SDRAM_START
190 #define	SDRAM_START	S3C2440_SDRAM_START
191 #endif
192 #ifndef	SDRAM_SIZE
193 #define	SDRAM_SIZE	(64*1024*1024) /* 64 Mb */
194 #endif
195 
196 /*
197  * Address to map I/O registers in early initialize stage.
198  */
199 #define MINI2440_IO_VBASE	0xfd000000
200 
201 /* Kernel text starts 2MB in from the bottom of the kernel address space. */
202 #define KERNEL_OFFSET		0x00200000
203 #define	KERNEL_TEXT_BASE	(KERNEL_BASE + KERNEL_OFFSET)
204 #define	KERNEL_VM_BASE		(KERNEL_BASE + 0x01000000)
205 
206 /*
207  * The range 0xc1000000 - 0xccffffff is available for kernel VM space
208  * Core-logic registers and I/O mappings occupy 0xfd000000 - 0xffffffff
209  */
210 #define KERNEL_VM_SIZE		0x0C000000
211 
212 /* Declared extern elsewhere in the kernel */
213 BootConfig bootconfig;		/* Boot config storage */
214 char *boot_args = NULL;
215 //char *boot_file = NULL;
216 
217 char bootinfo[BOOTINFO_MAXSIZE];
218 struct btinfo_rootdevice 	*bi_rdev;
219 struct btinfo_net		*bi_net;
220 struct btinfo_bootpath		*bi_path;
221 
222 vm_offset_t physical_start;
223 vm_offset_t physical_freestart;
224 vm_offset_t physical_freeend;
225 vm_offset_t physical_freeend_low;
226 vm_offset_t physical_end;
227 u_int free_pages;
228 vm_offset_t pagetables_start;
229 
230 /*int debug_flags;*/
231 #ifndef PMAP_STATIC_L1S
232 int max_processes = 64;		/* Default number */
233 #endif				/* !PMAP_STATIC_L1S */
234 
235 vm_offset_t msgbufphys;
236 
237 #ifdef PMAP_DEBUG
238 extern int pmap_debug_level;
239 #endif
240 
241 #define KERNEL_PT_SYS		0	/* L2 table for mapping zero page */
242 #define KERNEL_PT_KERNEL	1	/* L2 table for mapping kernel */
243 #define KERNEL_PT_KERNEL_NUM	3	/* L2 tables for mapping kernel VM */
244 
245 #define KERNEL_PT_VMDATA	(KERNEL_PT_KERNEL + KERNEL_PT_KERNEL_NUM)
246 
247 #define KERNEL_PT_VMDATA_NUM	4	/* start with 16MB of KVM */
248 #define NUM_KERNEL_PTS		(KERNEL_PT_VMDATA + KERNEL_PT_VMDATA_NUM)
249 
250 pv_addr_t kernel_pt_table[NUM_KERNEL_PTS];
251 
252 /* Prototypes */
253 
254 void consinit(void);
255 void kgdb_port_init(void);
256 static void mini2440_ksyms(struct btinfo_symtab *bi_symtab);
257 static void *lookup_bootinfo(int type);
258 static void mini2440_device_register(device_t dev, void *aux);
259 
260 
261 #include "com.h"
262 #if NCOM > 0
263 #include <dev/ic/comreg.h>
264 #include <dev/ic/comvar.h>
265 #endif
266 
267 #include "sscom.h"
268 #if NSSCOM > 0
269 #include "opt_sscom.h"
270 #include <arm/s3c2xx0/sscom_var.h>
271 #endif
272 
273 /*
274  * Define the default console speed for the board.  This is generally
275  * what the firmware provided with the board defaults to.
276  */
277 #ifndef CONSPEED
278 #define CONSPEED B115200	/* TTYDEF_SPEED */
279 #endif
280 #ifndef CONMODE
281 #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8)   /* 8N1 */
282 #endif
283 
284 int comcnspeed = CONSPEED;
285 int comcnmode = CONMODE;
286 
287 /*
288  * void cpu_reboot(int howto, char *bootstr)
289  *
290  * Reboots the system
291  *
292  * Deal with any syncing, unmounting, dumping and shutdown hooks,
293  * then reset the CPU.
294  */
295 void
296 cpu_reboot(int howto, char *bootstr)
297 {
298 #ifdef DIAGNOSTIC
299 	/* info */
300 	printf("boot: howto=%08x curproc=%p\n", howto, curproc);
301 #endif
302 
303 	cpu_reset_address_paddr = vtophys((uintptr_t)s3c2440_softreset);
304 
305 	/*
306 	 * If we are still cold then hit the air brakes
307 	 * and crash to earth fast
308 	 */
309 	if (cold) {
310 		doshutdownhooks();
311 		printf("The operating system has halted.\n");
312 		printf("Please press any key to reboot.\n\n");
313 		cngetc();
314 		printf("rebooting...\n");
315 		cpu_reset();
316 		/* NOTREACHED */
317 	}
318 	/* Disable console buffering */
319 
320 	/*
321 	 * If RB_NOSYNC was not specified sync the discs.
322 	 * Note: Unless cold is set to 1 here, syslogd will die during the
323 	 * unmount.  It looks like syslogd is getting woken up only to find
324 	 * that it cannot page part of the binary in as the filesystem has
325 	 * been unmounted.
326 	 */
327 	if (!(howto & RB_NOSYNC))
328 		bootsync();
329 
330 	/* Say NO to interrupts */
331 	splhigh();
332 
333 	/* Do a dump if requested. */
334 	if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP)
335 		dumpsys();
336 
337 	/* Run any shutdown hooks */
338 	doshutdownhooks();
339 
340 	/* Make sure IRQ's are disabled */
341 	IRQdisable;
342 
343 	if (howto & RB_HALT) {
344 		printf("The operating system has halted.\n");
345 		printf("Please press any key to reboot.\n\n");
346 		cngetc();
347 	}
348 	printf("rebooting...\n");
349 	cpu_reset();
350 	/* NOTREACHED */
351 }
352 
353 /*
354  * Static device mappings. These peripheral registers are mapped at
355  * fixed virtual addresses very early in initarm() so that we can use
356  * them while booting the kernel , and stay at the same address
357  * throughout whole kernel's life time.
358  *
359  * We use this table twice; once with bootstrap page table, and once
360  * with kernel's page table which we build up in initarm().
361  *
362  * Since we map these registers into the bootstrap page table using
363  * pmap_devmap_bootstrap() which calls pmap_map_chunk(), we map
364  * registers segment-aligned and segment-rounded in order to avoid
365  * using the 2nd page tables.
366  */
367 
368 #define	_A(a)	((a) & ~L1_S_OFFSET)
369 #define	_S(s)	(((s) + L1_S_SIZE - 1) & ~(L1_S_SIZE-1))
370 
371 #define	_V(n)	(MINI2440_IO_VBASE + (n) * L1_S_SIZE)
372 
373 #define	GPIO_VBASE	_V(0)
374 #define	INTCTL_VBASE	_V(1)
375 #define	CLKMAN_VBASE	_V(2)
376 #define	UART_VBASE	_V(3)
377 
378 static const struct pmap_devmap mini2440_devmap[] = {
379 	/* GPIO registers */
380 	{
381 		GPIO_VBASE,
382 		_A(S3C2440_GPIO_BASE),
383 		_S(S3C2440_GPIO_SIZE),
384 		VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE,
385 	},
386 	{
387 		INTCTL_VBASE,
388 		_A(S3C2440_INTCTL_BASE),
389 		_S(S3C2440_INTCTL_SIZE),
390 		VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE,
391 	},
392 	{
393 		CLKMAN_VBASE,
394 		_A(S3C2440_CLKMAN_BASE),
395 		_S(S3C24X0_CLKMAN_SIZE),
396 		VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE,
397 	},
398 	{	/* UART registers for UART0, 1, 2. */
399 		UART_VBASE,
400 		_A(S3C2440_UART0_BASE),
401 		_S(S3C2440_UART_BASE(3) - S3C2440_UART0_BASE),
402 		VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE,
403 	},
404 
405 	{ 0, 0, 0, 0 }
406 };
407 
408 #undef	_A
409 #undef	_S
410 
411 static inline	pd_entry_t *
412 read_ttb(void)
413 {
414 	long ttb;
415 
416 	__asm volatile("mrc	p15, 0, %0, c2, c0, 0" : "=r"(ttb));
417 
418 
419 	return (pd_entry_t *)(ttb & ~((1 << 14) - 1));
420 }
421 
422 
423 #define	ioreg_write32(a,v)  	(*(volatile uint32_t *)(a)=(v))
424 
425 /*
426  * u_int initarm(...)
427  *
428  * Initial entry point on startup. This gets called before main() is
429  * entered.
430  * It should be responsible for setting up everything that must be
431  * in place when main is called.
432  * This includes
433  *   Taking a copy of the boot configuration structure.
434  *   Initialising the physical console so characters can be printed.
435  *   Setting up page tables for the kernel
436  *   Relocating the kernel to the bottom of physical memory
437  */
438 
439 u_int
440 initarm(void *arg)
441 {
442 	int loop;
443 	int loop1;
444 	u_int l1pagetable;
445 	extern int etext __asm("_etext");
446 	extern int end __asm("_end");
447 	uint32_t kerneldatasize;
448 	struct btinfo_magic *bi_magic = arg;
449 	struct btinfo_bootstring *bi_bootstring;
450 	struct btinfo_symtab *bi_symtab;
451 
452 	boothowto = 0;
453 
454 	/* Copy bootinfo from boot loader into kernel memory where it remains.
455 	 */
456 	if (bi_magic != 0x0 && bi_magic->magic == BOOTINFO_MAGIC) {
457 		memcpy(bootinfo, bi_magic, sizeof(bootinfo));
458 	} else {
459 		memset(bootinfo, 0, sizeof(bootinfo));
460 	}
461 
462 	/* Extract boot_args from bootinfo */
463 	bi_bootstring = lookup_bootinfo(BTINFO_BOOTSTRING);
464 	if (bi_bootstring ) {
465 		printf("Bootloader args are %s\n", bi_bootstring->bootstring);
466 		boot_args = bi_bootstring->bootstring;
467 		parse_mi_bootargs(boot_args);
468 	}
469 
470 #define pdatb (*(volatile uint8_t *)(S3C2440_GPIO_BASE+GPIO_PBDAT))
471 
472 // 0x1E0 is the mask for GPB5, GPB6, GPB7, and GPB8
473 #define __LED(x)  (pdatb = (pdatb & ~0x1e0) | (~(1<<(x+5)) & 0x1e0))
474 
475 	__LED(0);
476 
477 	/*
478 	 * Heads up ... Setup the CPU / MMU / TLB functions
479 	 */
480 	if (set_cpufuncs())
481 		panic("cpu not recognized!");
482 
483 	/*
484 	 * Map I/O registers that are used in startup.  Now we are
485 	 * still using page table prepared by bootloader.  Later we'll
486 	 * map those registers at the same address in the kernel page
487 	 * table.
488 	 */
489 	pmap_devmap_bootstrap((vaddr_t)read_ttb(), mini2440_devmap);
490 
491 #undef	pdatb
492 #define pdatb (*(volatile uint8_t *)(GPIO_VBASE+GPIO_PBDAT))
493 
494 	/* Disable all peripheral interrupts */
495 	ioreg_write32(INTCTL_VBASE + INTCTL_INTMSK, ~0);
496 
497 	__LED(1);
498 
499 	/* initialize some variables so that splfoo() doesn't
500 	   touch illegal address.  */
501 	s3c2xx0_intr_bootstrap(INTCTL_VBASE);
502 
503 	__LED(2);
504 	consinit();
505 	__LED(3);
506 
507 	/* Extract information from the bootloader configuration */
508 	bi_rdev = lookup_bootinfo(BTINFO_ROOTDEVICE);
509 	bi_net = lookup_bootinfo(BTINFO_NET);
510 	bi_path = lookup_bootinfo(BTINFO_BOOTPATH);
511 
512 #ifdef VERBOSE_INIT_ARM
513 	printf("consinit done\n");
514 #endif
515 
516 #ifdef KGDB
517 	kgdb_port_init();
518 #endif
519 
520 #ifdef VERBOSE_INIT_ARM
521 	/* Talk to the user */
522 	printf("\nNetBSD/evbarm (MINI2440) booting ...\n");
523 #endif
524 	/*
525 	 * Ok we have the following memory map
526 	 *
527 	 * Physical Address Range     Description
528 	 * -----------------------    ----------------------------------
529 	 * 0x30000000 - 0x33ffffff    SDRAM (64MB)
530          *
531          * Kernel is loaded by bootloader at 0x30200000
532 	 *
533 	 * The initarm() has the responsibility for creating the kernel
534 	 * page tables.
535 	 * It must also set up various memory pointers that are used
536 	 * by pmap etc.
537 	 */
538 
539 	/* Fake bootconfig structure for the benefit of pmap.c */
540 	/* XXX must make the memory description h/w independent */
541 	bootconfig.dramblocks = 1;
542 	bootconfig.dram[0].address = SDRAM_START;
543 	bootconfig.dram[0].pages = SDRAM_SIZE / PAGE_SIZE;
544 
545 	/*
546 	 * Set up the variables that define the availablilty of
547 	 * physical memory.
548          * We use the 2MB between the physical start and the kernel to
549          * begin with. Allocating from 0x30200000 and downwards
550 	 * If we get too close to the bottom of SDRAM, we
551 	 * will panic.  We will update physical_freestart and
552 	 * physical_freeend later to reflect what pmap_bootstrap()
553 	 * wants to see.
554 	 *
555 	 * XXX pmap_bootstrap() needs an enema.
556 	 */
557 	physical_start = bootconfig.dram[0].address;
558 	physical_end = physical_start + (bootconfig.dram[0].pages * PAGE_SIZE);
559 
560 	physical_freestart = SDRAM_START;	/* XXX */
561 	physical_freeend = SDRAM_START + KERNEL_OFFSET;
562 
563 	physmem = (physical_end - physical_start) / PAGE_SIZE;
564 
565 #ifdef VERBOSE_INIT_ARM
566 	/* Tell the user about the memory */
567 	printf("physmemory: %d pages at 0x%08lx -> 0x%08lx\n", physmem,
568 	    physical_start, physical_end - 1);
569 	printf("phys_end: 0x%08lx\n", physical_end);
570 #endif
571 
572 	/*
573 	 * XXX
574 	 * Okay, the kernel starts 2MB in from the bottom of physical
575 	 * memory.  We are going to allocate our bootstrap pages downwards
576 	 * from there.
577 	 *
578 	 * We need to allocate some fixed page tables to get the kernel
579 	 * going.  We allocate one page directory and a number of page
580 	 * tables and store the physical addresses in the kernel_pt_table
581 	 * array.
582 	 *
583 	 * The kernel page directory must be on a 16K boundary.  The page
584 	 * tables must be on 4K boundaries.  What we do is allocate the
585 	 * page directory on the first 16K boundary that we encounter, and
586 	 * the page tables on 4K boundaries otherwise.  Since we allocate
587 	 * at least 3 L2 page tables, we are guaranteed to encounter at
588 	 * least one 16K aligned region.
589 	 */
590 
591 #ifdef VERBOSE_INIT_ARM
592 	printf("Allocating page tables\n");
593 #endif
594 
595 	free_pages = (physical_freeend - physical_freestart) / PAGE_SIZE;
596 
597 #ifdef VERBOSE_INIT_ARM
598 	printf("freestart = 0x%08lx, free_pages = %d (0x%08x), freeend = 0x%08lx\n",
599 	    physical_freestart, free_pages, free_pages, physical_freeend);
600 #endif
601 
602 	/* Define a macro to simplify memory allocation */
603 #define	valloc_pages(var, np)				\
604 	alloc_pages((var).pv_pa, (np));			\
605 	(var).pv_va = KERNEL_BASE + (var).pv_pa - physical_start;
606 
607 #define alloc_pages(var, np)				\
608 	physical_freeend -= ((np) * PAGE_SIZE);		\
609 	if (physical_freeend < physical_freestart)	\
610 		panic("initarm: out of memory");	\
611 	(var) = physical_freeend;			\
612 	free_pages -= (np);				\
613 	memset((char *)(var), 0, ((np) * PAGE_SIZE));
614 
615 	loop1 = 0;
616 	for (loop = 0; loop <= NUM_KERNEL_PTS; ++loop) {
617 		/* Are we 16KB aligned for an L1 ? */
618 		if (((physical_freeend - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) == 0
619 		    && kernel_l1pt.pv_pa == 0) {
620 			valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
621 		} else {
622 			valloc_pages(kernel_pt_table[loop1],
623 			    L2_TABLE_SIZE / PAGE_SIZE);
624 			++loop1;
625 		}
626 	}
627 
628 	/* This should never be able to happen but better confirm that. */
629 	if (!kernel_l1pt.pv_pa || (kernel_l1pt.pv_pa & (L1_TABLE_SIZE - 1)) != 0)
630 		panic("initarm: Failed to align the kernel page directory\n");
631 
632 	/*
633 	 * Allocate a page for the system page mapped to V0x00000000
634 	 * This page will just contain the system vectors and can be
635 	 * shared by all processes.
636 	 */
637 	alloc_pages(systempage.pv_pa, 1);
638 
639 	/* Allocate stacks for all modes */
640 	valloc_pages(irqstack, IRQ_STACK_SIZE);
641 	valloc_pages(abtstack, ABT_STACK_SIZE);
642 	valloc_pages(undstack, UND_STACK_SIZE);
643 	valloc_pages(kernelstack, UPAGES);
644 
645 #ifdef VERBOSE_INIT_ARM
646 	printf("IRQ stack: p0x%08lx v0x%08lx\n", irqstack.pv_pa,
647 	    irqstack.pv_va);
648 	printf("ABT stack: p0x%08lx v0x%08lx\n", abtstack.pv_pa,
649 	    abtstack.pv_va);
650 	printf("UND stack: p0x%08lx v0x%08lx\n", undstack.pv_pa,
651 	    undstack.pv_va);
652 	printf("SVC stack: p0x%08lx v0x%08lx\n", kernelstack.pv_pa,
653 	    kernelstack.pv_va);
654 	printf("Free memory in bootstrap region: %ld bytes\n", physical_freeend - physical_freestart);
655 #endif
656 
657 	alloc_pages(msgbufphys, round_page(MSGBUFSIZE) / PAGE_SIZE);
658 
659 	physical_freeend_low = physical_freeend;
660 
661 	/*
662 	 * Ok we have allocated physical pages for the primary kernel
663 	 * page tables
664 	 */
665 
666 #ifdef VERBOSE_INIT_ARM
667 	printf("Creating L1 page table at 0x%08lx\n", kernel_l1pt.pv_pa);
668 #endif
669 
670 	/*
671 	 * Now we start construction of the L1 page table
672 	 * We start by mapping the L2 page tables into the L1.
673 	 * This means that we can replace L1 mappings later on if necessary
674 	 */
675 	l1pagetable = kernel_l1pt.pv_pa;
676 
677 	/* Map the L2 pages tables in the L1 page table */
678 	pmap_link_l2pt(l1pagetable, 0x00000000,
679 	    &kernel_pt_table[KERNEL_PT_SYS]);
680 	for (loop = 0; loop < KERNEL_PT_KERNEL_NUM; loop++)
681 		pmap_link_l2pt(l1pagetable, KERNEL_BASE + loop * 0x00400000,
682 		    &kernel_pt_table[KERNEL_PT_KERNEL + loop]);
683 	for (loop = 0; loop < KERNEL_PT_VMDATA_NUM; loop++)
684 		pmap_link_l2pt(l1pagetable, KERNEL_VM_BASE + loop * 0x00400000,
685 		    &kernel_pt_table[KERNEL_PT_VMDATA + loop]);
686 
687 	/* update the top of the kernel VM */
688 	pmap_curmaxkvaddr =
689 	    KERNEL_VM_BASE + (KERNEL_PT_VMDATA_NUM * 0x00400000);
690 
691 #ifdef VERBOSE_INIT_ARM
692 	printf("Mapping kernel\n");
693 #endif
694 
695 	/* Now we fill in the L2 pagetable for the kernel static code/data */
696 	{
697 		/* Total size must include symbol table, if it exists.
698 		   The size of the symbol table can be acquired from the ELF
699 		   header, to which a pointer is passed in the boot info (ssym).
700 		 */
701 		size_t textsize = (uintptr_t)&etext - KERNEL_TEXT_BASE;
702 		kerneldatasize = (uintptr_t)&end - KERNEL_TEXT_BASE;
703 		u_int logical;
704 
705 		bi_symtab = lookup_bootinfo(BTINFO_SYMTAB);
706 
707 		if (bi_symtab) {
708 			Elf_Ehdr *elfHeader;
709 			Elf_Shdr *sectionHeader;
710 			int nsection;
711 			int sz = 0;
712 
713 			elfHeader = bi_symtab->ssym;
714 
715 #ifdef VERBOSE_INIT_ARM
716 			printf("Symbol table information provided by bootloader\n");
717 			printf("ELF header is at %p\n", elfHeader);
718 #endif
719 			sectionHeader = (Elf_Shdr*)((char*)(bi_symtab->ssym) +
720 						     (elfHeader->e_shoff));
721 			nsection = elfHeader->e_shnum;
722 #ifdef VERBOSE_INIT_ARM
723 			printf("Number of sections: %d\n", nsection);
724 #endif
725 			for(; nsection > 0; nsection--, sectionHeader++) {
726 				if (sectionHeader->sh_offset > 0 &&
727 				    (sectionHeader->sh_offset + sectionHeader->sh_size) > sz)
728 					sz = sectionHeader->sh_offset + sectionHeader->sh_size;
729 			}
730 #ifdef VERBOSE_INIT_ARM
731 			printf("Max size of sections: %d\n", sz);
732 #endif
733 			kerneldatasize += sz;
734 		}
735 
736 #ifdef VERBOSE_INIT_ARM
737 		printf("Textsize: %u, kerneldatasize: %u\n", (uint)textsize,
738 		       (uint)kerneldatasize);
739 		printf("&etext: 0x%x\n", (uint)&etext);
740 		printf("&end: 0x%x\n", (uint)&end);
741 		printf("KERNEL_TEXT_BASE: 0x%x\n", KERNEL_TEXT_BASE);
742 #endif
743 
744 		textsize = (textsize + PGOFSET) & ~PGOFSET;
745 		kerneldatasize = (kerneldatasize + PGOFSET) & ~PGOFSET;
746 
747 		logical = KERNEL_OFFSET;	/* offset of kernel in RAM */
748 
749 		logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical,
750 					  physical_start + logical, textsize,
751 					  VM_PROT_READ | VM_PROT_WRITE, PTE_CACHE);
752 		logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical,
753 					  physical_start + logical, kerneldatasize - textsize,
754 					  VM_PROT_READ | VM_PROT_WRITE, PTE_CACHE);
755 	}
756 
757 #ifdef VERBOSE_INIT_ARM
758 	printf("Constructing L2 page tables\n");
759 #endif
760 
761 	/* Map the stack pages */
762 	pmap_map_chunk(l1pagetable, irqstack.pv_va, irqstack.pv_pa,
763 	    IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE,
764 	    PTE_CACHE);
765 	pmap_map_chunk(l1pagetable, abtstack.pv_va, abtstack.pv_pa,
766 	    ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE,
767 	    PTE_CACHE);
768 	pmap_map_chunk(l1pagetable, undstack.pv_va, undstack.pv_pa,
769 	    UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE,
770 	    PTE_CACHE);
771 	pmap_map_chunk(l1pagetable, kernelstack.pv_va, kernelstack.pv_pa,
772 	    UPAGES * PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE, PTE_CACHE);
773 
774 	pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa,
775 	    L1_TABLE_SIZE, VM_PROT_READ | VM_PROT_WRITE, PTE_PAGETABLE);
776 
777 	for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) {
778 		pmap_map_chunk(l1pagetable, kernel_pt_table[loop].pv_va,
779 		    kernel_pt_table[loop].pv_pa, L2_TABLE_SIZE,
780 		    VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
781 	}
782 
783 	/* Map the vector page. */
784 #if 0
785 	/* MULTI-ICE requires that page 0 is NC/NB so that it can download the
786 	 * cache-clean code there.  */
787 	pmap_map_entry(l1pagetable, vector_page, systempage.pv_pa,
788 	    VM_PROT_READ | VM_PROT_WRITE, PTE_NOCACHE);
789 #else
790 	pmap_map_entry(l1pagetable, vector_page, systempage.pv_pa,
791 	    VM_PROT_READ | VM_PROT_WRITE, PTE_CACHE);
792 #endif
793 
794 	/*
795 	 * map integrated peripherals at same address in l1pagetable
796 	 * so that we can continue to use console.
797 	 */
798 	pmap_devmap_bootstrap(l1pagetable, mini2440_devmap);
799 
800 	/*
801 	 * Now we have the real page tables in place so we can switch to them.
802 	 * Once this is done we will be running with the REAL kernel page
803 	 * tables.
804 	 */
805 	/*
806 	 * Update the physical_freestart/physical_freeend/free_pages
807 	 * variables.
808 	 */
809 	physical_freestart = physical_start +
810 	  (KERNEL_TEXT_BASE - KERNEL_BASE) + kerneldatasize;
811 	physical_freeend = physical_end;
812 	free_pages =
813 	  (physical_freeend - physical_freestart) / PAGE_SIZE;
814 
815 	/* Switch tables */
816 #ifdef VERBOSE_INIT_ARM
817 	printf("freestart = 0x%08lx, free_pages = %d (0x%x)\n",
818 	    physical_freestart, free_pages, free_pages);
819 	printf("switching to new L1 page table  @%#lx...", kernel_l1pt.pv_pa);
820 #endif
821 	cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
822 	cpu_setttb(kernel_l1pt.pv_pa, true);
823 	cpu_tlb_flushID();
824 	cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
825 
826 	/*
827 	 * Moved from cpu_startup() as data_abort_handler() references
828 	 * this during uvm init
829 	 */
830 	uvm_lwp_setuarea(&lwp0, kernelstack.pv_va);
831 
832 #ifdef VERBOSE_INIT_ARM
833 	printf("done!\n");
834 #endif
835 
836 #ifdef VERBOSE_INIT_ARM
837 	printf("bootstrap done.\n");
838 #endif
839 
840 	arm32_vector_init(ARM_VECTORS_LOW, ARM_VEC_ALL);
841 
842 	/*
843 	 * Pages were allocated during the secondary bootstrap for the
844 	 * stacks for different CPU modes.
845 	 * We must now set the r13 registers in the different CPU modes to
846 	 * point to these stacks.
847 	 * Since the ARM stacks use STMFD etc. we must set r13 to the top end
848 	 * of the stack memory.
849 	 */
850 #ifdef VERBOSE_INIT_ARM
851 	printf("init subsystems: stacks ");
852 #endif
853 
854 	set_stackptr(PSR_IRQ32_MODE,
855 	    irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE);
856 	set_stackptr(PSR_ABT32_MODE,
857 	    abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE);
858 	set_stackptr(PSR_UND32_MODE,
859 	    undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE);
860 
861 	cpu_idcache_wbinv_all();
862 
863 	/*
864 	 * Well we should set a data abort handler.
865 	 * Once things get going this will change as we will need a proper
866 	 * handler.
867 	 * Until then we will use a handler that just panics but tells us
868 	 * why.
869 	 * Initialisation of the vectors will just panic on a data abort.
870 	 * This just fills in a slightly better one.
871 	 */
872 #ifdef VERBOSE_INIT_ARM
873 	printf("vectors ");
874 #endif
875 	data_abort_handler_address = (u_int)data_abort_handler;
876 	prefetch_abort_handler_address = (u_int)prefetch_abort_handler;
877 	undefined_handler_address = (u_int)undefinedinstruction_bounce;
878 
879 	/* Initialise the undefined instruction handlers */
880 #ifdef VERBOSE_INIT_ARM
881 	printf("undefined ");
882 #endif
883 	undefined_init();
884 
885 	/* Load memory into UVM. */
886 #ifdef VERBOSE_INIT_ARM
887 	printf("page ");
888 #endif
889 	uvm_setpagesize();	/* initialize PAGE_SIZE-dependent variables */
890 	uvm_page_physload(atop(physical_freestart), atop(physical_freeend),
891 	    atop(physical_freestart), atop(physical_freeend),
892 	    VM_FREELIST_DEFAULT);
893 	uvm_page_physload(atop(SDRAM_START), atop(physical_freeend_low),
894 	    atop(SDRAM_START), atop(physical_freeend_low),
895 	    VM_FREELIST_DEFAULT);
896 
897 
898 	/* Boot strap pmap telling it where the kernel page table is */
899 #ifdef VERBOSE_INIT_ARM
900 	printf("pmap ");
901 #endif
902 	pmap_bootstrap(KERNEL_VM_BASE, KERNEL_VM_BASE + KERNEL_VM_SIZE);
903 
904 #ifdef VERBOSE_INIT_ARM
905 	printf("done.\n");
906 #endif
907 
908 #ifdef BOOTHOWTO
909 	boothowto |= BOOTHOWTO;
910 #endif
911 
912 #ifdef KGDB
913 	if (boothowto & RB_KDB) {
914 		kgdb_debug_init = 1;
915 		kgdb_connect(1);
916 	}
917 #endif
918 
919 	mini2440_ksyms(bi_symtab);
920 
921 #ifdef DDB
922 	/*db_machine_init();*/
923 	if (boothowto & RB_KDB)
924 		Debugger();
925 #endif
926 
927 	evbarm_device_register = mini2440_device_register;
928 
929 	/* We return the new stack pointer address */
930 	return (kernelstack.pv_va + USPACE_SVC_STACK_TOP);
931 }
932 
933 void
934 consinit(void)
935 {
936 	static int consinit_done = 0;
937 #if defined(SSCOM0CONSOLE) || defined(SSCOM1CONSOLE)
938 	bus_space_tag_t iot = &s3c2xx0_bs_tag;
939 #endif
940 	int pclk;
941 
942 	if (consinit_done != 0)
943 		return;
944 
945 	consinit_done = 1;
946 
947 	s3c24x0_clock_freq2(CLKMAN_VBASE, NULL, NULL, &pclk);
948 
949 #if NSSCOM > 0
950 #ifdef SSCOM0CONSOLE
951 	if (0 == s3c2440_sscom_cnattach(iot, 0, comcnspeed,
952 		pclk, comcnmode))
953 		return;
954 #endif
955 #ifdef SSCOM1CONSOLE
956 	if (0 == s3c2440_sscom_cnattach(iot, 1, comcnspeed,
957 		pclk, comcnmode))
958 		return;
959 #endif
960 #endif				/* NSSCOM */
961 #if NCOM>0 && defined(CONCOMADDR)
962 	if (comcnattach(&isa_io_bs_tag, CONCOMADDR, comcnspeed,
963 		COM_FREQ, COM_TYPE_NORMAL, comcnmode))
964 		panic("can't init serial console @%x", CONCOMADDR);
965 	return;
966 #endif
967 
968 	consinit_done = 0;
969 }
970 
971 
972 #ifdef KGDB
973 
974 #if (NSSCOM > 0)
975 
976 #ifdef KGDB_DEVNAME
977 const char kgdb_devname[] = KGDB_DEVNAME;
978 #else
979 const char kgdb_devname[] = "";
980 #endif
981 
982 #ifndef KGDB_DEVMODE
983 #define KGDB_DEVMODE ((TTYDEF_CFLAG & ~(CSIZE|CSTOPB|PARENB))|CS8) /* 8N1 */
984 #endif
985 int kgdb_sscom_mode = KGDB_DEVMODE;
986 
987 #endif				/* NSSCOM */
988 
989 void
990 kgdb_port_init(void)
991 {
992 #if (NSSCOM > 0)
993 	int unit = -1;
994 	int pclk;
995 
996 	if (strcmp(kgdb_devname, "sscom0") == 0)
997 		unit = 0;
998 	else if (strcmp(kgdb_devname, "sscom1") == 0)
999 		unit = 1;
1000 
1001 	if (unit >= 0) {
1002 		s3c24x0_clock_freq2(CLKMAN_VBASE, NULL, NULL, &pclk);
1003 
1004 		s3c2440_sscom_kgdb_attach(&s3c2xx0_bs_tag,
1005 		    unit, kgdb_rate, pclk, kgdb_sscom_mode);
1006 	}
1007 #endif
1008 }
1009 #endif
1010 
1011 
1012 static struct arm32_dma_range mini2440_dma_ranges[1];
1013 
1014 bus_dma_tag_t
1015 s3c2xx0_bus_dma_init(struct arm32_bus_dma_tag *dma_tag_template)
1016 {
1017 	extern paddr_t physical_start, physical_end;
1018 	struct arm32_bus_dma_tag *dmat;
1019 
1020 	mini2440_dma_ranges[0].dr_sysbase = physical_start;
1021 	mini2440_dma_ranges[0].dr_busbase = physical_start;
1022 	mini2440_dma_ranges[0].dr_len = physical_end - physical_start;
1023 
1024 #if 1
1025 	dmat = dma_tag_template;
1026 #else
1027 	dmat = malloc(sizeof *dmat, M_DEVBUF, M_NOWAIT);
1028 	if (dmat == NULL)
1029 		return NULL;
1030 	*dmat =  *dma_tag_template;
1031 #endif
1032 
1033 	dmat->_ranges = mini2440_dma_ranges;
1034 	dmat->_nranges = 1;
1035 
1036 	return dmat;
1037 }
1038 
1039 void
1040 mini2440_ksyms(struct btinfo_symtab *bi_symtab)
1041 {
1042 #if NKSYMS || defined(DDB) || defined(LKM)
1043 	extern int end;
1044 
1045 #ifdef DDB
1046 	db_machine_init();
1047 #endif
1048 	if (bi_symtab == NULL) {
1049 		return;
1050 	}
1051 #ifdef VERBOSE_INIT_ARM
1052 	printf("Got symbol table. nsym=%d, ssym=%p, esym=%p\n",
1053 	       bi_symtab->nsym,
1054 	       bi_symtab->ssym,
1055 	       bi_symtab->esym);
1056 #endif
1057 
1058 	ksyms_addsyms_elf(bi_symtab->nsym,
1059 			  (int*)bi_symtab->ssym,
1060 			  (int*)bi_symtab->esym);
1061 #endif
1062 }
1063 
1064 void *
1065 lookup_bootinfo(int type)
1066 {
1067 	struct btinfo_common *bt;
1068 	struct btinfo_common *help = (struct btinfo_common *)bootinfo;
1069 
1070 	if (help->next == 0)
1071 		return (NULL);  /* bootinfo[] was not made */
1072 	do {
1073 		bt = help;
1074 		if (bt->type == type)
1075 			return (help);
1076 		help = (struct btinfo_common *)((char*)help + bt->next);
1077 	} while (bt->next &&
1078 		 (size_t)help < (size_t)bootinfo + BOOTINFO_MAXSIZE);
1079 
1080 	return (NULL);
1081 }
1082 
1083 
1084 extern char *booted_kernel;
1085 
1086 static void
1087 mini2440_device_register(device_t dev, void *aux) {
1088 	if (device_class(dev) == DV_IFNET) {
1089 #ifndef MEMORY_DISK_IS_ROOT
1090 		if (bi_rdev != NULL && device_is_a(dev, bi_rdev->devname) ) {
1091 			booted_device = dev;
1092 			rootfstype = MOUNT_NFS;
1093 			if( bi_path != NULL ) {
1094 				booted_kernel = bi_path->bootpath;
1095 			}
1096 		}
1097 #endif
1098 		if (bi_net != NULL && device_is_a(dev, bi_net->devname)) {
1099 			prop_data_t pd;
1100 			pd = prop_data_create_data_nocopy(bi_net->mac_address, ETHER_ADDR_LEN);
1101 			KASSERT(pd != NULL);
1102 			if (prop_dictionary_set(device_properties(dev), "mac-address", pd) == false) {
1103 				printf("WARNING: Unable to set mac-address property for %s\n", device_xname(dev));
1104 			}
1105 			prop_object_release(pd);
1106 			bi_net = NULL;
1107 		}
1108 	}
1109 #ifndef MEMORY_DISK_IS_ROOT
1110 	if (bi_rdev != NULL && device_class(dev) == DV_DISK
1111 	    && device_is_a(dev, bi_rdev->devname)
1112 	    && device_unit(dev) == bi_rdev->cookie) {
1113 		booted_device = dev;
1114 		booted_partition = bi_rdev->partition;
1115 		rootfstype = ROOT_FSTYPE_ANY;
1116 		if( bi_path != NULL ) {
1117 			booted_kernel = bi_path->bootpath;
1118 		}
1119 	}
1120 #endif
1121 }
1122