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