1/*	$NetBSD: rpi_machdep.c,v 1.3.2.4 2013/02/13 01:36:14 riz Exp $	*/
2
3/*
4 * Copyright (c) 2002, 2003, 2005  Genetec Corporation.  All rights reserved.
5 * Written by Hiroyuki Bessho for Genetec Corporation.
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. The name of Genetec Corporation may not be used to endorse or
16 *    promote products derived from this software without specific prior
17 *    written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Copyright (c) 2001 Wasabi Systems, Inc.
32 * All rights reserved.
33 *
34 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 *    notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 *    notice, this list of conditions and the following disclaimer in the
43 *    documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 *    must display the following acknowledgement:
46 *	This product includes software developed for the NetBSD Project by
47 *	Wasabi Systems, Inc.
48 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
49 *    or promote products derived from this software without specific prior
50 *    written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
54 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
55 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
56 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
57 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
58 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
59 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
60 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
61 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
62 * POSSIBILITY OF SUCH DAMAGE.
63 *
64 * Copyright (c) 1997,1998 Mark Brinicombe.
65 * Copyright (c) 1997,1998 Causality Limited.
66 * All rights reserved.
67 *
68 * Redistribution and use in source and binary forms, with or without
69 * modification, are permitted provided that the following conditions
70 * are met:
71 * 1. Redistributions of source code must retain the above copyright
72 *    notice, this list of conditions and the following disclaimer.
73 * 2. Redistributions in binary form must reproduce the above copyright
74 *    notice, this list of conditions and the following disclaimer in the
75 *    documentation and/or other materials provided with the distribution.
76 * 3. All advertising materials mentioning features or use of this software
77 *    must display the following acknowledgement:
78 *	This product includes software developed by Mark Brinicombe
79 *	for the NetBSD Project.
80 * 4. The name of the company nor the name of the author may be used to
81 *    endorse or promote products derived from this software without specific
82 *    prior written permission.
83 *
84 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
85 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
86 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
87 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
88 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
89 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
90 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
91 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
92 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
93 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
94 * SUCH DAMAGE.
95 *
96 * Copyright (c) 2007 Microsoft
97 * All rights reserved.
98 *
99 * Redistribution and use in source and binary forms, with or without
100 * modification, are permitted provided that the following conditions
101 * are met:
102 * 1. Redistributions of source code must retain the above copyright
103 *    notice, this list of conditions and the following disclaimer.
104 * 2. Redistributions in binary form must reproduce the above copyright
105 *    notice, this list of conditions and the following disclaimer in the
106 *    documentation and/or other materials provided with the distribution.
107 * 3. All advertising materials mentioning features or use of this software
108 *    must display the following acknowledgement:
109 *	This product includes software developed by Microsoft
110 *
111 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
112 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
113 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
114 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
115 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
116 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
117 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
118 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
119 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
120 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
121 * SUCH DAMAGE.
122 */
123
124#include <sys/cdefs.h>
125__KERNEL_RCSID(0, "$NetBSD: rpi_machdep.c,v 1.3.2.4 2013/02/13 01:36:14 riz Exp $");
126
127#include "opt_evbarm_boardtype.h"
128
129#include "sdhc.h"
130#include "dotg.h"
131#include "bcmspi.h"
132#include "bsciic.h"
133#include "plcom.h"
134#include "genfb.h"
135
136#include <sys/param.h>
137#include <sys/device.h>
138#include <sys/kernel.h>
139#include <sys/reboot.h>
140#include <sys/termios.h>
141#include <sys/bus.h>
142#include <sys/socket.h>
143
144#include <net/if.h>
145#include <net/if_ether.h>
146#include <prop/proplib.h>
147
148#include <dev/cons.h>
149
150#include <uvm/uvm_extern.h>
151
152#include <arm/db_machdep.h>
153#include <arm/undefined.h>
154#include <arm/arm32/machdep.h>
155
156#include <machine/vmparam.h>
157#include <machine/autoconf.h>
158#include <machine/bootconfig.h>
159#include <machine/pmap.h>
160
161#include <arm/broadcom/bcm2835reg.h>
162#include <arm/broadcom/bcm2835var.h>
163#include <arm/broadcom/bcm2835_pmvar.h>
164#include <arm/broadcom/bcm2835_mbox.h>
165
166#include <evbarm/rpi/vcio.h>
167#include <evbarm/rpi/vcpm.h>
168#include <evbarm/rpi/vcprop.h>
169
170#include <evbarm/rpi/rpi.h>
171
172#if NPLCOM > 0
173#include <evbarm/dev/plcomreg.h>
174#include <evbarm/dev/plcomvar.h>
175#endif
176
177#if NGENFB > 0
178#include <dev/videomode/videomode.h>
179#include <dev/videomode/edidvar.h>
180#endif
181
182#include "ksyms.h"
183
184static void setup_real_page_tables(void);
185static void rpi_bootparams(void);
186static void rpi_device_register(device_t, void *);
187
188/*
189 * Address to call from cpu_reset() to reset the machine.
190 * This is machine architecture dependent as it varies depending
191 * on where the ROM appears when you turn the MMU off.
192 */
193u_int cpu_reset_address;
194
195/* Define various stack sizes in pages */
196#define FIQ_STACK_SIZE	1
197#define IRQ_STACK_SIZE	1
198#define ABT_STACK_SIZE	1
199#define UND_STACK_SIZE	1
200
201BootConfig bootconfig;		/* Boot config storage */
202static char bootargs[MAX_BOOT_STRING];
203char *boot_args = NULL;
204
205vm_offset_t physical_start;
206vm_offset_t physical_freestart;
207vm_offset_t physical_freeend;
208vm_offset_t physical_end;
209u_int free_pages;
210int physmem = 0;
211
212/* Physical and virtual addresses for some global pages */
213pv_addr_t systempage;
214pv_addr_t fiqstack;
215pv_addr_t irqstack;
216pv_addr_t undstack;
217pv_addr_t abtstack;
218pv_addr_t kernelstack;
219
220vm_offset_t msgbufphys;
221
222extern u_int data_abort_handler_address;
223extern u_int prefetch_abort_handler_address;
224extern u_int undefined_handler_address;
225
226extern char etext[];
227extern char __data_start[], _edata[];
228extern char __bss_start[], __bss_end__[];
229extern char _end[];
230
231extern int KERNEL_BASE_phys[];
232extern int KERNEL_BASE_virt[];
233
234#define KERNEL_PT_SYS		0  /* Page table for mapping proc0 zero page */
235#define KERNEL_PT_KERNEL	1  /* Page table for mapping kernel */
236#define KERNEL_PT_KERNEL_NUM	4
237
238#define KERNEL_PT_VMDATA	(KERNEL_PT_KERNEL + KERNEL_PT_KERNEL_NUM)
239/* Page tables for mapping kernel VM */
240#define KERNEL_PT_VMDATA_NUM	4	/* start with 16MB of KVM */
241#define NUM_KERNEL_PTS		(KERNEL_PT_VMDATA + KERNEL_PT_VMDATA_NUM)
242
243pv_addr_t kernel_pt_table[NUM_KERNEL_PTS];
244
245/*
246 * Macros to translate between physical and virtual for a subset of the
247 * kernel address space.  *Not* for general use.
248 */
249
250#define	KERN_VTOPDIFF	((vaddr_t)KERNEL_BASE_phys - (vaddr_t)KERNEL_BASE_virt)
251#define KERN_VTOPHYS(va) ((paddr_t)((vaddr_t)va + KERN_VTOPDIFF))
252#define KERN_PHYSTOV(pa) ((vaddr_t)((paddr_t)pa - KERN_VTOPDIFF))
253
254#ifndef RPI_FB_WIDTH
255#define RPI_FB_WIDTH	1280
256#endif
257#ifndef RPI_FB_HEIGHT
258#define RPI_FB_HEIGHT	720
259#endif
260
261#define	PLCONADDR 0x20201000
262
263#ifndef CONSDEVNAME
264#define CONSDEVNAME "plcom"
265#endif
266
267#ifndef PLCONSPEED
268#define PLCONSPEED B115200
269#endif
270#ifndef PLCONMODE
271#define PLCONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
272#endif
273#ifndef PLCOMCNUNIT
274#define PLCOMCNUNIT -1
275#endif
276
277#if (NPLCOM > 0)
278static const bus_addr_t consaddr = (bus_addr_t)PLCONADDR;
279
280int plcomcnspeed = PLCONSPEED;
281int plcomcnmode = PLCONMODE;
282#endif
283
284#include "opt_kgdb.h"
285#ifdef KGDB
286#include <sys/kgdb.h>
287#endif
288
289void
290cpu_reboot(int howto, char *bootstr)
291{
292
293	/*
294	 * If we are still cold then hit the air brakes
295	 * and crash to earth fast
296	 */
297	if (cold) {
298		doshutdownhooks();
299		printf("The operating system has halted.\r\n");
300		printf("Please press any key to reboot.\r\n");
301		cngetc();
302		printf("rebooting...\r\n");
303		bcm2835_system_reset();
304	}
305
306	/*
307	 * If RB_NOSYNC was not specified sync the discs.
308	 * Note: Unless cold is set to 1 here, syslogd will die during the
309	 * unmount.  It looks like syslogd is getting woken up only to find
310	 * that it cannot page part of the binary in as the filesystem has
311	 * been unmounted.
312	 */
313	if (!(howto & RB_NOSYNC))
314		bootsync();
315
316	/* Say NO to interrupts */
317	splhigh();
318
319	/* Do a dump if requested. */
320	if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP)
321		dumpsys();
322
323	/* Run any shutdown hooks */
324	doshutdownhooks();
325
326	/* Make sure IRQ's are disabled */
327	IRQdisable;
328
329	if (howto & RB_HALT) {
330		printf("The operating system has halted.\r\n");
331		printf("Please press any key to reboot.\r\n");
332		cngetc();
333	}
334
335	printf("rebooting...\r\n");
336	bcm2835_system_reset();
337
338	/*NOTREACHED*/
339}
340
341/* Smallest amount of RAM start.elf could give us. */
342#define RPI_MINIMUM_SPLIT (128U * 1024 * 1024)
343
344static struct {
345	struct vcprop_buffer_hdr	vb_hdr;
346	struct vcprop_tag_fwrev		vbt_fwrev;
347	struct vcprop_tag_boardmodel	vbt_boardmodel;
348	struct vcprop_tag_boardrev	vbt_boardrev;
349	struct vcprop_tag_macaddr	vbt_macaddr;
350	struct vcprop_tag_memory	vbt_memory;
351	struct vcprop_tag_boardserial	vbt_serial;
352	struct vcprop_tag_cmdline	vbt_cmdline;
353	struct vcprop_tag_clockrate	vbt_emmcclockrate;
354	struct vcprop_tag_clockrate	vbt_armclockrate;
355	struct vcprop_tag end;
356} vb __packed __aligned(16) =
357{
358	.vb_hdr = {
359		.vpb_len = sizeof(vb),
360		.vpb_rcode = VCPROP_PROCESS_REQUEST,
361	},
362	.vbt_fwrev = {
363		.tag = {
364			.vpt_tag = VCPROPTAG_GET_FIRMWAREREV,
365			.vpt_len = VCPROPTAG_LEN(vb.vbt_fwrev),
366			.vpt_rcode = VCPROPTAG_REQUEST
367		},
368	},
369	.vbt_boardmodel = {
370		.tag = {
371			.vpt_tag = VCPROPTAG_GET_BOARDMODEL,
372			.vpt_len = VCPROPTAG_LEN(vb.vbt_boardmodel),
373			.vpt_rcode = VCPROPTAG_REQUEST
374		},
375	},
376	.vbt_boardrev = {
377		.tag = {
378			.vpt_tag = VCPROPTAG_GET_BOARDREVISION,
379			.vpt_len = VCPROPTAG_LEN(vb.vbt_boardrev),
380			.vpt_rcode = VCPROPTAG_REQUEST
381		},
382	},
383	.vbt_macaddr = {
384		.tag = {
385			.vpt_tag = VCPROPTAG_GET_MACADDRESS,
386			.vpt_len = VCPROPTAG_LEN(vb.vbt_macaddr),
387			.vpt_rcode = VCPROPTAG_REQUEST
388		},
389	},
390	.vbt_memory = {
391		.tag = {
392			.vpt_tag = VCPROPTAG_GET_ARMMEMORY,
393			.vpt_len = VCPROPTAG_LEN(vb.vbt_memory),
394			.vpt_rcode = VCPROPTAG_REQUEST
395		},
396	},
397	.vbt_serial = {
398		.tag = {
399			.vpt_tag = VCPROPTAG_GET_BOARDSERIAL,
400			.vpt_len = VCPROPTAG_LEN(vb.vbt_serial),
401			.vpt_rcode = VCPROPTAG_REQUEST
402		},
403	},
404	.vbt_cmdline = {
405		.tag = {
406			.vpt_tag = VCPROPTAG_GET_CMDLINE,
407			.vpt_len = VCPROPTAG_LEN(vb.vbt_cmdline),
408			.vpt_rcode = VCPROPTAG_REQUEST
409		},
410	},
411	.vbt_emmcclockrate = {
412		.tag = {
413			.vpt_tag = VCPROPTAG_GET_CLOCKRATE,
414			.vpt_len = VCPROPTAG_LEN(vb.vbt_emmcclockrate),
415			.vpt_rcode = VCPROPTAG_REQUEST
416		},
417		.id = VCPROP_CLK_EMMC
418	},
419	.vbt_armclockrate = {
420		.tag = {
421			.vpt_tag = VCPROPTAG_GET_CLOCKRATE,
422			.vpt_len = VCPROPTAG_LEN(vb.vbt_armclockrate),
423			.vpt_rcode = VCPROPTAG_REQUEST
424		},
425		.id = VCPROP_CLK_ARM
426	},
427	.end = {
428		.vpt_tag = VCPROPTAG_NULL
429	}
430};
431
432#if NGENFB > 0
433static struct {
434	struct vcprop_buffer_hdr	vb_hdr;
435	struct vcprop_tag_edidblock	vbt_edid;
436	struct vcprop_tag end;
437} vb_edid __packed __aligned(16) =
438{
439	.vb_hdr = {
440		.vpb_len = sizeof(vb_edid),
441		.vpb_rcode = VCPROP_PROCESS_REQUEST,
442	},
443	.vbt_edid = {
444		.tag = {
445			.vpt_tag = VCPROPTAG_GET_EDID_BLOCK,
446			.vpt_len = VCPROPTAG_LEN(vb_edid.vbt_edid),
447			.vpt_rcode = VCPROPTAG_REQUEST,
448		},
449		.blockno = 0,
450	},
451	.end = {
452		.vpt_tag = VCPROPTAG_NULL
453	}
454};
455
456static struct {
457	struct vcprop_buffer_hdr	vb_hdr;
458	struct vcprop_tag_fbres		vbt_res;
459	struct vcprop_tag_fbres		vbt_vres;
460	struct vcprop_tag_fbdepth	vbt_depth;
461	struct vcprop_tag_fbpixelorder	vbt_pixelorder;
462	struct vcprop_tag_fbalpha	vbt_alpha;
463	struct vcprop_tag_allocbuf	vbt_allocbuf;
464	struct vcprop_tag_blankscreen	vbt_blank;
465	struct vcprop_tag_fbpitch	vbt_pitch;
466	struct vcprop_tag end;
467} vb_setfb __packed __aligned(16) =
468{
469	.vb_hdr = {
470		.vpb_len = sizeof(vb_setfb),
471		.vpb_rcode = VCPROP_PROCESS_REQUEST,
472	},
473	.vbt_res = {
474		.tag = {
475			.vpt_tag = VCPROPTAG_SET_FB_RES,
476			.vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_res),
477			.vpt_rcode = VCPROPTAG_REQUEST,
478		},
479		.width = 0,
480		.height = 0,
481	},
482	.vbt_vres = {
483		.tag = {
484			.vpt_tag = VCPROPTAG_SET_FB_VRES,
485			.vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_vres),
486			.vpt_rcode = VCPROPTAG_REQUEST,
487		},
488		.width = 0,
489		.height = 0,
490	},
491	.vbt_depth = {
492		.tag = {
493			.vpt_tag = VCPROPTAG_SET_FB_DEPTH,
494			.vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_depth),
495			.vpt_rcode = VCPROPTAG_REQUEST,
496		},
497		.bpp = 32,
498	},
499	.vbt_pixelorder = {
500		.tag = {
501			.vpt_tag = VCPROPTAG_SET_FB_PIXEL_ORDER,
502			.vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_pixelorder),
503			.vpt_rcode = VCPROPTAG_REQUEST,
504		},
505		.state = VCPROP_PIXEL_BGR,
506	},
507	.vbt_alpha = {
508		.tag = {
509			.vpt_tag = VCPROPTAG_SET_FB_ALPHA_MODE,
510			.vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_alpha),
511			.vpt_rcode = VCPROPTAG_REQUEST,
512		},
513		.state = VCPROP_ALPHA_IGNORED,
514	},
515	.vbt_allocbuf = {
516		.tag = {
517			.vpt_tag = VCPROPTAG_ALLOCATE_BUFFER,
518			.vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_allocbuf),
519			.vpt_rcode = VCPROPTAG_REQUEST,
520		},
521		.address = PAGE_SIZE,	/* alignment */
522	},
523	.vbt_blank = {
524		.tag = {
525			.vpt_tag = VCPROPTAG_BLANK_SCREEN,
526			.vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_blank),
527			.vpt_rcode = VCPROPTAG_REQUEST,
528		},
529		.state = VCPROP_BLANK_OFF,
530	},
531	.vbt_pitch = {
532		.tag = {
533			.vpt_tag = VCPROPTAG_GET_FB_PITCH,
534			.vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_pitch),
535			.vpt_rcode = VCPROPTAG_REQUEST,
536		},
537	},
538	.end = {
539		.vpt_tag = VCPROPTAG_NULL,
540	},
541};
542#endif
543
544static void
545rpi_bootparams(void)
546{
547	bus_space_tag_t iot = &bcm2835_bs_tag;
548	bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(BCM2835_ARMMBOX_BASE);
549	uint32_t res;
550
551	bcm2835_mbox_write(iot, ioh, BCMMBOX_CHANPM, (
552#if (NSDHC > 0)
553	    (1 << VCPM_POWER_SDCARD) |
554#endif
555#if (NPLCOM > 0)
556	    (1 << VCPM_POWER_UART0) |
557#endif
558#if (NDOTG > 0)
559	    (1 << VCPM_POWER_USB) |
560#endif
561#if (NBSCIIC > 0)
562	    (1 << VCPM_POWER_I2C0) | (1 << VCPM_POWER_I2C1) |
563	/*  (1 << VCPM_POWER_I2C2) | */
564#endif
565#if (NBCMSPI > 0)
566	    (1 << VCPM_POWER_SPI) |
567#endif
568	    0) << 4);
569
570	bcm2835_mbox_write(iot, ioh, BCMMBOX_CHANARM2VC, KERN_VTOPHYS(&vb));
571
572	bcm2835_mbox_read(iot, ioh, BCMMBOX_CHANARM2VC, &res);
573
574	/*
575	 * No need to invalid the cache as the memory has never been referenced
576	 * by the ARM.
577	 *
578	 * cpu_dcache_inv_range((vaddr_t)&vb, sizeof(vb));
579	 *
580	 */
581
582	if (!vcprop_buffer_success_p(&vb.vb_hdr)) {
583		bootconfig.dramblocks = 1;
584		bootconfig.dram[0].address = 0x0;
585		bootconfig.dram[0].pages = atop(RPI_MINIMUM_SPLIT);
586		return;
587	}
588
589	struct vcprop_tag_memory *vptp_mem = &vb.vbt_memory;
590
591	if (vcprop_tag_success_p(&vptp_mem->tag)) {
592		size_t n = vcprop_tag_resplen(&vptp_mem->tag) /
593		    sizeof(struct vcprop_memory);
594
595    		bootconfig.dramblocks = 0;
596
597		for (int i = 0; i < n && i < DRAM_BLOCKS; i++) {
598			bootconfig.dram[i].address = vptp_mem->mem[i].base;
599			bootconfig.dram[i].pages = atop(vptp_mem->mem[i].size);
600			bootconfig.dramblocks++;
601		}
602	}
603
604	if (vcprop_tag_success_p(&vb.vbt_armclockrate.tag))
605		curcpu()->ci_data.cpu_cc_freq = vb.vbt_armclockrate.rate;
606
607#ifdef VERBOSE_INIT_ARM
608	if (vcprop_tag_success_p(&vb.vbt_fwrev.tag))
609		printf("%s: firmware rev %x\n", __func__,
610		    vb.vbt_fwrev.rev);
611	if (vcprop_tag_success_p(&vb.vbt_macaddr.tag))
612		printf("%s: mac-address  %llx\n", __func__,
613		    vb.vbt_macaddr.addr);
614	if (vcprop_tag_success_p(&vb.vbt_boardmodel.tag))
615		printf("%s: board model  %x\n", __func__,
616		    vb.vbt_boardmodel.model);
617	if (vcprop_tag_success_p(&vb.vbt_boardrev.tag))
618		printf("%s: board rev    %x\n", __func__,
619		    vb.vbt_boardrev.rev);
620	if (vcprop_tag_success_p(&vb.vbt_serial.tag))
621		printf("%s: board serial %llx\n", __func__,
622		    vb.vbt_serial.sn);
623
624	if (vcprop_tag_success_p(&vb.vbt_cmdline.tag))
625		printf("%s: cmdline      %s\n", __func__,
626		    vb.vbt_cmdline.cmdline);
627#endif
628}
629
630/*
631 * Static device mappings. These peripheral registers are mapped at
632 * fixed virtual addresses very early in initarm() so that we can use
633 * them while booting the kernel, and stay at the same address
634 * throughout whole kernel's life time.
635 *
636 * We use this table twice; once with bootstrap page table, and once
637 * with kernel's page table which we build up in initarm().
638 *
639 * Since we map these registers into the bootstrap page table using
640 * pmap_devmap_bootstrap() which calls pmap_map_chunk(), we map
641 * registers segment-aligned and segment-rounded in order to avoid
642 * using the 2nd page tables.
643 */
644#define _A(a)	((a) & ~L1_S_OFFSET)
645#define _S(s)	(((s) + L1_S_SIZE - 1) & ~(L1_S_SIZE-1))
646
647static inline
648pd_entry_t *
649read_ttb(void)
650{
651	long ttb;
652
653	__asm volatile("mrc   p15, 0, %0, c2, c0, 0" : "=r" (ttb));
654
655	return (pd_entry_t *)(ttb & ~((1<<14)-1));
656}
657
658#define _A(a)	((a) & ~L1_S_OFFSET)
659#define _S(s)	(((s) + L1_S_SIZE - 1) & ~(L1_S_SIZE-1))
660
661static const struct pmap_devmap rpi_devmap[] = {
662	{
663		_A(RPI_KERNEL_IO_VBASE),	/* 0xf2000000 */
664		_A(RPI_KERNEL_IO_PBASE),	/* 0x20000000 */
665		_S(RPI_KERNEL_IO_VSIZE),	/* 16Mb */
666		VM_PROT_READ|VM_PROT_WRITE,
667		PTE_NOCACHE,
668	},
669	{ 0, 0, 0, 0, 0 }
670};
671
672#undef  _A
673#undef  _S
674
675/*
676 * u_int initarm(...)
677 *
678 * Initial entry point on startup. This gets called before main() is
679 * entered.
680 * It should be responsible for setting up everything that must be
681 * in place when main is called.
682 * This includes
683 *   Taking a copy of the boot configuration structure.
684 *   Initialising the physical console so characters can be printed.
685 *   Setting up page tables for the kernel
686 */
687u_int
688initarm(void *arg)
689{
690
691	/*
692	 * Heads up ... Setup the CPU / MMU / TLB functions
693	 */
694	if (set_cpufuncs())
695		panic("cpu not recognized!");
696
697	/* map some peripheral registers */
698	pmap_devmap_bootstrap((vaddr_t)read_ttb(), rpi_devmap);
699
700	cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
701
702	consinit();
703
704	/* Talk to the user */
705#define BDSTR(s)	_BDSTR(s)
706#define _BDSTR(s)	#s
707	printf("\nNetBSD/evbarm (" BDSTR(EVBARM_BOARDTYPE) ") booting ...\n");
708
709	rpi_bootparams();
710
711	if (vcprop_tag_success_p(&vb.vbt_armclockrate.tag)) {
712		curcpu()->ci_data.cpu_cc_freq = vb.vbt_armclockrate.rate;
713#ifdef VERBOSE_INIT_ARM
714		printf("%s: arm clock   %d\n", __func__,
715		    vb.vbt_armclockrate.rate);
716#endif
717	}
718
719#ifdef VERBOSE_INIT_ARM
720	printf("initarm: Configuring system ...\n");
721#endif
722
723	bootconfig.dramblocks = 1;
724	physical_end = bootconfig.dram[0].pages * PAGE_SIZE;
725	physmem = bootconfig.dram[0].pages;
726	physical_start = 0;
727
728	/*
729	 * Our kernel is at the beginning of memory, so set our free space to
730	 * all the memory after the kernel.
731	 */
732	physical_freestart = KERN_VTOPHYS(round_page((vaddr_t)_end));
733	physical_freeend = physical_end;
734	free_pages = (physical_freeend - physical_freestart) / PAGE_SIZE;
735
736#ifdef VERBOSE_INIT_ARM
737	/* Tell the user about the memory */
738	printf("physmemory: %d pages at 0x%08lx -> 0x%08lx\n", physmem,
739	    physical_start, physical_end - 1);
740#endif
741
742	/*
743	 * This is going to do all the hard work of setting up the first and
744	 * and second level page tables.  Pages of memory will be allocated
745	 * and mapped for other structures that are required for system
746	 * operation.  When it returns, physical_freestart and free_pages will
747	 * have been updated to reflect the allocations that were made.  In
748	 * addition, kernel_l1pt, kernel_pt_table[], systempage, irqstack,
749	 * abtstack, undstack, kernelstack, msgbufphys will be set to point to
750	 * the memory that was allocated for them.
751	 */
752	setup_real_page_tables();
753
754	/*
755	 * Okay, the kernel starts 8kB in from the bottom of physical
756	 * memory.  We are going to allocate our bootstrap pages upwards
757	 * from physical_freestart.
758	 *
759	 * We need to allocate some fixed page tables to get the kernel
760	 * going.  We allocate one page directory and a number of page
761	 * tables and store the physical addresses in the kernel_pt_table
762	 * array.
763	 *
764	 * The kernel page directory must be on a 16K boundary.  The page
765	 * tables must be on 4K bounaries.  What we do is allocate the
766	 * page directory on the first 16K boundary that we encounter, and
767	 * the page tables on 4K boundaries otherwise.  Since we allocate
768	 * at least 3 L2 page tables, we are guaranteed to encounter at
769	 * least one 16K aligned region.
770	 */
771
772#ifdef VERBOSE_INIT_ARM
773	printf("freestart = 0x%08lx, free_pages = %d (0x%08x)\n",
774	    physical_freestart, free_pages, free_pages);
775#endif
776
777	/*
778	 * Moved from cpu_startup() as data_abort_handler() references
779	 * this during uvm init.
780	 */
781	uvm_lwp_setuarea(&lwp0, kernelstack.pv_va);
782
783#ifdef VERBOSE_INIT_ARM
784	printf("bootstrap done.\n");
785#endif
786
787	arm32_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
788
789	/*
790	 * Pages were allocated during the secondary bootstrap for the
791	 * stacks for different CPU modes.
792	 * We must now set the r13 registers in the different CPU modes to
793	 * point to these stacks.
794	 * Since the ARM stacks use STMFD etc. we must set r13 to the top end
795	 * of the stack memory.
796	 */
797#ifdef VERBOSE_INIT_ARM
798	printf("init subsystems: stacks ");
799#endif
800	set_stackptr(PSR_FIQ32_MODE,
801	    fiqstack.pv_va + FIQ_STACK_SIZE * PAGE_SIZE);
802	set_stackptr(PSR_IRQ32_MODE,
803	    irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE);
804	set_stackptr(PSR_ABT32_MODE,
805	    abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE);
806	set_stackptr(PSR_UND32_MODE,
807	    undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE);
808
809	/*
810	 * Well we should set a data abort handler.
811	 * Once things get going this will change as we will need a proper
812	 * handler.
813	 * Until then we will use a handler that just panics but tells us
814	 * why.
815	 * Initialisation of the vectors will just panic on a data abort.
816	 * This just fills in a slightly better one.
817	 */
818#ifdef VERBOSE_INIT_ARM
819	printf("vectors ");
820#endif
821	data_abort_handler_address = (u_int)data_abort_handler;
822	prefetch_abort_handler_address = (u_int)prefetch_abort_handler;
823	undefined_handler_address = (u_int)undefinedinstruction_bounce;
824
825	/* Initialise the undefined instruction handlers */
826#ifdef VERBOSE_INIT_ARM
827	printf("undefined ");
828#endif
829	undefined_init();
830
831	/* Load memory into UVM. */
832#ifdef VERBOSE_INIT_ARM
833	printf("page ");
834#endif
835	uvm_setpagesize();	/* initialize PAGE_SIZE-dependent variables */
836	uvm_page_physload(atop(physical_freestart), atop(physical_freeend),
837	    atop(physical_freestart), atop(physical_freeend),
838	    VM_FREELIST_DEFAULT);
839
840	/* Boot strap pmap telling it where the kernel page table is */
841#ifdef VERBOSE_INIT_ARM
842	printf("pmap ");
843#endif
844	pmap_bootstrap(KERNEL_VM_BASE, KERNEL_VM_BASE + KERNEL_VM_SIZE);
845
846	/* flag used in locore.s */
847	extern u_int cpu_reset_needs_v4_MMU_disable;
848	cpu_reset_needs_v4_MMU_disable = 0;
849	cpu_reset_address = (u_int) bcm2835_system_reset;
850
851#ifdef VERBOSE_INIT_ARM
852	printf("done.\n");
853#endif
854
855#ifdef __HAVE_MEMORY_DISK__
856	md_root_setconf(memory_disk, sizeof memory_disk);
857#endif
858
859	if (vcprop_tag_success_p(&vb.vbt_cmdline.tag))
860		strlcpy(bootargs, vb.vbt_cmdline.cmdline, sizeof(bootargs));
861	boot_args = bootargs;
862	parse_mi_bootargs(boot_args);
863
864#ifdef BOOTHOWTO
865	boothowto |= BOOTHOWTO;
866#endif
867
868#ifdef KGDB
869	if (boothowto & RB_KDB) {
870		kgdb_debug_init = 1;
871		kgdb_connect(1);
872	}
873#endif
874
875#ifdef DDB
876	db_machine_init();
877	if (boothowto & RB_KDB)
878		Debugger();
879#endif
880
881	/* we've a specific device_register routine */
882	evbarm_device_register = rpi_device_register;
883
884	/* We return the new stack pointer address */
885	return kernelstack.pv_va + USPACE_SVC_STACK_TOP;
886}
887
888void
889consinit(void)
890{
891	static int consinit_called = 0;
892#if (NPLCOM > 0 && defined(PLCONSOLE))
893	static struct plcom_instance rpi_pi = {
894		.pi_type = PLCOM_TYPE_PL011,
895		.pi_flags = PLC_FLAG_32BIT_ACCESS,
896		.pi_iot = &bcm2835_bs_tag,
897		.pi_size = BCM2835_UART0_SIZE
898	};
899#endif
900	if (consinit_called != 0)
901		return;
902
903	consinit_called = 1;
904
905#if (NPLCOM > 0 && defined(PLCONSOLE))
906	/*
907	 * Initialise the diagnostic serial console
908	 * This allows a means of generating output during initarm().
909	 */
910	rpi_pi.pi_iobase = consaddr;
911
912	plcomcnattach(&rpi_pi, plcomcnspeed, BCM2835_UART0_CLK,
913	    plcomcnmode, PLCOMCNUNIT);
914
915#endif
916}
917
918static void
919setup_real_page_tables(void)
920{
921	/*
922	 * We need to allocate some fixed page tables to get the kernel going.
923	 *
924	 * We are going to allocate our bootstrap pages from the beginning of
925	 * the free space that we just calculated.  We allocate one page
926	 * directory and a number of page tables and store the physical
927	 * addresses in the kernel_pt_table array.
928	 *
929	 * The kernel page directory must be on a 16K boundary.  The page
930	 * tables must be on 4K boundaries.  What we do is allocate the
931	 * page directory on the first 16K boundary that we encounter, and
932	 * the page tables on 4K boundaries otherwise.  Since we allocate
933	 * at least 3 L2 page tables, we are guaranteed to encounter at
934	 * least one 16K aligned region.
935	 */
936
937#ifdef VERBOSE_INIT_ARM
938	printf("Allocating page tables\n");
939#endif
940
941	/*
942	 * Define a macro to simplify memory allocation.  As we allocate the
943	 * memory, make sure that we don't walk over our temporary first level
944	 * translation table.
945	 */
946#define valloc_pages(var, np)						\
947	(var).pv_pa = physical_freestart;				\
948	physical_freestart += ((np) * PAGE_SIZE);			\
949	if (physical_freestart > (physical_freeend - L1_TABLE_SIZE))	\
950		panic("%s: out of memory", __func__);			\
951	free_pages -= (np);						\
952	(var).pv_va = KERN_PHYSTOV((var).pv_pa);			\
953	memset((char *)(var).pv_va, 0, ((np) * PAGE_SIZE));
954
955	int loop, pt_index;
956
957	pt_index = 0;
958	kernel_l1pt.pv_pa = 0;
959	kernel_l1pt.pv_va = 0;
960	for (loop = 0; loop <= NUM_KERNEL_PTS; ++loop) {
961		/* Are we 16KB aligned for an L1 ? */
962		if ((physical_freestart & (L1_TABLE_SIZE - 1)) == 0 &&
963		    kernel_l1pt.pv_pa == 0) {
964			valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
965		} else {
966			valloc_pages(kernel_pt_table[pt_index],
967			    L2_TABLE_SIZE / PAGE_SIZE);
968			++pt_index;
969		}
970	}
971
972	/* This should never be able to happen but better confirm that. */
973	if (!kernel_l1pt.pv_pa ||
974	    (kernel_l1pt.pv_pa & (L1_TABLE_SIZE - 1)) != 0)
975		panic("%s: Failed to align the kernel page directory", __func__);
976
977	/*
978	 * Allocate a page for the system page mapped to V0x00000000
979	 * This page will just contain the system vectors and can be
980	 * shared by all processes.
981	 */
982	valloc_pages(systempage, 1);
983	systempage.pv_va = ARM_VECTORS_HIGH;
984
985	/* Allocate stacks for all modes */
986	valloc_pages(fiqstack, FIQ_STACK_SIZE);
987	valloc_pages(irqstack, IRQ_STACK_SIZE);
988	valloc_pages(abtstack, ABT_STACK_SIZE);
989	valloc_pages(undstack, UND_STACK_SIZE);
990	valloc_pages(kernelstack, UPAGES);
991
992	/* Allocate the message buffer. */
993	pv_addr_t msgbuf;
994	int msgbuf_pgs = round_page(MSGBUFSIZE) / PAGE_SIZE;
995	valloc_pages(msgbuf, msgbuf_pgs);
996	msgbufphys = msgbuf.pv_pa;
997
998	/*
999	 * Ok we have allocated physical pages for the primary kernel
1000	 * page tables
1001	 */
1002
1003#ifdef VERBOSE_INIT_ARM
1004	printf("Creating L1 page table at 0x%08lx\n", kernel_l1pt.pv_pa);
1005#endif
1006
1007	/*
1008	 * Now we start construction of the L1 page table
1009	 * We start by mapping the L2 page tables into the L1.
1010	 * This means that we can replace L1 mappings later on if necessary
1011	 */
1012	vaddr_t l1_va = kernel_l1pt.pv_va;
1013	paddr_t l1_pa = kernel_l1pt.pv_pa;
1014
1015	/* Map the L2 pages tables in the L1 page table */
1016	pmap_link_l2pt(l1_va, ARM_VECTORS_HIGH & ~(0x00400000 - 1),
1017	    &kernel_pt_table[KERNEL_PT_SYS]);
1018	for (loop = 0; loop < KERNEL_PT_KERNEL_NUM; loop++)
1019		pmap_link_l2pt(l1_va, KERNEL_BASE + loop * 0x00400000,
1020		    &kernel_pt_table[KERNEL_PT_KERNEL + loop]);
1021	for (loop = 0; loop < KERNEL_PT_VMDATA_NUM; loop++)
1022		pmap_link_l2pt(l1_va, KERNEL_VM_BASE + loop * 0x00400000,
1023		    &kernel_pt_table[KERNEL_PT_VMDATA + loop]);
1024
1025	/* update the top of the kernel VM */
1026	pmap_curmaxkvaddr =
1027	    KERNEL_VM_BASE + (KERNEL_PT_VMDATA_NUM * 0x00400000);
1028
1029#ifdef VERBOSE_INIT_ARM
1030	printf("Mapping kernel\n");
1031#endif
1032
1033	extern char etext[], _end[];
1034	size_t textsize = (uintptr_t)etext - KERNEL_BASE;
1035	size_t totalsize = (uintptr_t)_end - KERNEL_BASE;
1036	u_int logical;
1037
1038	textsize = (textsize + PGOFSET) & ~PGOFSET;
1039	totalsize = (totalsize + PGOFSET) & ~PGOFSET;
1040
1041	logical = 0x00000000;	/* offset of kernel in RAM */
1042
1043	logical += pmap_map_chunk(l1_va, KERNEL_BASE + logical,
1044	    physical_start + logical, textsize,
1045	    VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
1046	logical += pmap_map_chunk(l1_va, KERNEL_BASE + logical,
1047	    physical_start + logical, totalsize - textsize,
1048	    VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
1049
1050#ifdef VERBOSE_INIT_ARM
1051	printf("Constructing L2 page tables\n");
1052#endif
1053
1054	/* Map the stack pages */
1055	pmap_map_chunk(l1_va, fiqstack.pv_va, fiqstack.pv_pa,
1056	    FIQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
1057	pmap_map_chunk(l1_va, irqstack.pv_va, irqstack.pv_pa,
1058	    IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
1059	pmap_map_chunk(l1_va, abtstack.pv_va, abtstack.pv_pa,
1060	    ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
1061	pmap_map_chunk(l1_va, undstack.pv_va, undstack.pv_pa,
1062	    UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
1063	pmap_map_chunk(l1_va, kernelstack.pv_va, kernelstack.pv_pa,
1064	    UPAGES * PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE, PTE_CACHE);
1065
1066	pmap_map_chunk(l1_va, kernel_l1pt.pv_va, kernel_l1pt.pv_pa,
1067	    L1_TABLE_SIZE, VM_PROT_READ | VM_PROT_WRITE, PTE_PAGETABLE);
1068
1069	for (loop = 0; loop < NUM_KERNEL_PTS; ++loop)
1070		pmap_map_chunk(l1_va, kernel_pt_table[loop].pv_va,
1071		    kernel_pt_table[loop].pv_pa, L2_TABLE_SIZE,
1072		    VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
1073
1074	/* Map the vector page. */
1075	pmap_map_entry(l1_va, ARM_VECTORS_HIGH, systempage.pv_pa,
1076	    VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
1077
1078	/*
1079	 * Map integrated peripherals at same address in first level page
1080	 * table so that we can continue to use console.
1081	 */
1082	pmap_devmap_bootstrap(l1_va, rpi_devmap);
1083
1084#ifdef VERBOSE_INIT_ARM
1085	/* Tell the user about where all the bits and pieces live. */
1086	printf("%22s       Physical              Virtual        Num\n", " ");
1087	printf("%22s Starting    Ending    Starting    Ending   Pages\n", " ");
1088
1089	static const char mem_fmt[] =
1090	    "%20s: 0x%08lx 0x%08lx 0x%08lx 0x%08lx %d\n";
1091	static const char mem_fmt_nov[] =
1092	    "%20s: 0x%08lx 0x%08lx                       %d\n";
1093
1094	printf(mem_fmt, "SDRAM", physical_start, physical_end-1,
1095	    KERN_PHYSTOV(physical_start), KERN_PHYSTOV(physical_end-1),
1096	    physmem);
1097	printf(mem_fmt, "text section",
1098	       KERN_VTOPHYS(KERNEL_BASE), KERN_VTOPHYS(etext-1),
1099	       (vaddr_t)KERNEL_BASE, (vaddr_t)etext-1,
1100	       (int)(textsize / PAGE_SIZE));
1101	printf(mem_fmt, "data section",
1102	       KERN_VTOPHYS(__data_start), KERN_VTOPHYS(_edata),
1103	       (vaddr_t)__data_start, (vaddr_t)_edata,
1104	       (int)((round_page((vaddr_t)_edata)
1105		      - trunc_page((vaddr_t)__data_start)) / PAGE_SIZE));
1106	printf(mem_fmt, "bss section",
1107	       KERN_VTOPHYS(__bss_start), KERN_VTOPHYS(__bss_end__),
1108	       (vaddr_t)__bss_start, (vaddr_t)__bss_end__,
1109	       (int)((round_page((vaddr_t)__bss_end__)
1110		      - trunc_page((vaddr_t)__bss_start)) / PAGE_SIZE));
1111	printf(mem_fmt, "L1 page directory",
1112	    kernel_l1pt.pv_pa, kernel_l1pt.pv_pa + L1_TABLE_SIZE - 1,
1113	    kernel_l1pt.pv_va, kernel_l1pt.pv_va + L1_TABLE_SIZE - 1,
1114	    L1_TABLE_SIZE / PAGE_SIZE);
1115	printf(mem_fmt, "Exception Vectors",
1116	    systempage.pv_pa, systempage.pv_pa + PAGE_SIZE - 1,
1117	    (vaddr_t)ARM_VECTORS_HIGH, (vaddr_t)ARM_VECTORS_HIGH + PAGE_SIZE - 1,
1118	    1);
1119	printf(mem_fmt, "FIQ stack",
1120	    fiqstack.pv_pa, fiqstack.pv_pa + (FIQ_STACK_SIZE * PAGE_SIZE) - 1,
1121	    fiqstack.pv_va, fiqstack.pv_va + (FIQ_STACK_SIZE * PAGE_SIZE) - 1,
1122	    FIQ_STACK_SIZE);
1123	printf(mem_fmt, "IRQ stack",
1124	    irqstack.pv_pa, irqstack.pv_pa + (IRQ_STACK_SIZE * PAGE_SIZE) - 1,
1125	    irqstack.pv_va, irqstack.pv_va + (IRQ_STACK_SIZE * PAGE_SIZE) - 1,
1126	    IRQ_STACK_SIZE);
1127	printf(mem_fmt, "ABT stack",
1128	    abtstack.pv_pa, abtstack.pv_pa + (ABT_STACK_SIZE * PAGE_SIZE) - 1,
1129	    abtstack.pv_va, abtstack.pv_va + (ABT_STACK_SIZE * PAGE_SIZE) - 1,
1130	    ABT_STACK_SIZE);
1131	printf(mem_fmt, "UND stack",
1132	    undstack.pv_pa, undstack.pv_pa + (UND_STACK_SIZE * PAGE_SIZE) - 1,
1133	    undstack.pv_va, undstack.pv_va + (UND_STACK_SIZE * PAGE_SIZE) - 1,
1134	    UND_STACK_SIZE);
1135	printf(mem_fmt, "SVC stack",
1136	    kernelstack.pv_pa, kernelstack.pv_pa + (UPAGES * PAGE_SIZE) - 1,
1137	    kernelstack.pv_va, kernelstack.pv_va + (UPAGES * PAGE_SIZE) - 1,
1138	    UPAGES);
1139	printf(mem_fmt_nov, "Message Buffer",
1140	    msgbufphys, msgbufphys + msgbuf_pgs * PAGE_SIZE - 1, msgbuf_pgs);
1141	printf(mem_fmt, "Free Memory", physical_freestart, physical_freeend-1,
1142	    KERN_PHYSTOV(physical_freestart), KERN_PHYSTOV(physical_freeend-1),
1143	    free_pages);
1144#endif
1145	/*
1146	 * Now we have the real page tables in place so we can switch to them.
1147	 * Once this is done we will be running with the REAL kernel page
1148	 * tables.
1149	 */
1150
1151	/* Switch tables */
1152#ifdef VERBOSE_INIT_ARM
1153	printf("switching to new L1 page table  @%#lx...", l1_pa);
1154#endif
1155
1156	cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
1157	cpu_setttb(l1_pa);
1158	cpu_tlb_flushID();
1159	cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
1160
1161#ifdef VERBOSE_INIT_ARM
1162	printf("OK.\n");
1163#endif
1164}
1165
1166#if NGENFB > 0
1167static bool
1168rpi_fb_parse_mode(const char *s, uint32_t *pwidth, uint32_t *pheight)
1169{
1170	if (strncmp(s, "fb", 2) != 0)
1171		return false;
1172
1173	if (strncmp(s, "fb:", 3) == 0) {
1174		char *x = strchr(s + 3, 'x');
1175		if (x) {
1176			*pwidth = strtoul(s + 3, NULL, 10);
1177			*pheight = strtoul(x + 1, NULL, 10);
1178		}
1179	}
1180
1181	return true;
1182}
1183
1184static bool
1185rpi_fb_get_edid_mode(uint32_t *pwidth, uint32_t *pheight)
1186{
1187	struct edid_info ei;
1188	uint8_t edid_data[1024];
1189	uint32_t res;
1190	int error;
1191
1192	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_edid,
1193	    sizeof(vb_edid), &res);
1194	if (error) {
1195		printf("%s: mbox request failed (%d)\n", __func__, error);
1196		return false;
1197	}
1198
1199	if (!vcprop_buffer_success_p(&vb_edid.vb_hdr) ||
1200	    !vcprop_tag_success_p(&vb_edid.vbt_edid.tag) ||
1201	    vb_edid.vbt_edid.status != 0)
1202		return false;
1203
1204	memset(edid_data, 0, sizeof(edid_data));
1205	memcpy(edid_data, vb_edid.vbt_edid.data,
1206	    sizeof(vb_edid.vbt_edid.data));
1207	edid_parse(edid_data, &ei);
1208#ifdef VERBOSE_INIT_ARM
1209	edid_print(&ei);
1210#endif
1211
1212	if (ei.edid_preferred_mode) {
1213		*pwidth = ei.edid_preferred_mode->hdisplay;
1214		*pheight = ei.edid_preferred_mode->vdisplay;
1215	}
1216
1217	return true;
1218}
1219
1220/*
1221 * Initialize framebuffer console.
1222 *
1223 * Some notes about boot parameters:
1224 *  - If "fb=disable" is present, ignore framebuffer completely.
1225 *  - If "fb=<width>x<height> is present, use the specified mode.
1226 *  - If "console=fb" is present, attach framebuffer to console.
1227 */
1228static bool
1229rpi_fb_init(prop_dictionary_t dict)
1230{
1231	uint32_t width = 0, height = 0;
1232	uint32_t res;
1233	char *ptr;
1234	int integer;
1235	int error;
1236
1237	if (get_bootconf_option(boot_args, "fb",
1238			      BOOTOPT_TYPE_STRING, &ptr)) {
1239		if (rpi_fb_parse_mode(ptr, &width, &height) == false)
1240			return false;
1241	}
1242	if (width == 0 || height == 0) {
1243		rpi_fb_get_edid_mode(&width, &height);
1244	}
1245	if (width == 0 || height == 0) {
1246		width = RPI_FB_WIDTH;
1247		height = RPI_FB_HEIGHT;
1248	}
1249
1250	vb_setfb.vbt_res.width = width;
1251	vb_setfb.vbt_res.height = height;
1252	vb_setfb.vbt_vres.width = width;
1253	vb_setfb.vbt_vres.height = height;
1254	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_setfb,
1255	    sizeof(vb_setfb), &res);
1256	if (error) {
1257		printf("%s: mbox request failed (%d)\n", __func__, error);
1258		return false;
1259	}
1260
1261	if (!vcprop_buffer_success_p(&vb_setfb.vb_hdr) ||
1262	    !vcprop_tag_success_p(&vb_setfb.vbt_res.tag) ||
1263	    !vcprop_tag_success_p(&vb_setfb.vbt_vres.tag) ||
1264	    !vcprop_tag_success_p(&vb_setfb.vbt_depth.tag) ||
1265	    !vcprop_tag_success_p(&vb_setfb.vbt_pixelorder.tag) ||
1266	    !vcprop_tag_success_p(&vb_setfb.vbt_allocbuf.tag) ||
1267	    !vcprop_tag_success_p(&vb_setfb.vbt_blank.tag) ||
1268	    !vcprop_tag_success_p(&vb_setfb.vbt_pitch.tag)) {
1269		printf("%s: prop tag failed\n", __func__);
1270		return false;
1271	}
1272
1273#ifdef VERBOSE_INIT_ARM
1274	printf("%s: addr = 0x%x size = %d\n", __func__,
1275	    vb_setfb.vbt_allocbuf.address,
1276	    vb_setfb.vbt_allocbuf.size);
1277	printf("%s: depth = %d\n", __func__, vb_setfb.vbt_depth.bpp);
1278	printf("%s: pitch = %d\n", __func__,
1279	    vb_setfb.vbt_pitch.linebytes);
1280	printf("%s: width = %d height = %d\n", __func__,
1281	    vb_setfb.vbt_res.width, vb_setfb.vbt_res.height);
1282	printf("%s: vwidth = %d vheight = %d\n", __func__,
1283	    vb_setfb.vbt_vres.width, vb_setfb.vbt_vres.height);
1284	printf("%s: pixelorder = %d\n", __func__,
1285	    vb_setfb.vbt_pixelorder.state);
1286#endif
1287
1288	if (vb_setfb.vbt_allocbuf.address == 0 ||
1289	    vb_setfb.vbt_allocbuf.size == 0 ||
1290	    vb_setfb.vbt_res.width == 0 ||
1291	    vb_setfb.vbt_res.height == 0 ||
1292	    vb_setfb.vbt_vres.width == 0 ||
1293	    vb_setfb.vbt_vres.height == 0 ||
1294	    vb_setfb.vbt_pitch.linebytes == 0) {
1295		printf("%s: failed to set mode %ux%u\n", __func__,
1296		    width, height);
1297		return false;
1298	}
1299
1300	prop_dictionary_set_uint32(dict, "width", vb_setfb.vbt_res.width);
1301	prop_dictionary_set_uint32(dict, "height", vb_setfb.vbt_res.height);
1302	prop_dictionary_set_uint8(dict, "depth", vb_setfb.vbt_depth.bpp);
1303	prop_dictionary_set_uint16(dict, "linebytes",
1304	    vb_setfb.vbt_pitch.linebytes);
1305	prop_dictionary_set_uint32(dict, "address",
1306	    vb_setfb.vbt_allocbuf.address);
1307	if (vb_setfb.vbt_pixelorder.state == VCPROP_PIXEL_BGR)
1308		prop_dictionary_set_bool(dict, "is_bgr", true);
1309
1310	/* if "genfb.type=<n>" is passed in cmdline, override wsdisplay type */
1311	if (get_bootconf_option(boot_args, "genfb.type",
1312				BOOTOPT_TYPE_INT, &integer)) {
1313		prop_dictionary_set_uint32(dict, "wsdisplay_type", integer);
1314	}
1315
1316	return true;
1317}
1318#endif
1319
1320static void
1321rpi_device_register(device_t dev, void *aux)
1322{
1323	prop_dictionary_t dict = device_properties(dev);
1324
1325#if NSDHC > 0
1326	if (device_is_a(dev, "sdhc") &&
1327	    vcprop_tag_success_p(&vb.vbt_emmcclockrate.tag) &&
1328	    vb.vbt_emmcclockrate.rate > 0) {
1329		prop_dictionary_set_uint32(dict,
1330		    "frequency", vb.vbt_emmcclockrate.rate);
1331	}
1332	if (booted_device == NULL &&
1333	    device_is_a(dev, "ld") &&
1334	    device_is_a(device_parent(dev), "sdmmc")) {
1335		booted_partition = 0;
1336		booted_device = dev;
1337	}
1338#endif
1339	if (device_is_a(dev, "usmsc") &&
1340	    vcprop_tag_success_p(&vb.vbt_macaddr.tag)) {
1341		const uint8_t enaddr[ETHER_ADDR_LEN] = {
1342		     (vb.vbt_macaddr.addr >> 0) & 0xff,
1343		     (vb.vbt_macaddr.addr >> 8) & 0xff,
1344		     (vb.vbt_macaddr.addr >> 16) & 0xff,
1345		     (vb.vbt_macaddr.addr >> 24) & 0xff,
1346		     (vb.vbt_macaddr.addr >> 32) & 0xff,
1347		     (vb.vbt_macaddr.addr >> 40) & 0xff
1348		};
1349
1350		prop_data_t pd = prop_data_create_data(enaddr, ETHER_ADDR_LEN);
1351		KASSERT(pd != NULL);
1352		if (prop_dictionary_set(device_properties(dev), "mac-address",
1353		    pd) == false) {
1354			aprint_error_dev(dev,
1355			    "WARNING: Unable to set mac-address property\n");
1356		}
1357		prop_object_release(pd);
1358	}
1359
1360#if NGENFB > 0
1361	if (device_is_a(dev, "genfb")) {
1362		char *ptr;
1363		if (rpi_fb_init(dict) == false)
1364			return;
1365		if (get_bootconf_option(boot_args, "console",
1366		    BOOTOPT_TYPE_STRING, &ptr) && strncmp(ptr, "fb", 2) == 0) {
1367			prop_dictionary_set_bool(dict, "is_console", true);
1368#if NUKBD > 0
1369			/* allow ukbd to be the console keyboard */
1370			ukbd_cnattach();
1371#endif
1372		} else {
1373			prop_dictionary_set_bool(dict, "is_console", false);
1374		}
1375	}
1376#endif
1377}
1378
1379#if 0
1380SYSCTL_SETUP(sysctl_machdep_rpi, "sysctl machdep subtree setup (rpi)")
1381{
1382	sysctl_createv(clog, 0, NULL, NULL,
1383	    CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL,
1384	    NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL);
1385
1386	sysctl_createv(clog, 0, NULL, NULL,
1387	    CTLFLAG_PERMANENT|CTLFLAG_READONLY|CTLFLAG_HEX|CTLFLAG_PRIVATE,
1388	    CTLTYPE_QUAD, "serial", NULL, NULL, 0,
1389	    &vb.vbt_serial.sn, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL);
1390}
1391#endif
1392