Home | History | Annotate | Line # | Download | only in broadcom
bcm283x_platform.c revision 1.18
      1 /*	$NetBSD: bcm283x_platform.c,v 1.18 2018/09/10 11:05:12 ryo Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2017 Jared D. McNeill <jmcneill (at) invisible.ca>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: bcm283x_platform.c,v 1.18 2018/09/10 11:05:12 ryo Exp $");
     31 
     32 #include "opt_arm_debug.h"
     33 #include "opt_bcm283x.h"
     34 #include "opt_cpuoptions.h"
     35 #include "opt_ddb.h"
     36 #include "opt_evbarm_boardtype.h"
     37 #include "opt_kgdb.h"
     38 #include "opt_fdt.h"
     39 #include "opt_rpi.h"
     40 #include "opt_vcprop.h"
     41 
     42 #include "sdhc.h"
     43 #include "bcmsdhost.h"
     44 #include "bcmdwctwo.h"
     45 #include "bcmspi.h"
     46 #include "bsciic.h"
     47 #include "plcom.h"
     48 #include "com.h"
     49 #include "genfb.h"
     50 #include "ukbd.h"
     51 
     52 #include <sys/param.h>
     53 #include <sys/bus.h>
     54 #include <sys/cpu.h>
     55 #include <sys/device.h>
     56 #include <sys/termios.h>
     57 
     58 #include <net/if_ether.h>
     59 
     60 #include <prop/proplib.h>
     61 
     62 #include <dev/fdt/fdtvar.h>
     63 
     64 #include <uvm/uvm_extern.h>
     65 
     66 #include <machine/bootconfig.h>
     67 
     68 #include <arm/armreg.h>
     69 #include <arm/cpufunc.h>
     70 
     71 #include <libfdt.h>
     72 
     73 #include <arm/broadcom/bcm2835reg.h>
     74 #include <arm/broadcom/bcm2835var.h>
     75 #include <arm/broadcom/bcm283x_platform.h>
     76 #include <arm/broadcom/bcm2835_intr.h>
     77 #include <arm/broadcom/bcm2835_mbox.h>
     78 #include <arm/broadcom/bcm2835_pmwdogvar.h>
     79 
     80 #include <evbarm/dev/plcomreg.h>
     81 #include <evbarm/dev/plcomvar.h>
     82 #include <evbarm/fdt/machdep.h>
     83 
     84 #include <dev/ic/ns16550reg.h>
     85 #include <dev/ic/comreg.h>
     86 
     87 #include <evbarm/rpi/vcio.h>
     88 #include <evbarm/rpi/vcpm.h>
     89 #include <evbarm/rpi/vcprop.h>
     90 
     91 #include <arm/fdt/arm_fdtvar.h>
     92 
     93 #include <arm/cortex/gtmr_var.h>
     94 
     95 #if NGENFB > 0
     96 #include <dev/videomode/videomode.h>
     97 #include <dev/videomode/edidvar.h>
     98 #include <dev/wscons/wsconsio.h>
     99 #endif
    100 
    101 #if NUKBD > 0
    102 #include <dev/usb/ukbdvar.h>
    103 #endif
    104 
    105 #ifdef DDB
    106 #include <machine/db_machdep.h>
    107 #include <ddb/db_sym.h>
    108 #include <ddb/db_extern.h>
    109 #endif
    110 
    111 void bcm283x_platform_early_putchar(vaddr_t, paddr_t, char c);
    112 void bcm2835_platform_early_putchar(char c);
    113 void bcm2836_platform_early_putchar(char c);
    114 void bcm2837_platform_early_putchar(char c);
    115 
    116 extern void bcmgenfb_set_console_dev(device_t dev);
    117 void bcmgenfb_set_ioctl(int(*)(void *, void *, u_long, void *, int, struct lwp *));
    118 extern void bcmgenfb_ddb_trap_callback(int where);
    119 static int rpi_ioctl(void *, void *, u_long, void *, int, lwp_t *);
    120 
    121 extern struct bus_space arm_generic_bs_tag;
    122 extern struct bus_space arm_generic_a4x_bs_tag;
    123 
    124 /* Prototypes for all the bus_space structure functions */
    125 bs_protos(arm_generic);
    126 bs_protos(arm_generic_a4x);
    127 bs_protos(bcm2835);
    128 bs_protos(bcm2835_a4x);
    129 bs_protos(bcm2836);
    130 bs_protos(bcm2836_a4x);
    131 
    132 struct bus_space bcm2835_bs_tag;
    133 struct bus_space bcm2835_a4x_bs_tag;
    134 struct bus_space bcm2836_bs_tag;
    135 struct bus_space bcm2836_a4x_bs_tag;
    136 
    137 static paddr_t bcm2835_bus_to_phys(bus_addr_t);
    138 static paddr_t bcm2836_bus_to_phys(bus_addr_t);
    139 
    140 static paddr_t
    141 bcm2835_bus_to_phys(bus_addr_t ba)
    142 {
    143 
    144 	/* Attempt to find the PA device mapping */
    145 	if (ba >= BCM2835_PERIPHERALS_BASE_BUS &&
    146 	    ba < BCM2835_PERIPHERALS_BASE_BUS + BCM2835_PERIPHERALS_SIZE)
    147 		return BCM2835_PERIPHERALS_BUS_TO_PHYS(ba);
    148 
    149 	return ba & ~BCM2835_BUSADDR_CACHE_MASK;
    150 }
    151 
    152 static paddr_t
    153 bcm2836_bus_to_phys(bus_addr_t ba)
    154 {
    155 
    156 	/* Attempt to find the PA device mapping */
    157 	if (ba >= BCM2835_PERIPHERALS_BASE_BUS &&
    158 	    ba < BCM2835_PERIPHERALS_BASE_BUS + BCM2835_PERIPHERALS_SIZE)
    159 		return BCM2836_PERIPHERALS_BUS_TO_PHYS(ba);
    160 
    161 	if (ba >= BCM2836_ARM_LOCAL_BASE &&
    162 	    ba < BCM2836_ARM_LOCAL_BASE + BCM2836_ARM_LOCAL_SIZE)
    163 		return ba;
    164 
    165 	return ba & ~BCM2835_BUSADDR_CACHE_MASK;
    166 }
    167 
    168 int
    169 bcm2835_bs_map(void *t, bus_addr_t ba, bus_size_t size, int flag,
    170     bus_space_handle_t *bshp)
    171 {
    172 	const paddr_t pa = bcm2835_bus_to_phys(ba);
    173 
    174 	return bus_space_map(&arm_generic_bs_tag, pa, size, flag, bshp);
    175 }
    176 
    177 paddr_t
    178 bcm2835_bs_mmap(void *t, bus_addr_t ba, off_t offset, int prot, int flags)
    179 {
    180 	const paddr_t pa = bcm2835_bus_to_phys(ba);
    181 
    182 	return bus_space_mmap(&arm_generic_bs_tag, pa, offset, prot, flags);
    183 }
    184 
    185 paddr_t
    186 bcm2835_a4x_bs_mmap(void *t, bus_addr_t ba, off_t offset, int prot, int flags)
    187 {
    188 
    189 	return bcm2835_bs_mmap(t, ba, 4 * offset, prot, flags);
    190 }
    191 
    192 int
    193 bcm2836_bs_map(void *t, bus_addr_t ba, bus_size_t size, int flag,
    194     bus_space_handle_t *bshp)
    195 {
    196 	const paddr_t pa = bcm2836_bus_to_phys(ba);
    197 
    198 	return bus_space_map(&arm_generic_bs_tag, pa, size, flag, bshp);
    199 }
    200 
    201 paddr_t
    202 bcm2836_bs_mmap(void *t, bus_addr_t ba, off_t offset, int prot, int flags)
    203 {
    204 	const paddr_t pa = bcm2836_bus_to_phys(ba);
    205 
    206 	return bus_space_mmap(&arm_generic_bs_tag, pa, offset, prot, flags);
    207 }
    208 
    209 paddr_t
    210 bcm2836_a4x_bs_mmap(void *t, bus_addr_t ba, off_t offset, int prot, int flags)
    211 {
    212 
    213 	return bcm2836_bs_mmap(t, ba, 4 * offset, prot, flags);
    214 }
    215 
    216 struct arm32_dma_range bcm2835_dma_ranges[] = {
    217 	[0] = {
    218 		.dr_sysbase = 0,
    219 		.dr_busbase = BCM2835_BUSADDR_CACHE_COHERENT,
    220 	}
    221 };
    222 
    223 struct arm32_dma_range bcm2836_dma_ranges[] = {
    224 	[0] = {
    225 		.dr_sysbase = 0,
    226 		.dr_busbase = BCM2835_BUSADDR_CACHE_DIRECT,
    227 	}
    228 };
    229 
    230 
    231 #if defined(SOC_BCM2835)
    232 static const struct pmap_devmap *
    233 bcm2835_platform_devmap(void)
    234 {
    235 	static const struct pmap_devmap devmap[] = {
    236 		DEVMAP_ENTRY(BCM2835_PERIPHERALS_VBASE, BCM2835_PERIPHERALS_BASE,
    237 		    BCM2835_PERIPHERALS_SIZE),	/* 16Mb */
    238 
    239 		DEVMAP_ENTRY_END
    240 	};
    241 
    242 	return devmap;
    243 }
    244 #endif
    245 
    246 #if defined(SOC_BCM2836)
    247 static const struct pmap_devmap *
    248 bcm2836_platform_devmap(void)
    249 {
    250 	static const struct pmap_devmap devmap[] = {
    251 		DEVMAP_ENTRY(BCM2836_PERIPHERALS_VBASE, BCM2836_PERIPHERALS_BASE,
    252 		    BCM2835_PERIPHERALS_SIZE),	/* 16Mb */
    253 
    254 		DEVMAP_ENTRY(BCM2836_ARM_LOCAL_VBASE, BCM2836_ARM_LOCAL_BASE,
    255 		    BCM2836_ARM_LOCAL_SIZE),
    256 #if defined(MULTIPROCESSOR) && defined(__aarch64__)
    257 		/* for fdt cpu spin-table */
    258 		DEVMAP_ENTRY(BCM2836_ARM_SMP_VBASE, BCM2836_ARM_SMP_BASE,
    259 		    BCM2836_ARM_SMP_SIZE),
    260 #endif
    261 		DEVMAP_ENTRY_END
    262 	};
    263 
    264 	return devmap;
    265 }
    266 #endif
    267 /*
    268  * Macros to translate between physical and virtual for a subset of the
    269  * kernel address space.  *Not* for general use.
    270  */
    271 
    272 #ifndef RPI_FB_WIDTH
    273 #define RPI_FB_WIDTH	1280
    274 #endif
    275 #ifndef RPI_FB_HEIGHT
    276 #define RPI_FB_HEIGHT	720
    277 #endif
    278 
    279 int uart_clk = BCM2835_UART0_CLK;
    280 int core_clk;
    281 
    282 static struct {
    283 	struct vcprop_buffer_hdr	vb_hdr;
    284 	struct vcprop_tag_clockrate	vbt_uartclockrate;
    285 	struct vcprop_tag_clockrate	vbt_vpuclockrate;
    286 	struct vcprop_tag end;
    287 } vb_uart __cacheline_aligned = {
    288 	.vb_hdr = {
    289 		.vpb_len = sizeof(vb_uart),
    290 		.vpb_rcode = VCPROP_PROCESS_REQUEST,
    291 	},
    292 	.vbt_uartclockrate = {
    293 		.tag = {
    294 			.vpt_tag = VCPROPTAG_GET_CLOCKRATE,
    295 			.vpt_len = VCPROPTAG_LEN(vb_uart.vbt_uartclockrate),
    296 			.vpt_rcode = VCPROPTAG_REQUEST
    297 		},
    298 		.id = VCPROP_CLK_UART
    299 	},
    300 	.vbt_vpuclockrate = {
    301 		.tag = {
    302 			.vpt_tag = VCPROPTAG_GET_CLOCKRATE,
    303 			.vpt_len = VCPROPTAG_LEN(vb_uart.vbt_vpuclockrate),
    304 			.vpt_rcode = VCPROPTAG_REQUEST
    305 		},
    306 		.id = VCPROP_CLK_CORE
    307 	},
    308 	.end = {
    309 		.vpt_tag = VCPROPTAG_NULL
    310 	}
    311 };
    312 
    313 static struct {
    314 	struct vcprop_buffer_hdr	vb_hdr;
    315 	struct vcprop_tag_fwrev		vbt_fwrev;
    316 	struct vcprop_tag_boardmodel	vbt_boardmodel;
    317 	struct vcprop_tag_boardrev	vbt_boardrev;
    318 	struct vcprop_tag_macaddr	vbt_macaddr;
    319 	struct vcprop_tag_memory	vbt_memory;
    320 	struct vcprop_tag_boardserial	vbt_serial;
    321 	struct vcprop_tag_dmachan	vbt_dmachan;
    322 	struct vcprop_tag_cmdline	vbt_cmdline;
    323 	struct vcprop_tag_clockrate	vbt_emmcclockrate;
    324 	struct vcprop_tag_clockrate	vbt_armclockrate;
    325 	struct vcprop_tag_clockrate	vbt_vpuclockrate;
    326 	struct vcprop_tag end;
    327 } vb __cacheline_aligned = {
    328 	.vb_hdr = {
    329 		.vpb_len = sizeof(vb),
    330 		.vpb_rcode = VCPROP_PROCESS_REQUEST,
    331 	},
    332 	.vbt_fwrev = {
    333 		.tag = {
    334 			.vpt_tag = VCPROPTAG_GET_FIRMWAREREV,
    335 			.vpt_len = VCPROPTAG_LEN(vb.vbt_fwrev),
    336 			.vpt_rcode = VCPROPTAG_REQUEST
    337 		},
    338 	},
    339 	.vbt_boardmodel = {
    340 		.tag = {
    341 			.vpt_tag = VCPROPTAG_GET_BOARDMODEL,
    342 			.vpt_len = VCPROPTAG_LEN(vb.vbt_boardmodel),
    343 			.vpt_rcode = VCPROPTAG_REQUEST
    344 		},
    345 	},
    346 	.vbt_boardrev = {
    347 		.tag = {
    348 			.vpt_tag = VCPROPTAG_GET_BOARDREVISION,
    349 			.vpt_len = VCPROPTAG_LEN(vb.vbt_boardrev),
    350 			.vpt_rcode = VCPROPTAG_REQUEST
    351 		},
    352 	},
    353 	.vbt_macaddr = {
    354 		.tag = {
    355 			.vpt_tag = VCPROPTAG_GET_MACADDRESS,
    356 			.vpt_len = VCPROPTAG_LEN(vb.vbt_macaddr),
    357 			.vpt_rcode = VCPROPTAG_REQUEST
    358 		},
    359 	},
    360 	.vbt_memory = {
    361 		.tag = {
    362 			.vpt_tag = VCPROPTAG_GET_ARMMEMORY,
    363 			.vpt_len = VCPROPTAG_LEN(vb.vbt_memory),
    364 			.vpt_rcode = VCPROPTAG_REQUEST
    365 		},
    366 	},
    367 	.vbt_serial = {
    368 		.tag = {
    369 			.vpt_tag = VCPROPTAG_GET_BOARDSERIAL,
    370 			.vpt_len = VCPROPTAG_LEN(vb.vbt_serial),
    371 			.vpt_rcode = VCPROPTAG_REQUEST
    372 		},
    373 	},
    374 	.vbt_dmachan = {
    375 		.tag = {
    376 			.vpt_tag = VCPROPTAG_GET_DMACHAN,
    377 			.vpt_len = VCPROPTAG_LEN(vb.vbt_dmachan),
    378 			.vpt_rcode = VCPROPTAG_REQUEST
    379 		},
    380 	},
    381 	.vbt_cmdline = {
    382 		.tag = {
    383 			.vpt_tag = VCPROPTAG_GET_CMDLINE,
    384 			.vpt_len = VCPROPTAG_LEN(vb.vbt_cmdline),
    385 			.vpt_rcode = VCPROPTAG_REQUEST
    386 		},
    387 	},
    388 	.vbt_emmcclockrate = {
    389 		.tag = {
    390 			.vpt_tag = VCPROPTAG_GET_CLOCKRATE,
    391 			.vpt_len = VCPROPTAG_LEN(vb.vbt_emmcclockrate),
    392 			.vpt_rcode = VCPROPTAG_REQUEST
    393 		},
    394 		.id = VCPROP_CLK_EMMC
    395 	},
    396 	.vbt_armclockrate = {
    397 		.tag = {
    398 			.vpt_tag = VCPROPTAG_GET_CLOCKRATE,
    399 			.vpt_len = VCPROPTAG_LEN(vb.vbt_armclockrate),
    400 			.vpt_rcode = VCPROPTAG_REQUEST
    401 		},
    402 		.id = VCPROP_CLK_ARM
    403 	},
    404 	.vbt_vpuclockrate = {
    405 		.tag = {
    406 			.vpt_tag = VCPROPTAG_GET_CLOCKRATE,
    407 			.vpt_len = VCPROPTAG_LEN(vb.vbt_vpuclockrate),
    408 			.vpt_rcode = VCPROPTAG_REQUEST
    409 		},
    410 		.id = VCPROP_CLK_CORE
    411 	},
    412 	.end = {
    413 		.vpt_tag = VCPROPTAG_NULL
    414 	}
    415 };
    416 
    417 #if NGENFB > 0
    418 static struct {
    419 	struct vcprop_buffer_hdr	vb_hdr;
    420 	struct vcprop_tag_edidblock	vbt_edid;
    421 	struct vcprop_tag end;
    422 } vb_edid __cacheline_aligned = {
    423 	.vb_hdr = {
    424 		.vpb_len = sizeof(vb_edid),
    425 		.vpb_rcode = VCPROP_PROCESS_REQUEST,
    426 	},
    427 	.vbt_edid = {
    428 		.tag = {
    429 			.vpt_tag = VCPROPTAG_GET_EDID_BLOCK,
    430 			.vpt_len = VCPROPTAG_LEN(vb_edid.vbt_edid),
    431 			.vpt_rcode = VCPROPTAG_REQUEST,
    432 		},
    433 		.blockno = 0,
    434 	},
    435 	.end = {
    436 		.vpt_tag = VCPROPTAG_NULL
    437 	}
    438 };
    439 
    440 static struct {
    441 	struct vcprop_buffer_hdr	vb_hdr;
    442 	struct vcprop_tag_fbres		vbt_res;
    443 	struct vcprop_tag_fbres		vbt_vres;
    444 	struct vcprop_tag_fbdepth	vbt_depth;
    445 	struct vcprop_tag_fbalpha	vbt_alpha;
    446 	struct vcprop_tag_allocbuf	vbt_allocbuf;
    447 	struct vcprop_tag_blankscreen	vbt_blank;
    448 	struct vcprop_tag_fbpitch	vbt_pitch;
    449 	struct vcprop_tag end;
    450 } vb_setfb __cacheline_aligned = {
    451 	.vb_hdr = {
    452 		.vpb_len = sizeof(vb_setfb),
    453 		.vpb_rcode = VCPROP_PROCESS_REQUEST,
    454 	},
    455 	.vbt_res = {
    456 		.tag = {
    457 			.vpt_tag = VCPROPTAG_SET_FB_RES,
    458 			.vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_res),
    459 			.vpt_rcode = VCPROPTAG_REQUEST,
    460 		},
    461 		.width = 0,
    462 		.height = 0,
    463 	},
    464 	.vbt_vres = {
    465 		.tag = {
    466 			.vpt_tag = VCPROPTAG_SET_FB_VRES,
    467 			.vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_vres),
    468 			.vpt_rcode = VCPROPTAG_REQUEST,
    469 		},
    470 		.width = 0,
    471 		.height = 0,
    472 	},
    473 	.vbt_depth = {
    474 		.tag = {
    475 			.vpt_tag = VCPROPTAG_SET_FB_DEPTH,
    476 			.vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_depth),
    477 			.vpt_rcode = VCPROPTAG_REQUEST,
    478 		},
    479 		.bpp = 32,
    480 	},
    481 	.vbt_alpha = {
    482 		.tag = {
    483 			.vpt_tag = VCPROPTAG_SET_FB_ALPHA_MODE,
    484 			.vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_alpha),
    485 			.vpt_rcode = VCPROPTAG_REQUEST,
    486 		},
    487 		.state = VCPROP_ALPHA_IGNORED,
    488 	},
    489 	.vbt_allocbuf = {
    490 		.tag = {
    491 			.vpt_tag = VCPROPTAG_ALLOCATE_BUFFER,
    492 			.vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_allocbuf),
    493 			.vpt_rcode = VCPROPTAG_REQUEST,
    494 		},
    495 		.address = PAGE_SIZE,	/* alignment */
    496 	},
    497 	.vbt_blank = {
    498 		.tag = {
    499 			.vpt_tag = VCPROPTAG_BLANK_SCREEN,
    500 			.vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_blank),
    501 			.vpt_rcode = VCPROPTAG_REQUEST,
    502 		},
    503 		.state = VCPROP_BLANK_OFF,
    504 	},
    505 	.vbt_pitch = {
    506 		.tag = {
    507 			.vpt_tag = VCPROPTAG_GET_FB_PITCH,
    508 			.vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_pitch),
    509 			.vpt_rcode = VCPROPTAG_REQUEST,
    510 		},
    511 	},
    512 	.end = {
    513 		.vpt_tag = VCPROPTAG_NULL,
    514 	},
    515 };
    516 
    517 #endif
    518 
    519 static int rpi_video_on = WSDISPLAYIO_VIDEO_ON;
    520 
    521 #if defined(RPI_HWCURSOR)
    522 #define CURSOR_BITMAP_SIZE	(64 * 8)
    523 #define CURSOR_ARGB_SIZE	(64 * 64 * 4)
    524 static uint32_t hcursor = 0;
    525 static bus_addr_t pcursor = 0;
    526 static uint32_t *cmem = NULL;
    527 static int cursor_x = 0, cursor_y = 0, hot_x = 0, hot_y = 0, cursor_on = 0;
    528 static uint32_t cursor_cmap[4];
    529 static uint8_t cursor_mask[8 * 64], cursor_bitmap[8 * 64];
    530 #endif
    531 
    532 u_int
    533 bcm283x_clk_get_rate_uart(void)
    534 {
    535 
    536 	if (vcprop_tag_success_p(&vb_uart.vbt_uartclockrate.tag))
    537 		return vb_uart.vbt_uartclockrate.rate;
    538 	return 0;
    539 }
    540 
    541 u_int
    542 bcm283x_clk_get_rate_vpu(void)
    543 {
    544 
    545 	if (vcprop_tag_success_p(&vb.vbt_vpuclockrate.tag) &&
    546 	    vb.vbt_vpuclockrate.rate > 0) {
    547 		return vb.vbt_vpuclockrate.rate;
    548 	}
    549 	return 0;
    550 }
    551 
    552 u_int
    553 bcm283x_clk_get_rate_emmc(void)
    554 {
    555 
    556 	if (vcprop_tag_success_p(&vb.vbt_emmcclockrate.tag) &&
    557 	    vb.vbt_emmcclockrate.rate > 0) {
    558 		return vb.vbt_emmcclockrate.rate;
    559 	}
    560 	return 0;
    561 }
    562 
    563 
    564 
    565 static void
    566 bcm283x_uartinit(bus_space_tag_t iot, bus_space_handle_t ioh)
    567 {
    568 	uint32_t res;
    569 
    570 	bcm2835_mbox_write(iot, ioh, BCMMBOX_CHANARM2VC,
    571 	    KERN_VTOPHYS((vaddr_t)&vb_uart));
    572 
    573 	bcm2835_mbox_read(iot, ioh, BCMMBOX_CHANARM2VC, &res);
    574 
    575 	cpu_dcache_inv_range((vaddr_t)&vb_uart, sizeof(vb_uart));
    576 
    577 	if (vcprop_tag_success_p(&vb_uart.vbt_uartclockrate.tag))
    578 		uart_clk = vb_uart.vbt_uartclockrate.rate;
    579 	if (vcprop_tag_success_p(&vb_uart.vbt_vpuclockrate.tag))
    580 		core_clk = vb_uart.vbt_vpuclockrate.rate;
    581 }
    582 
    583 #if defined(SOC_BCM2835)
    584 static void
    585 bcm2835_uartinit(void)
    586 {
    587 	const paddr_t pa = BCM2835_PERIPHERALS_BUS_TO_PHYS(BCM2835_ARMMBOX_BASE);
    588 	const bus_space_tag_t iot = &bcm2835_bs_tag;
    589 	const bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(pa);
    590 
    591 	bcm283x_uartinit(iot, ioh);
    592 }
    593 #endif
    594 
    595 #if defined(SOC_BCM2836)
    596 static void
    597 bcm2836_uartinit(void)
    598 {
    599 	const paddr_t pa = BCM2836_PERIPHERALS_BUS_TO_PHYS(BCM2835_ARMMBOX_BASE);
    600 	const bus_space_tag_t iot = &bcm2836_bs_tag;
    601 	const bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(pa);
    602 
    603 	bcm283x_uartinit(iot, ioh);
    604 }
    605 #endif
    606 
    607 #define	BCM283x_MINIMUM_SPLIT	(128U * 1024 * 1024)
    608 
    609 static size_t bcm283x_memorysize;
    610 
    611 static void
    612 bcm283x_bootparams(bus_space_tag_t iot, bus_space_handle_t ioh)
    613 {
    614 	uint32_t res;
    615 
    616 	bcm2835_mbox_write(iot, ioh, BCMMBOX_CHANPM, (
    617 #if (NSDHC > 0)
    618 	    (1 << VCPM_POWER_SDCARD) |
    619 #endif
    620 #if (NPLCOM > 0)
    621 	    (1 << VCPM_POWER_UART0) |
    622 #endif
    623 #if (NBCMDWCTWO > 0)
    624 	    (1 << VCPM_POWER_USB) |
    625 #endif
    626 #if (NBSCIIC > 0)
    627 	    (1 << VCPM_POWER_I2C0) | (1 << VCPM_POWER_I2C1) |
    628 	/*  (1 << VCPM_POWER_I2C2) | */
    629 #endif
    630 #if (NBCMSPI > 0)
    631 	    (1 << VCPM_POWER_SPI) |
    632 #endif
    633 	    0) << 4);
    634 
    635 	bcm2835_mbox_write(iot, ioh, BCMMBOX_CHANARM2VC,
    636 	    KERN_VTOPHYS((vaddr_t)&vb));
    637 
    638 	bcm2835_mbox_read(iot, ioh, BCMMBOX_CHANARM2VC, &res);
    639 
    640 	cpu_dcache_inv_range((vaddr_t)&vb, sizeof(vb));
    641 
    642 	if (!vcprop_buffer_success_p(&vb.vb_hdr)) {
    643 		bootconfig.dramblocks = 1;
    644 		bootconfig.dram[0].address = 0x0;
    645 		bootconfig.dram[0].pages = atop(BCM283x_MINIMUM_SPLIT);
    646 		return;
    647 	}
    648 
    649 	struct vcprop_tag_memory *vptp_mem = &vb.vbt_memory;
    650 	if (vcprop_tag_success_p(&vptp_mem->tag)) {
    651 		size_t n = vcprop_tag_resplen(&vptp_mem->tag) /
    652 		    sizeof(struct vcprop_memory);
    653 
    654 		bcm283x_memorysize = 0;
    655 		bootconfig.dramblocks = 0;
    656 
    657 		for (int i = 0; i < n && i < DRAM_BLOCKS; i++) {
    658 			bootconfig.dram[i].address = vptp_mem->mem[i].base;
    659 			bootconfig.dram[i].pages = atop(vptp_mem->mem[i].size);
    660 			bootconfig.dramblocks++;
    661 
    662 			bcm283x_memorysize += vptp_mem->mem[i].size;
    663 		}
    664 	}
    665 
    666 	if (vcprop_tag_success_p(&vb.vbt_armclockrate.tag))
    667 		curcpu()->ci_data.cpu_cc_freq = vb.vbt_armclockrate.rate;
    668 
    669 #ifdef VERBOSE_INIT_ARM
    670 	if (vcprop_tag_success_p(&vb.vbt_memory.tag))
    671 		printf("%s: memory size  %zu\n", __func__,
    672 		    bcm283x_memorysize);
    673 	if (vcprop_tag_success_p(&vb.vbt_armclockrate.tag))
    674 		printf("%s: arm clock    %d\n", __func__,
    675 		    vb.vbt_armclockrate.rate);
    676 	if (vcprop_tag_success_p(&vb.vbt_fwrev.tag))
    677 		printf("%s: firmware rev %x\n", __func__,
    678 		    vb.vbt_fwrev.rev);
    679 	if (vcprop_tag_success_p(&vb.vbt_boardmodel.tag))
    680 		printf("%s: board model  %x\n", __func__,
    681 		    vb.vbt_boardmodel.model);
    682 	if (vcprop_tag_success_p(&vb.vbt_macaddr.tag))
    683 		printf("%s: mac-address  %" PRIx64 "\n", __func__,
    684 		    vb.vbt_macaddr.addr);
    685 	if (vcprop_tag_success_p(&vb.vbt_boardrev.tag))
    686 		printf("%s: board rev    %x\n", __func__,
    687 		    vb.vbt_boardrev.rev);
    688 	if (vcprop_tag_success_p(&vb.vbt_serial.tag))
    689 		printf("%s: board serial %" PRIx64 "\n", __func__,
    690 		    vb.vbt_serial.sn);
    691 	if (vcprop_tag_success_p(&vb.vbt_dmachan.tag))
    692 		printf("%s: DMA channel mask 0x%08x\n", __func__,
    693 		    vb.vbt_dmachan.mask);
    694 
    695 	if (vcprop_tag_success_p(&vb.vbt_cmdline.tag))
    696 		printf("%s: cmdline      %s\n", __func__,
    697 		    vb.vbt_cmdline.cmdline);
    698 #endif
    699 }
    700 
    701 #if defined(SOC_BCM2835)
    702 static void
    703 bcm2835_bootparams(void)
    704 {
    705 	const paddr_t pa = BCM2835_PERIPHERALS_BUS_TO_PHYS(BCM2835_ARMMBOX_BASE);
    706 	const bus_space_tag_t iot = &bcm2835_bs_tag;
    707 	const bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(pa);
    708 
    709 	bcm283x_bootparams(iot, ioh);
    710 }
    711 #endif
    712 
    713 #if defined(SOC_BCM2836)
    714 static void
    715 bcm2836_bootparams(void)
    716 {
    717 	const paddr_t pa = BCM2836_PERIPHERALS_BUS_TO_PHYS(BCM2835_ARMMBOX_BASE);
    718 	const bus_space_tag_t iot = &bcm2836_bs_tag;
    719 	const bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(pa);
    720 
    721 	bcm283x_bootparams(iot, ioh);
    722 }
    723 
    724 static void
    725 bcm2836_bootstrap(void)
    726 {
    727 #ifdef MULTIPROCESSOR
    728 #ifdef __arm__
    729 
    730 #ifdef VERBOSE_INIT_ARM
    731 #define DPRINTF(...)	printf(__VA_ARGS__)
    732 #else
    733 #define DPRINTF(...)
    734 #endif
    735 
    736 #define RPI_CPU_MAX	4
    737 
    738 	const char *method;
    739 
    740 	const int cpus = OF_finddevice("/cpus");
    741 	if (cpus == -1) {
    742 		aprint_error("%s: no /cpus node found\n", __func__);
    743 		arm_cpu_max = 1;
    744 		return;
    745 	}
    746 
    747 	/* implementation dependent string "brcm,bcm2836-smp" for ARM 32-bit */
    748 	method = fdtbus_get_string(cpus, "enable-method");
    749 	if ((method != NULL) && (strcmp(method, "brcm,bcm2836-smp") == 0)) {
    750 		arm_cpu_max = RPI_CPU_MAX;
    751 		DPRINTF("%s: %d cpus present\n", __func__, arm_cpu_max);
    752 
    753 		extern void cortex_mpstart(void);
    754 
    755 		for (size_t i = 1; i < RPI_CPU_MAX; i++) {
    756 			bus_space_tag_t iot = &bcm2836_bs_tag;
    757 			bus_space_handle_t ioh = BCM2836_ARM_LOCAL_VBASE;
    758 
    759 			bus_space_write_4(iot, ioh,
    760 			    BCM2836_LOCAL_MAILBOX3_SETN(i),
    761 			    (uint32_t)cortex_mpstart);
    762 		}
    763 
    764 		/* Wake up AP in case firmware has placed it in WFE state */
    765 		__asm __volatile("sev" ::: "memory");
    766 
    767 		for (int loop = 0; loop < 16; loop++) {
    768 			if (arm_cpu_hatched == __BITS(arm_cpu_max - 1, 1))
    769 				break;
    770 			gtmr_delay(10000);
    771 		}
    772 
    773 		for (size_t i = 1; i < arm_cpu_max; i++) {
    774 			if ((arm_cpu_hatched & (1 << i)) == 0) {
    775 				printf("%s: warning: cpu%zu failed to hatch\n",
    776 				    __func__, i);
    777 			}
    778 		}
    779 		return;
    780 	}
    781 #endif /* __arm__ */
    782 
    783 	/* try enable-method each cpus */
    784 	arm_fdt_cpu_bootstrap();
    785 #endif /* MULTIPROCESSOR */
    786 }
    787 
    788 #endif	/* SOC_BCM2836 */
    789 
    790 #if NGENFB > 0
    791 static bool
    792 rpi_fb_parse_mode(const char *s, uint32_t *pwidth, uint32_t *pheight)
    793 {
    794 	char *x;
    795 
    796 	if (strncmp(s, "disable", 7) == 0)
    797 		return false;
    798 
    799 	x = strchr(s, 'x');
    800 	if (x) {
    801 		*pwidth = strtoul(s, NULL, 10);
    802 		*pheight = strtoul(x + 1, NULL, 10);
    803 	}
    804 
    805 	return true;
    806 }
    807 
    808 static bool
    809 rpi_fb_get_edid_mode(uint32_t *pwidth, uint32_t *pheight)
    810 {
    811 	struct edid_info ei;
    812 	uint8_t edid_data[1024];
    813 	uint32_t res;
    814 	int error;
    815 
    816 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_edid,
    817 	    sizeof(vb_edid), &res);
    818 	if (error) {
    819 		printf("%s: mbox request failed (%d)\n", __func__, error);
    820 		return false;
    821 	}
    822 
    823 	if (!vcprop_buffer_success_p(&vb_edid.vb_hdr) ||
    824 	    !vcprop_tag_success_p(&vb_edid.vbt_edid.tag) ||
    825 	    vb_edid.vbt_edid.status != 0)
    826 		return false;
    827 
    828 	memset(edid_data, 0, sizeof(edid_data));
    829 	memcpy(edid_data, vb_edid.vbt_edid.data,
    830 	    sizeof(vb_edid.vbt_edid.data));
    831 	edid_parse(edid_data, &ei);
    832 #ifdef VERBOSE_INIT_ARM
    833 	edid_print(&ei);
    834 #endif
    835 
    836 	if (ei.edid_preferred_mode) {
    837 		*pwidth = ei.edid_preferred_mode->hdisplay;
    838 		*pheight = ei.edid_preferred_mode->vdisplay;
    839 	}
    840 
    841 	return true;
    842 }
    843 
    844 /*
    845  * Initialize framebuffer console.
    846  *
    847  * Some notes about boot parameters:
    848  *  - If "fb=disable" is present, ignore framebuffer completely.
    849  *  - If "fb=<width>x<height> is present, use the specified mode.
    850  *  - If "console=fb" is present, attach framebuffer to console.
    851  */
    852 static bool
    853 rpi_fb_init(prop_dictionary_t dict, void *aux)
    854 {
    855 	uint32_t width = 0, height = 0;
    856 	uint32_t res;
    857 	char *ptr;
    858 	int integer;
    859 	int error;
    860 	bool is_bgr = true;
    861 
    862 	if (get_bootconf_option(boot_args, "fb",
    863 			      BOOTOPT_TYPE_STRING, &ptr)) {
    864 		if (rpi_fb_parse_mode(ptr, &width, &height) == false)
    865 			return false;
    866 	}
    867 	if (width == 0 || height == 0) {
    868 		rpi_fb_get_edid_mode(&width, &height);
    869 	}
    870 	if (width == 0 || height == 0) {
    871 		width = RPI_FB_WIDTH;
    872 		height = RPI_FB_HEIGHT;
    873 	}
    874 
    875 	vb_setfb.vbt_res.width = width;
    876 	vb_setfb.vbt_res.height = height;
    877 	vb_setfb.vbt_vres.width = width;
    878 	vb_setfb.vbt_vres.height = height;
    879 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_setfb,
    880 	    sizeof(vb_setfb), &res);
    881 	if (error) {
    882 		printf("%s: mbox request failed (%d)\n", __func__, error);
    883 		return false;
    884 	}
    885 
    886 	if (!vcprop_buffer_success_p(&vb_setfb.vb_hdr) ||
    887 	    !vcprop_tag_success_p(&vb_setfb.vbt_res.tag) ||
    888 	    !vcprop_tag_success_p(&vb_setfb.vbt_vres.tag) ||
    889 	    !vcprop_tag_success_p(&vb_setfb.vbt_depth.tag) ||
    890 	    !vcprop_tag_success_p(&vb_setfb.vbt_allocbuf.tag) ||
    891 	    !vcprop_tag_success_p(&vb_setfb.vbt_blank.tag) ||
    892 	    !vcprop_tag_success_p(&vb_setfb.vbt_pitch.tag)) {
    893 		printf("%s: prop tag failed\n", __func__);
    894 		return false;
    895 	}
    896 
    897 #ifdef VERBOSE_INIT_ARM
    898 	printf("%s: addr = 0x%x size = %d\n", __func__,
    899 	    vb_setfb.vbt_allocbuf.address,
    900 	    vb_setfb.vbt_allocbuf.size);
    901 	printf("%s: depth = %d\n", __func__, vb_setfb.vbt_depth.bpp);
    902 	printf("%s: pitch = %d\n", __func__,
    903 	    vb_setfb.vbt_pitch.linebytes);
    904 	printf("%s: width = %d height = %d\n", __func__,
    905 	    vb_setfb.vbt_res.width, vb_setfb.vbt_res.height);
    906 	printf("%s: vwidth = %d vheight = %d\n", __func__,
    907 	    vb_setfb.vbt_vres.width, vb_setfb.vbt_vres.height);
    908 #endif
    909 
    910 	if (vb_setfb.vbt_allocbuf.address == 0 ||
    911 	    vb_setfb.vbt_allocbuf.size == 0 ||
    912 	    vb_setfb.vbt_res.width == 0 ||
    913 	    vb_setfb.vbt_res.height == 0 ||
    914 	    vb_setfb.vbt_vres.width == 0 ||
    915 	    vb_setfb.vbt_vres.height == 0 ||
    916 	    vb_setfb.vbt_pitch.linebytes == 0) {
    917 		printf("%s: failed to set mode %ux%u\n", __func__,
    918 		    width, height);
    919 		return false;
    920 	}
    921 
    922 	prop_dictionary_set_uint32(dict, "width", vb_setfb.vbt_res.width);
    923 	prop_dictionary_set_uint32(dict, "height", vb_setfb.vbt_res.height);
    924 	prop_dictionary_set_uint8(dict, "depth", vb_setfb.vbt_depth.bpp);
    925 	prop_dictionary_set_uint16(dict, "linebytes",
    926 	    vb_setfb.vbt_pitch.linebytes);
    927 	prop_dictionary_set_uint32(dict, "address",
    928 	    vb_setfb.vbt_allocbuf.address);
    929 
    930 	/*
    931 	 * Old firmware uses BGR. New firmware uses RGB. The get and set
    932 	 * pixel order mailbox properties don't seem to work. The firmware
    933 	 * adds a kernel cmdline option bcm2708_fb.fbswap=<0|1>, so use it
    934 	 * to determine pixel order. 0 means BGR, 1 means RGB.
    935 	 *
    936 	 * See https://github.com/raspberrypi/linux/issues/514
    937 	 */
    938 	if (get_bootconf_option(boot_args, "bcm2708_fb.fbswap",
    939 				BOOTOPT_TYPE_INT, &integer)) {
    940 		is_bgr = integer == 0;
    941 	}
    942 	prop_dictionary_set_bool(dict, "is_bgr", is_bgr);
    943 
    944 	/* if "genfb.type=<n>" is passed in cmdline, override wsdisplay type */
    945 	if (get_bootconf_option(boot_args, "genfb.type",
    946 				BOOTOPT_TYPE_INT, &integer)) {
    947 		prop_dictionary_set_uint32(dict, "wsdisplay_type", integer);
    948 	}
    949 
    950 #if defined(RPI_HWCURSOR)
    951 	struct fdt_attach_args *faa = aux;
    952 	bus_space_handle_t hc;
    953 
    954 	hcursor = rpi_alloc_mem(CURSOR_ARGB_SIZE, PAGE_SIZE,
    955 	    MEM_FLAG_L1_NONALLOCATING | MEM_FLAG_HINT_PERMALOCK);
    956 	pcursor = rpi_lock_mem(hcursor);
    957 #ifdef RPI_IOCTL_DEBUG
    958 	printf("hcursor: %08x\n", hcursor);
    959 	printf("pcursor: %08x\n", (uint32_t)pcursor);
    960 	printf("fb: %08x\n", (uint32_t)vb_setfb.vbt_allocbuf.address);
    961 #endif
    962 	if (bus_space_map(faa->faa_bst, pcursor, CURSOR_ARGB_SIZE,
    963 	    BUS_SPACE_MAP_LINEAR|BUS_SPACE_MAP_PREFETCHABLE, &hc) != 0) {
    964 		printf("couldn't map cursor memory\n");
    965 	} else {
    966 		int i, j, k;
    967 
    968 		cmem = bus_space_vaddr(faa->faa_bst, hc);
    969 		k = 0;
    970 		for (j = 0; j < 64; j++) {
    971 			for (i = 0; i < 64; i++) {
    972 				cmem[i + k] =
    973 				 ((i & 8) ^ (j & 8)) ? 0xa0ff0000 : 0xa000ff00;
    974 			}
    975 			k += 64;
    976 		}
    977 		cpu_dcache_wb_range((vaddr_t)cmem, CURSOR_ARGB_SIZE);
    978 		rpi_fb_initcursor(pcursor, 0, 0);
    979 #ifdef RPI_IOCTL_DEBUG
    980 		rpi_fb_movecursor(600, 400, 1);
    981 #else
    982 		rpi_fb_movecursor(cursor_x, cursor_y, cursor_on);
    983 #endif
    984 	}
    985 #endif
    986 
    987 	return true;
    988 }
    989 
    990 
    991 #if defined(RPI_HWCURSOR)
    992 static int
    993 rpi_fb_do_cursor(struct wsdisplay_cursor *cur)
    994 {
    995 	int pos = 0;
    996 	int shape = 0;
    997 
    998 	if (cur->which & WSDISPLAY_CURSOR_DOCUR) {
    999 		if (cursor_on != cur->enable) {
   1000 			cursor_on = cur->enable;
   1001 			pos = 1;
   1002 		}
   1003 	}
   1004 	if (cur->which & WSDISPLAY_CURSOR_DOHOT) {
   1005 
   1006 		hot_x = cur->hot.x;
   1007 		hot_y = cur->hot.y;
   1008 		pos = 1;
   1009 		shape = 1;
   1010 	}
   1011 	if (cur->which & WSDISPLAY_CURSOR_DOPOS) {
   1012 
   1013 		cursor_x = cur->pos.x;
   1014 		cursor_y = cur->pos.y;
   1015 		pos = 1;
   1016 	}
   1017 	if (cur->which & WSDISPLAY_CURSOR_DOCMAP) {
   1018 		int i;
   1019 		uint32_t val;
   1020 
   1021 		for (i = 0; i < uimin(cur->cmap.count, 3); i++) {
   1022 			val = (cur->cmap.red[i] << 16 ) |
   1023 			      (cur->cmap.green[i] << 8) |
   1024 			      (cur->cmap.blue[i] ) |
   1025 			      0xff000000;
   1026 			cursor_cmap[i + cur->cmap.index + 2] = val;
   1027 		}
   1028 		shape = 1;
   1029 	}
   1030 	if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) {
   1031 		int err;
   1032 
   1033 		err = copyin(cur->mask, cursor_mask, CURSOR_BITMAP_SIZE);
   1034 		err += copyin(cur->image, cursor_bitmap, CURSOR_BITMAP_SIZE);
   1035 		if (err != 0)
   1036 			return EFAULT;
   1037 		shape = 1;
   1038 	}
   1039 	if (shape) {
   1040 		int i, j, idx;
   1041 		uint8_t mask;
   1042 
   1043 		for (i = 0; i < CURSOR_BITMAP_SIZE; i++) {
   1044 			mask = 0x01;
   1045 			for (j = 0; j < 8; j++) {
   1046 				idx = ((cursor_mask[i] & mask) ? 2 : 0) |
   1047 				    ((cursor_bitmap[i] & mask) ? 1 : 0);
   1048 				cmem[i * 8 + j] = cursor_cmap[idx];
   1049 				mask = mask << 1;
   1050 			}
   1051 		}
   1052 		/* just in case */
   1053 		cpu_dcache_wb_range((vaddr_t)cmem, CURSOR_ARGB_SIZE);
   1054 		rpi_fb_initcursor(pcursor, hot_x, hot_y);
   1055 	}
   1056 	if (pos) {
   1057 		rpi_fb_movecursor(cursor_x, cursor_y, cursor_on);
   1058 	}
   1059 	return 0;
   1060 }
   1061 #endif
   1062 
   1063 static int
   1064 rpi_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, lwp_t *l)
   1065 {
   1066 
   1067 	switch (cmd) {
   1068 	case WSDISPLAYIO_SVIDEO:
   1069 		{
   1070 			int d = *(int *)data;
   1071 			if (d == rpi_video_on)
   1072 				return 0;
   1073 			rpi_video_on = d;
   1074 			rpi_fb_set_video(d);
   1075 #if defined(RPI_HWCURSOR)
   1076 			rpi_fb_movecursor(cursor_x, cursor_y,
   1077 			                  d ? cursor_on : 0);
   1078 #endif
   1079 		}
   1080 		return 0;
   1081 	case WSDISPLAYIO_GVIDEO:
   1082 		*(int *)data = rpi_video_on;
   1083 		return 0;
   1084 #if defined(RPI_HWCURSOR)
   1085 	case WSDISPLAYIO_GCURPOS:
   1086 		{
   1087 			struct wsdisplay_curpos *cp = (void *)data;
   1088 
   1089 			cp->x = cursor_x;
   1090 			cp->y = cursor_y;
   1091 		}
   1092 		return 0;
   1093 	case WSDISPLAYIO_SCURPOS:
   1094 		{
   1095 			struct wsdisplay_curpos *cp = (void *)data;
   1096 
   1097 			cursor_x = cp->x;
   1098 			cursor_y = cp->y;
   1099 			rpi_fb_movecursor(cursor_x, cursor_y, cursor_on);
   1100 		}
   1101 		return 0;
   1102 	case WSDISPLAYIO_GCURMAX:
   1103 		{
   1104 			struct wsdisplay_curpos *cp = (void *)data;
   1105 
   1106 			cp->x = 64;
   1107 			cp->y = 64;
   1108 		}
   1109 		return 0;
   1110 	case WSDISPLAYIO_SCURSOR:
   1111 		{
   1112 			struct wsdisplay_cursor *cursor = (void *)data;
   1113 
   1114 			return rpi_fb_do_cursor(cursor);
   1115 		}
   1116 #endif
   1117 	default:
   1118 		return EPASSTHROUGH;
   1119 	}
   1120 }
   1121 
   1122 #endif
   1123 
   1124 SYSCTL_SETUP(sysctl_machdep_rpi, "sysctl machdep subtree setup (rpi)")
   1125 {
   1126 	sysctl_createv(clog, 0, NULL, NULL,
   1127 	    CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL,
   1128 	    NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL);
   1129 
   1130 	sysctl_createv(clog, 0, NULL, NULL,
   1131 	    CTLFLAG_PERMANENT|CTLFLAG_READONLY,
   1132 	    CTLTYPE_INT, "firmware_revision", NULL, NULL, 0,
   1133 	    &vb.vbt_fwrev.rev, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL);
   1134 
   1135 	sysctl_createv(clog, 0, NULL, NULL,
   1136 	    CTLFLAG_PERMANENT|CTLFLAG_READONLY,
   1137 	    CTLTYPE_INT, "board_model", NULL, NULL, 0,
   1138 	    &vb.vbt_boardmodel.model, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL);
   1139 
   1140 	sysctl_createv(clog, 0, NULL, NULL,
   1141 	    CTLFLAG_PERMANENT|CTLFLAG_READONLY,
   1142 	    CTLTYPE_INT, "board_revision", NULL, NULL, 0,
   1143 	    &vb.vbt_boardrev.rev, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL);
   1144 
   1145 	sysctl_createv(clog, 0, NULL, NULL,
   1146 	    CTLFLAG_PERMANENT|CTLFLAG_READONLY|CTLFLAG_HEX|CTLFLAG_PRIVATE,
   1147 	    CTLTYPE_QUAD, "serial", NULL, NULL, 0,
   1148 	    &vb.vbt_serial.sn, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL);
   1149 }
   1150 
   1151 #if defined(SOC_BCM2835)
   1152 static void
   1153 bcm2835_platform_bootstrap(void)
   1154 {
   1155 
   1156 	bcm2835_bs_tag = arm_generic_bs_tag;
   1157 	bcm2835_a4x_bs_tag = arm_generic_a4x_bs_tag;
   1158 
   1159 	bcm2835_bs_tag.bs_map = bcm2835_bs_map;
   1160 	bcm2835_bs_tag.bs_mmap = bcm2835_bs_mmap;
   1161 	bcm2835_a4x_bs_tag.bs_map = bcm2835_bs_map;
   1162 	bcm2835_a4x_bs_tag.bs_mmap = bcm2835_a4x_bs_mmap;
   1163 
   1164 	fdtbus_set_decoderegprop(false);
   1165 
   1166 	bcm2835_uartinit();
   1167 
   1168 	bcm2835_bootparams();
   1169 }
   1170 #endif
   1171 
   1172 #if defined(SOC_BCM2836)
   1173 static void
   1174 bcm2836_platform_bootstrap(void)
   1175 {
   1176 
   1177 	bcm2836_bs_tag = arm_generic_bs_tag;
   1178 	bcm2836_a4x_bs_tag = arm_generic_a4x_bs_tag;
   1179 
   1180 	bcm2836_bs_tag.bs_map = bcm2836_bs_map;
   1181 	bcm2836_bs_tag.bs_mmap = bcm2836_bs_mmap;
   1182 	bcm2836_a4x_bs_tag.bs_map = bcm2836_bs_map;
   1183 	bcm2836_a4x_bs_tag.bs_mmap = bcm2836_a4x_bs_mmap;
   1184 
   1185 	fdtbus_set_decoderegprop(false);
   1186 
   1187 	bcm2836_uartinit();
   1188 
   1189 	bcm2836_bootparams();
   1190 
   1191 	bcm2836_bootstrap();
   1192 }
   1193 #endif
   1194 
   1195 #if defined(SOC_BCM2835)
   1196 static void
   1197 bcm2835_platform_init_attach_args(struct fdt_attach_args *faa)
   1198 {
   1199 
   1200 	faa->faa_bst = &bcm2835_bs_tag;
   1201 	faa->faa_a4x_bst = &bcm2835_a4x_bs_tag;
   1202 	faa->faa_dmat = &bcm2835_bus_dma_tag;
   1203 
   1204 	bcm2835_bus_dma_tag._ranges = bcm2835_dma_ranges;
   1205 	bcm2835_bus_dma_tag._nranges = __arraycount(bcm2835_dma_ranges);
   1206 	bcm2835_dma_ranges[0].dr_len = bcm283x_memorysize;
   1207 }
   1208 #endif
   1209 
   1210 #if defined(SOC_BCM2836)
   1211 static void
   1212 bcm2836_platform_init_attach_args(struct fdt_attach_args *faa)
   1213 {
   1214 
   1215 	faa->faa_bst = &bcm2836_bs_tag;
   1216 	faa->faa_a4x_bst = &bcm2836_a4x_bs_tag;
   1217 	faa->faa_dmat = &bcm2835_bus_dma_tag;
   1218 
   1219 	bcm2835_bus_dma_tag._ranges = bcm2836_dma_ranges;
   1220 	bcm2835_bus_dma_tag._nranges = __arraycount(bcm2836_dma_ranges);
   1221 	bcm2836_dma_ranges[0].dr_len = bcm283x_memorysize;
   1222 }
   1223 #endif
   1224 
   1225 
   1226 void
   1227 bcm283x_platform_early_putchar(vaddr_t va, paddr_t pa, char c)
   1228 {
   1229 	volatile uint32_t *uartaddr =
   1230 	    cpu_earlydevice_va_p() ?
   1231 		(volatile uint32_t *)va :
   1232 		(volatile uint32_t *)pa;
   1233 
   1234 	while ((uartaddr[PL01XCOM_FR / 4] & PL01X_FR_TXFF) != 0)
   1235 		continue;
   1236 
   1237 	uartaddr[PL01XCOM_DR / 4] = c;
   1238 
   1239 	while ((uartaddr[PL01XCOM_FR / 4] & PL01X_FR_TXFE) == 0)
   1240 		continue;
   1241 }
   1242 
   1243 void
   1244 bcm2835_platform_early_putchar(char c)
   1245 {
   1246 	paddr_t pa = BCM2835_PERIPHERALS_BUS_TO_PHYS(BCM2835_UART0_BASE);
   1247 	vaddr_t va = BCM2835_IOPHYSTOVIRT(pa);
   1248 
   1249 	bcm283x_platform_early_putchar(va, pa, c);
   1250 }
   1251 
   1252 void
   1253 bcm2836_platform_early_putchar(char c)
   1254 {
   1255 	paddr_t pa = BCM2836_PERIPHERALS_BUS_TO_PHYS(BCM2835_UART0_BASE);
   1256 	vaddr_t va = BCM2835_IOPHYSTOVIRT(pa);
   1257 
   1258 	bcm283x_platform_early_putchar(va, pa, c);
   1259 }
   1260 
   1261 #define	BCM283x_REF_FREQ	19200000
   1262 
   1263 void
   1264 bcm2837_platform_early_putchar(char c)
   1265 {
   1266 #define AUCONSADDR_PA	BCM2836_PERIPHERALS_BUS_TO_PHYS(BCM2835_AUX_UART_BASE)
   1267 #define AUCONSADDR_VA	BCM2835_IOPHYSTOVIRT(AUCONSADDR_PA)
   1268 	volatile uint32_t *uartaddr =
   1269 	    cpu_earlydevice_va_p() ?
   1270 		(volatile uint32_t *)AUCONSADDR_VA :
   1271 		(volatile uint32_t *)AUCONSADDR_PA;
   1272 
   1273 	while ((uartaddr[com_lsr] & LSR_TXRDY) == 0)
   1274 		;
   1275 
   1276 	uartaddr[com_data] = c;
   1277 }
   1278 
   1279 static void
   1280 bcm283x_platform_device_register(device_t dev, void *aux)
   1281 {
   1282 	prop_dictionary_t dict = device_properties(dev);
   1283 
   1284 	if (device_is_a(dev, "bcmdmac") &&
   1285 	    vcprop_tag_success_p(&vb.vbt_dmachan.tag)) {
   1286 		prop_dictionary_set_uint32(dict,
   1287 		    "chanmask", vb.vbt_dmachan.mask);
   1288 	}
   1289 #if NSDHC > 0
   1290 	if (booted_device == NULL &&
   1291 	    device_is_a(dev, "ld") &&
   1292 	    device_is_a(device_parent(dev), "sdmmc")) {
   1293 		booted_partition = 0;
   1294 		booted_device = dev;
   1295 	}
   1296 #endif
   1297 	if ((device_is_a(dev, "usmsc") || device_is_a(dev, "mue")) &&
   1298 	    vcprop_tag_success_p(&vb.vbt_macaddr.tag)) {
   1299 		const uint8_t enaddr[ETHER_ADDR_LEN] = {
   1300 		     (vb.vbt_macaddr.addr >> 0) & 0xff,
   1301 		     (vb.vbt_macaddr.addr >> 8) & 0xff,
   1302 		     (vb.vbt_macaddr.addr >> 16) & 0xff,
   1303 		     (vb.vbt_macaddr.addr >> 24) & 0xff,
   1304 		     (vb.vbt_macaddr.addr >> 32) & 0xff,
   1305 		     (vb.vbt_macaddr.addr >> 40) & 0xff
   1306 		};
   1307 
   1308 		prop_data_t pd = prop_data_create_data(enaddr, ETHER_ADDR_LEN);
   1309 		KASSERT(pd != NULL);
   1310 		if (prop_dictionary_set(device_properties(dev), "mac-address",
   1311 		    pd) == false) {
   1312 			aprint_error_dev(dev,
   1313 			    "WARNING: Unable to set mac-address property\n");
   1314 		}
   1315 		prop_object_release(pd);
   1316 	}
   1317 
   1318 #if NGENFB > 0
   1319 	if (device_is_a(dev, "genfb")) {
   1320 		char *ptr;
   1321 
   1322 		bcmgenfb_set_console_dev(dev);
   1323 		bcmgenfb_set_ioctl(&rpi_ioctl);
   1324 #ifdef DDB
   1325 		db_trap_callback = bcmgenfb_ddb_trap_callback;
   1326 #endif
   1327 		if (rpi_fb_init(dict, aux) == false)
   1328 			return;
   1329 		if (get_bootconf_option(boot_args, "console",
   1330 		    BOOTOPT_TYPE_STRING, &ptr) && strncmp(ptr, "fb", 2) == 0) {
   1331 			prop_dictionary_set_bool(dict, "is_console", true);
   1332 #if NUKBD > 0
   1333 			/* allow ukbd to be the console keyboard */
   1334 			ukbd_cnattach();
   1335 #endif
   1336 		} else {
   1337 			prop_dictionary_set_bool(dict, "is_console", false);
   1338 		}
   1339 	}
   1340 #endif
   1341 }
   1342 
   1343 static u_int
   1344 bcm283x_platform_uart_freq(void)
   1345 {
   1346 
   1347 	return uart_clk;
   1348 }
   1349 
   1350 #if defined(SOC_BCM2835)
   1351 static const struct arm_platform bcm2835_platform = {
   1352 	.ap_devmap = bcm2835_platform_devmap,
   1353 	.ap_bootstrap = bcm2835_platform_bootstrap,
   1354 	.ap_init_attach_args = bcm2835_platform_init_attach_args,
   1355 	.ap_early_putchar = bcm2835_platform_early_putchar,
   1356 	.ap_device_register = bcm283x_platform_device_register,
   1357 	.ap_reset = bcm2835_system_reset,
   1358 	.ap_delay = bcm2835_tmr_delay,
   1359 	.ap_uart_freq = bcm283x_platform_uart_freq,
   1360 };
   1361 
   1362 ARM_PLATFORM(bcm2835, "brcm,bcm2835", &bcm2835_platform);
   1363 #endif
   1364 
   1365 #if defined(SOC_BCM2836)
   1366 static u_int
   1367 bcm2837_platform_uart_freq(void)
   1368 {
   1369 
   1370 	return core_clk * 2;
   1371 }
   1372 
   1373 static const struct arm_platform bcm2836_platform = {
   1374 	.ap_devmap = bcm2836_platform_devmap,
   1375 	.ap_bootstrap = bcm2836_platform_bootstrap,
   1376 	.ap_init_attach_args = bcm2836_platform_init_attach_args,
   1377 	.ap_early_putchar = bcm2836_platform_early_putchar,
   1378 	.ap_device_register = bcm283x_platform_device_register,
   1379 	.ap_reset = bcm2835_system_reset,
   1380 	.ap_delay = gtmr_delay,
   1381 	.ap_uart_freq = bcm283x_platform_uart_freq,
   1382 };
   1383 
   1384 static const struct arm_platform bcm2837_platform = {
   1385 	.ap_devmap = bcm2836_platform_devmap,
   1386 	.ap_bootstrap = bcm2836_platform_bootstrap,
   1387 	.ap_init_attach_args = bcm2836_platform_init_attach_args,
   1388 	.ap_early_putchar = bcm2837_platform_early_putchar,
   1389 	.ap_device_register = bcm283x_platform_device_register,
   1390 	.ap_reset = bcm2835_system_reset,
   1391 	.ap_delay = gtmr_delay,
   1392 	.ap_uart_freq = bcm2837_platform_uart_freq,
   1393 };
   1394 
   1395 ARM_PLATFORM(bcm2836, "brcm,bcm2836", &bcm2836_platform);
   1396 ARM_PLATFORM(bcm2837, "brcm,bcm2837", &bcm2837_platform);
   1397 #endif
   1398