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