1 /* $NetBSD: bcm283x_platform.c,v 1.51 2025/09/06 22:53:47 thorpej 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.51 2025/09/06 22:53:47 thorpej 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 #if NGENFB > 0 495 static struct { 496 struct vcprop_buffer_hdr vb_hdr; 497 struct vcprop_tag_edidblock vbt_edid; 498 struct vcprop_tag end; 499 } vb_edid __cacheline_aligned = { 500 .vb_hdr = { 501 .vpb_len = htole32(sizeof(vb_edid)), 502 .vpb_rcode = htole32(VCPROP_PROCESS_REQUEST), 503 }, 504 .vbt_edid = { 505 .tag = { 506 .vpt_tag = htole32(VCPROPTAG_GET_EDID_BLOCK), 507 .vpt_len = htole32(VCPROPTAG_LEN(vb_edid.vbt_edid)), 508 .vpt_rcode = htole32(VCPROPTAG_REQUEST), 509 }, 510 .blockno = htole32(0), 511 }, 512 .end = { 513 .vpt_tag = htole32(VCPROPTAG_NULL) 514 } 515 }; 516 517 static struct { 518 struct vcprop_buffer_hdr vb_hdr; 519 struct vcprop_tag_fbres vbt_res; 520 struct vcprop_tag_fbres vbt_vres; 521 struct vcprop_tag_fbdepth vbt_depth; 522 struct vcprop_tag_fbalpha vbt_alpha; 523 struct vcprop_tag_allocbuf vbt_allocbuf; 524 struct vcprop_tag_blankscreen vbt_blank; 525 struct vcprop_tag_fbpitch vbt_pitch; 526 struct vcprop_tag end; 527 } vb_setfb __cacheline_aligned = { 528 .vb_hdr = { 529 .vpb_len = htole32(sizeof(vb_setfb)), 530 .vpb_rcode = htole32(VCPROP_PROCESS_REQUEST), 531 }, 532 .vbt_res = { 533 .tag = { 534 .vpt_tag = htole32(VCPROPTAG_SET_FB_RES), 535 .vpt_len = htole32(VCPROPTAG_LEN(vb_setfb.vbt_res)), 536 .vpt_rcode = htole32(VCPROPTAG_REQUEST), 537 }, 538 .width = htole32(0), 539 .height = htole32(0), 540 }, 541 .vbt_vres = { 542 .tag = { 543 .vpt_tag = htole32(VCPROPTAG_SET_FB_VRES), 544 .vpt_len = htole32(VCPROPTAG_LEN(vb_setfb.vbt_vres)), 545 .vpt_rcode = htole32(VCPROPTAG_REQUEST), 546 }, 547 .width = htole32(0), 548 .height = htole32(0), 549 }, 550 .vbt_depth = { 551 .tag = { 552 .vpt_tag = htole32(VCPROPTAG_SET_FB_DEPTH), 553 .vpt_len = htole32(VCPROPTAG_LEN(vb_setfb.vbt_depth)), 554 .vpt_rcode = htole32(VCPROPTAG_REQUEST), 555 }, 556 .bpp = htole32(32), 557 }, 558 .vbt_alpha = { 559 .tag = { 560 .vpt_tag = htole32(VCPROPTAG_SET_FB_ALPHA_MODE), 561 .vpt_len = htole32(VCPROPTAG_LEN(vb_setfb.vbt_alpha)), 562 .vpt_rcode = htole32(VCPROPTAG_REQUEST), 563 }, 564 .state = htole32(VCPROP_ALPHA_IGNORED), 565 }, 566 .vbt_allocbuf = { 567 .tag = { 568 .vpt_tag = htole32(VCPROPTAG_ALLOCATE_BUFFER), 569 .vpt_len = 570 htole32(VCPROPTAG_LEN(vb_setfb.vbt_allocbuf)), 571 .vpt_rcode = htole32(VCPROPTAG_REQUEST), 572 }, 573 .address = htole32(PAGE_SIZE), /* alignment */ 574 }, 575 .vbt_blank = { 576 .tag = { 577 .vpt_tag = htole32(VCPROPTAG_BLANK_SCREEN), 578 .vpt_len = htole32(VCPROPTAG_LEN(vb_setfb.vbt_blank)), 579 .vpt_rcode = htole32(VCPROPTAG_REQUEST), 580 }, 581 .state = htole32(VCPROP_BLANK_OFF), 582 }, 583 .vbt_pitch = { 584 .tag = { 585 .vpt_tag = htole32(VCPROPTAG_GET_FB_PITCH), 586 .vpt_len = htole32(VCPROPTAG_LEN(vb_setfb.vbt_pitch)), 587 .vpt_rcode = htole32(VCPROPTAG_REQUEST), 588 }, 589 }, 590 .end = { 591 .vpt_tag = htole32(VCPROPTAG_NULL), 592 }, 593 }; 594 595 #endif 596 597 static int rpi_video_on = WSDISPLAYIO_VIDEO_ON; 598 599 #if defined(RPI_HWCURSOR) 600 #define CURSOR_BITMAP_SIZE (64 * 8) 601 #define CURSOR_ARGB_SIZE (64 * 64 * 4) 602 static uint32_t hcursor = 0; 603 static bus_addr_t pcursor = 0; 604 static uint32_t *cmem = NULL; 605 static int cursor_x = 0, cursor_y = 0, hot_x = 0, hot_y = 0, cursor_on = 0; 606 static uint32_t cursor_cmap[4]; 607 static uint8_t cursor_mask[8 * 64], cursor_bitmap[8 * 64]; 608 #endif 609 610 u_int 611 bcm283x_clk_get_rate_uart(void) 612 { 613 614 if (vcprop_tag_success_p(&vb_uart.vbt_uartclockrate.tag)) 615 return le32toh(vb_uart.vbt_uartclockrate.rate); 616 return 0; 617 } 618 619 u_int 620 bcm283x_clk_get_rate_vpu(void) 621 { 622 623 if (vcprop_tag_success_p(&vb.vbt_vpuclockrate.tag) && 624 vb.vbt_vpuclockrate.rate != 0) { 625 return le32toh(vb.vbt_vpuclockrate.rate); 626 } 627 return 0; 628 } 629 630 u_int 631 bcm283x_clk_get_rate_emmc(void) 632 { 633 634 if (vcprop_tag_success_p(&vb.vbt_emmcclockrate.tag) && 635 vb.vbt_emmcclockrate.rate != 0) { 636 return le32toh(vb.vbt_emmcclockrate.rate); 637 } 638 return 0; 639 } 640 641 u_int 642 bcm283x_clk_get_rate_emmc2(void) 643 { 644 645 if (vcprop_tag_success_p(&vb.vbt_emmc2clockrate.tag) && 646 vb.vbt_emmc2clockrate.rate != 0) { 647 return le32toh(vb.vbt_emmc2clockrate.rate); 648 } 649 return 0; 650 } 651 652 653 654 static void 655 bcm283x_uartinit(bus_space_tag_t iot, bus_space_handle_t ioh) 656 { 657 uint32_t res; 658 659 bcm2835_mbox_write(iot, ioh, BCMMBOX_CHANARM2VC, 660 KERN_VTOPHYS((vaddr_t)&vb_uart)); 661 662 bcm2835_mbox_read(iot, ioh, BCMMBOX_CHANARM2VC, &res); 663 664 /* 665 * RPI4 has Cortex A72 processors which do speculation, so 666 * we need to invalidate the cache for an updates done by 667 * the firmware 668 */ 669 cpu_dcache_inv_range((vaddr_t)&vb_uart, sizeof(vb_uart)); 670 671 if (vcprop_tag_success_p(&vb_uart.vbt_uartclockrate.tag)) 672 uart_clk = le32toh(vb_uart.vbt_uartclockrate.rate); 673 if (vcprop_tag_success_p(&vb_uart.vbt_vpuclockrate.tag)) 674 core_clk = le32toh(vb_uart.vbt_vpuclockrate.rate); 675 } 676 677 #if defined(SOC_BCM2835) 678 static void 679 bcm2835_uartinit(void) 680 { 681 const paddr_t pa = BCM2835_PERIPHERALS_BUS_TO_PHYS(BCM2835_ARMMBOX_BASE); 682 const bus_space_tag_t iot = &bcm2835_bs_tag; 683 const bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(pa); 684 685 bcm283x_uartinit(iot, ioh); 686 } 687 #endif 688 689 #if defined(SOC_BCM2836) 690 static void 691 bcm2836_uartinit(void) 692 { 693 const paddr_t pa = BCM2836_PERIPHERALS_BUS_TO_PHYS(BCM2835_ARMMBOX_BASE); 694 const bus_space_tag_t iot = &bcm2836_bs_tag; 695 const bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(pa); 696 697 bcm283x_uartinit(iot, ioh); 698 } 699 700 static void 701 bcm2711_uartinit(void) 702 { 703 const paddr_t pa = BCM2711_PERIPHERALS_BUS_TO_PHYS(BCM2835_ARMMBOX_BASE); 704 const bus_space_tag_t iot = &bcm2711_bs_tag; 705 const bus_space_handle_t ioh = BCM2711_IOPHYSTOVIRT(pa); 706 707 bcm283x_uartinit(iot, ioh); 708 } 709 #endif 710 711 #define BCM283x_MINIMUM_SPLIT (128U * 1024 * 1024) 712 713 static size_t bcm283x_memorysize; 714 715 static void 716 bcm283x_bootparams(bus_space_tag_t iot, bus_space_handle_t ioh) 717 { 718 uint32_t res; 719 720 bcm2835_mbox_write(iot, ioh, BCMMBOX_CHANPM, ( 721 #if (NSDHC > 0) 722 (1 << VCPM_POWER_SDCARD) | 723 #endif 724 #if (NPLCOM > 0) 725 (1 << VCPM_POWER_UART0) | 726 #endif 727 #if (NBCMDWCTWO > 0) 728 (1 << VCPM_POWER_USB) | 729 #endif 730 #if (NBSCIIC > 0) 731 (1 << VCPM_POWER_I2C0) | (1 << VCPM_POWER_I2C1) | 732 /* (1 << VCPM_POWER_I2C2) | */ 733 #endif 734 #if (NBCMSPI > 0) 735 (1 << VCPM_POWER_SPI) | 736 #endif 737 0) << 4); 738 739 bcm2835_mbox_write(iot, ioh, BCMMBOX_CHANARM2VC, 740 KERN_VTOPHYS((vaddr_t)&vb)); 741 742 bcm2835_mbox_read(iot, ioh, BCMMBOX_CHANARM2VC, &res); 743 744 /* 745 * RPI4 has Cortex A72 processors which do speculation, so 746 * we need to invalidate the cache for an updates done by 747 * the firmware 748 */ 749 cpu_dcache_inv_range((vaddr_t)&vb, sizeof(vb)); 750 751 if (!vcprop_buffer_success_p(&vb.vb_hdr)) { 752 bootconfig.dramblocks = 1; 753 bootconfig.dram[0].address = 0x0; 754 bootconfig.dram[0].pages = atop(BCM283x_MINIMUM_SPLIT); 755 return; 756 } 757 758 struct vcprop_tag_memory *vptp_mem = &vb.vbt_memory; 759 if (vcprop_tag_success_p(&vptp_mem->tag)) { 760 size_t n = vcprop_tag_resplen(&vptp_mem->tag) / 761 sizeof(struct vcprop_memory); 762 763 bcm283x_memorysize = 0; 764 bootconfig.dramblocks = 0; 765 766 for (int i = 0; i < n && i < DRAM_BLOCKS; i++) { 767 bootconfig.dram[i].address = 768 le32toh(vptp_mem->mem[i].base); 769 bootconfig.dram[i].pages = 770 atop(le32toh(vptp_mem->mem[i].size)); 771 bootconfig.dramblocks++; 772 773 bcm283x_memorysize += le32toh(vptp_mem->mem[i].size); 774 } 775 } 776 777 if (vcprop_tag_success_p(&vb.vbt_armclockrate.tag)) 778 curcpu()->ci_data.cpu_cc_freq = 779 le32toh(vb.vbt_armclockrate.rate); 780 781 #ifdef VERBOSE_INIT_ARM 782 if (vcprop_tag_success_p(&vb.vbt_memory.tag)) 783 printf("%s: memory size %zu\n", __func__, 784 bcm283x_memorysize); 785 if (vcprop_tag_success_p(&vb.vbt_armclockrate.tag)) 786 printf("%s: arm clock %d\n", __func__, 787 le32toh(vb.vbt_armclockrate.rate)); 788 if (vcprop_tag_success_p(&vb.vbt_vpuclockrate.tag)) 789 printf("%s: vpu clock %d\n", __func__, 790 le32toh(vb.vbt_vpuclockrate.rate)); 791 if (vcprop_tag_success_p(&vb.vbt_emmcclockrate.tag)) 792 printf("%s: emmc clock %d\n", __func__, 793 le32toh(vb.vbt_emmcclockrate.rate)); 794 if (vcprop_tag_success_p(&vb.vbt_emmc2clockrate.tag)) 795 printf("%s: emmc2 clock %d\n", __func__, 796 le32toh(vb.vbt_emmcclockrate.rate)); 797 if (vcprop_tag_success_p(&vb.vbt_fwrev.tag)) 798 printf("%s: firmware rev %x\n", __func__, 799 le32toh(vb.vbt_fwrev.rev)); 800 if (vcprop_tag_success_p(&vb.vbt_boardmodel.tag)) 801 printf("%s: board model %x\n", __func__, 802 le32toh(vb.vbt_boardmodel.model)); 803 if (vcprop_tag_success_p(&vb.vbt_macaddr.tag)) 804 printf("%s: mac-address %" PRIx64 "\n", __func__, 805 le64toh(vb.vbt_macaddr.addr)); 806 if (vcprop_tag_success_p(&vb.vbt_boardrev.tag)) 807 printf("%s: board rev %x\n", __func__, 808 le32toh(vb.vbt_boardrev.rev)); 809 if (vcprop_tag_success_p(&vb.vbt_serial.tag)) 810 printf("%s: board serial %" PRIx64 "\n", __func__, 811 le64toh(vb.vbt_serial.sn)); 812 if (vcprop_tag_success_p(&vb.vbt_dmachan.tag)) 813 printf("%s: DMA channel mask 0x%08x\n", __func__, 814 le32toh(vb.vbt_dmachan.mask)); 815 816 if (vcprop_tag_success_p(&vb.vbt_cmdline.tag)) 817 printf("%s: cmdline %s\n", __func__, 818 vb.vbt_cmdline.cmdline); 819 #endif 820 } 821 822 #if defined(SOC_BCM2835) 823 static void 824 bcm2835_bootparams(void) 825 { 826 const paddr_t pa = BCM2835_PERIPHERALS_BUS_TO_PHYS(BCM2835_ARMMBOX_BASE); 827 const bus_space_tag_t iot = &bcm2835_bs_tag; 828 const bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(pa); 829 830 bcm283x_bootparams(iot, ioh); 831 } 832 #endif 833 834 #if defined(SOC_BCM2836) 835 static void 836 bcm2836_bootparams(void) 837 { 838 const paddr_t pa = BCM2836_PERIPHERALS_BUS_TO_PHYS(BCM2835_ARMMBOX_BASE); 839 const bus_space_tag_t iot = &bcm2836_bs_tag; 840 const bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(pa); 841 842 bcm283x_bootparams(iot, ioh); 843 } 844 845 static void 846 bcm2711_bootparams(void) 847 { 848 const paddr_t pa = BCM2711_PERIPHERALS_BUS_TO_PHYS(BCM2835_ARMMBOX_BASE); 849 const bus_space_tag_t iot = &bcm2711_bs_tag; 850 const bus_space_handle_t ioh = BCM2711_IOPHYSTOVIRT(pa); 851 852 bcm283x_bootparams(iot, ioh); 853 } 854 855 #if defined(MULTIPROCESSOR) 856 static int 857 cpu_enable_bcm2836(int phandle) 858 { 859 bus_space_tag_t iot = &bcm2836_bs_tag; 860 bus_space_handle_t ioh = BCM2836_ARM_LOCAL_VBASE; 861 uint64_t mpidr; 862 863 fdtbus_get_reg64(phandle, 0, &mpidr, NULL); 864 865 const u_int cpuno = __SHIFTOUT(mpidr, MPIDR_AFF0); 866 867 bus_space_write_4(iot, ioh, BCM2836_LOCAL_MAILBOX3_SETN(cpuno), 868 KERN_VTOPHYS((vaddr_t)cpu_mpstart)); 869 870 return 0; 871 } 872 ARM_CPU_METHOD(bcm2836, "brcm,bcm2836-smp", cpu_enable_bcm2836); 873 #endif 874 875 #endif /* SOC_BCM2836 */ 876 877 #if NGENFB > 0 878 static bool 879 rpi_fb_parse_mode(const char *s, uint32_t *pwidth, uint32_t *pheight) 880 { 881 char *x; 882 883 if (strncmp(s, "disable", 7) == 0) 884 return false; 885 886 x = strchr(s, 'x'); 887 if (x) { 888 *pwidth = strtoul(s, NULL, 10); 889 *pheight = strtoul(x + 1, NULL, 10); 890 } 891 892 return true; 893 } 894 895 #define RPI_EDIDSIZE 1024 896 897 static bool 898 rpi_fb_get_edid_mode(uint32_t *pwidth, uint32_t *pheight) 899 { 900 struct edid_info ei; 901 uint32_t res; 902 int error; 903 904 error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_edid, 905 sizeof(vb_edid), &res); 906 if (error) { 907 printf("%s: mbox request failed (%d)\n", __func__, error); 908 return false; 909 } 910 911 if (!vcprop_buffer_success_p(&vb_edid.vb_hdr) || 912 !vcprop_tag_success_p(&vb_edid.vbt_edid.tag) || 913 vb_edid.vbt_edid.status != 0) 914 return false; 915 916 uint8_t *edid_data = kmem_alloc(RPI_EDIDSIZE, KM_SLEEP); 917 918 memset(edid_data, 0, RPI_EDIDSIZE); 919 memcpy(edid_data, vb_edid.vbt_edid.data, 920 sizeof(vb_edid.vbt_edid.data)); 921 edid_parse(edid_data, &ei); 922 #ifdef VERBOSE_INIT_ARM 923 edid_print(&ei); 924 #endif 925 926 if (ei.edid_preferred_mode) { 927 *pwidth = ei.edid_preferred_mode->hdisplay; 928 *pheight = ei.edid_preferred_mode->vdisplay; 929 } 930 931 kmem_free(edid_data, RPI_EDIDSIZE); 932 933 return true; 934 } 935 936 /* 937 * Initialize framebuffer console. 938 * 939 * Some notes about boot parameters: 940 * - If "fb=disable" is present, ignore framebuffer completely. 941 * - If "fb=<width>x<height> is present, use the specified mode. 942 * - If "console=fb" is present, attach framebuffer to console. 943 */ 944 static bool 945 rpi_fb_init(prop_dictionary_t dict, void *aux) 946 { 947 uint32_t width = 0, height = 0; 948 uint32_t res; 949 char *ptr; 950 int integer; 951 int error; 952 bool is_bgr = true; 953 954 if (get_bootconf_option(boot_args, "fb", 955 BOOTOPT_TYPE_STRING, &ptr)) { 956 if (rpi_fb_parse_mode(ptr, &width, &height) == false) 957 return false; 958 } 959 if (width == 0 || height == 0) { 960 rpi_fb_get_edid_mode(&width, &height); 961 } 962 if (width == 0 || height == 0) { 963 width = RPI_FB_WIDTH; 964 height = RPI_FB_HEIGHT; 965 } 966 967 vb_setfb.vbt_res.width = htole32(width); 968 vb_setfb.vbt_res.height = htole32(height); 969 vb_setfb.vbt_vres.width = htole32(width); 970 vb_setfb.vbt_vres.height = htole32(height); 971 error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_setfb, 972 sizeof(vb_setfb), &res); 973 if (error) { 974 printf("%s: mbox request failed (%d)\n", __func__, error); 975 return false; 976 } 977 978 if (!vcprop_buffer_success_p(&vb_setfb.vb_hdr) || 979 !vcprop_tag_success_p(&vb_setfb.vbt_res.tag) || 980 !vcprop_tag_success_p(&vb_setfb.vbt_vres.tag) || 981 !vcprop_tag_success_p(&vb_setfb.vbt_depth.tag) || 982 !vcprop_tag_success_p(&vb_setfb.vbt_allocbuf.tag) || 983 !vcprop_tag_success_p(&vb_setfb.vbt_blank.tag) || 984 !vcprop_tag_success_p(&vb_setfb.vbt_pitch.tag)) { 985 printf("%s: prop tag failed\n", __func__); 986 return false; 987 } 988 989 #ifdef VERBOSE_INIT_ARM 990 printf("%s: addr = 0x%x size = %d\n", __func__, 991 le32toh(vb_setfb.vbt_allocbuf.address), 992 le32toh(vb_setfb.vbt_allocbuf.size)); 993 printf("%s: depth = %d\n", __func__, le32toh(vb_setfb.vbt_depth.bpp)); 994 printf("%s: pitch = %d\n", __func__, 995 le32toh(vb_setfb.vbt_pitch.linebytes)); 996 printf("%s: width = %d height = %d\n", __func__, 997 le32toh(vb_setfb.vbt_res.width), le32toh(vb_setfb.vbt_res.height)); 998 printf("%s: vwidth = %d vheight = %d\n", __func__, 999 le32toh(vb_setfb.vbt_vres.width), 1000 le32toh(vb_setfb.vbt_vres.height)); 1001 #endif 1002 1003 if (vb_setfb.vbt_allocbuf.address == 0 || 1004 vb_setfb.vbt_allocbuf.size == 0 || 1005 vb_setfb.vbt_res.width == 0 || 1006 vb_setfb.vbt_res.height == 0 || 1007 vb_setfb.vbt_vres.width == 0 || 1008 vb_setfb.vbt_vres.height == 0 || 1009 vb_setfb.vbt_pitch.linebytes == 0) { 1010 printf("%s: failed to set mode %ux%u\n", __func__, 1011 width, height); 1012 return false; 1013 } 1014 1015 prop_dictionary_set_uint32(dict, "width", 1016 le32toh(vb_setfb.vbt_res.width)); 1017 prop_dictionary_set_uint32(dict, "height", 1018 le32toh(vb_setfb.vbt_res.height)); 1019 prop_dictionary_set_uint8(dict, "depth", 1020 le32toh(vb_setfb.vbt_depth.bpp)); 1021 prop_dictionary_set_uint16(dict, "linebytes", 1022 le32toh(vb_setfb.vbt_pitch.linebytes)); 1023 prop_dictionary_set_uint32(dict, "address", 1024 le32toh(vb_setfb.vbt_allocbuf.address)); 1025 1026 /* 1027 * Old firmware uses BGR. New firmware uses RGB. The get and set 1028 * pixel order mailbox properties don't seem to work. The firmware 1029 * adds a kernel cmdline option bcm2708_fb.fbswap=<0|1>, so use it 1030 * to determine pixel order. 0 means BGR, 1 means RGB. 1031 * 1032 * See https://github.com/raspberrypi/linux/issues/514 1033 */ 1034 if (get_bootconf_option(boot_args, "bcm2708_fb.fbswap", 1035 BOOTOPT_TYPE_INT, &integer)) { 1036 is_bgr = integer == 0; 1037 } 1038 prop_dictionary_set_bool(dict, "is_bgr", is_bgr); 1039 1040 /* if "genfb.type=<n>" is passed in cmdline, override wsdisplay type */ 1041 if (get_bootconf_option(boot_args, "genfb.type", 1042 BOOTOPT_TYPE_INT, &integer)) { 1043 prop_dictionary_set_uint32(dict, "wsdisplay_type", integer); 1044 } 1045 1046 #if defined(RPI_HWCURSOR) 1047 struct fdt_attach_args *faa = aux; 1048 bus_space_handle_t hc; 1049 1050 hcursor = rpi_alloc_mem(CURSOR_ARGB_SIZE, PAGE_SIZE, 1051 MEM_FLAG_L1_NONALLOCATING | MEM_FLAG_HINT_PERMALOCK); 1052 pcursor = rpi_lock_mem(hcursor); 1053 #ifdef RPI_IOCTL_DEBUG 1054 printf("hcursor: %08x\n", hcursor); 1055 printf("pcursor: %08x\n", (uint32_t)pcursor); 1056 printf("fb: %08x\n", (uint32_t)vb_setfb.vbt_allocbuf.address); 1057 #endif 1058 if (bus_space_map(faa->faa_bst, pcursor, CURSOR_ARGB_SIZE, 1059 BUS_SPACE_MAP_LINEAR|BUS_SPACE_MAP_PREFETCHABLE, &hc) != 0) { 1060 printf("couldn't map cursor memory\n"); 1061 } else { 1062 int i, j, k; 1063 1064 cmem = bus_space_vaddr(faa->faa_bst, hc); 1065 k = 0; 1066 for (j = 0; j < 64; j++) { 1067 for (i = 0; i < 64; i++) { 1068 cmem[i + k] = 1069 ((i & 8) ^ (j & 8)) ? 0xa0ff0000 : 0xa000ff00; 1070 } 1071 k += 64; 1072 } 1073 cpu_dcache_wb_range((vaddr_t)cmem, CURSOR_ARGB_SIZE); 1074 rpi_fb_initcursor(pcursor, 0, 0); 1075 #ifdef RPI_IOCTL_DEBUG 1076 rpi_fb_movecursor(600, 400, 1); 1077 #else 1078 rpi_fb_movecursor(cursor_x, cursor_y, cursor_on); 1079 #endif 1080 } 1081 #endif 1082 1083 return true; 1084 } 1085 1086 1087 #if defined(RPI_HWCURSOR) 1088 static int 1089 rpi_fb_do_cursor(struct wsdisplay_cursor *cur) 1090 { 1091 int pos = 0; 1092 int shape = 0; 1093 1094 if (cur->which & WSDISPLAY_CURSOR_DOCUR) { 1095 if (cursor_on != cur->enable) { 1096 cursor_on = cur->enable; 1097 pos = 1; 1098 } 1099 } 1100 if (cur->which & WSDISPLAY_CURSOR_DOHOT) { 1101 1102 hot_x = cur->hot.x; 1103 hot_y = cur->hot.y; 1104 pos = 1; 1105 shape = 1; 1106 } 1107 if (cur->which & WSDISPLAY_CURSOR_DOPOS) { 1108 1109 cursor_x = cur->pos.x; 1110 cursor_y = cur->pos.y; 1111 pos = 1; 1112 } 1113 if (cur->which & WSDISPLAY_CURSOR_DOCMAP) { 1114 int i; 1115 uint32_t val; 1116 1117 for (i = 0; i < uimin(cur->cmap.count, 3); i++) { 1118 val = (cur->cmap.red[i] << 16 ) | 1119 (cur->cmap.green[i] << 8) | 1120 (cur->cmap.blue[i] ) | 1121 0xff000000; 1122 cursor_cmap[i + cur->cmap.index + 2] = val; 1123 } 1124 shape = 1; 1125 } 1126 if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) { 1127 int err; 1128 1129 err = copyin(cur->mask, cursor_mask, CURSOR_BITMAP_SIZE); 1130 err += copyin(cur->image, cursor_bitmap, CURSOR_BITMAP_SIZE); 1131 if (err != 0) 1132 return EFAULT; 1133 shape = 1; 1134 } 1135 if (shape) { 1136 int i, j, idx; 1137 uint8_t mask; 1138 1139 for (i = 0; i < CURSOR_BITMAP_SIZE; i++) { 1140 mask = 0x01; 1141 for (j = 0; j < 8; j++) { 1142 idx = ((cursor_mask[i] & mask) ? 2 : 0) | 1143 ((cursor_bitmap[i] & mask) ? 1 : 0); 1144 cmem[i * 8 + j] = cursor_cmap[idx]; 1145 mask = mask << 1; 1146 } 1147 } 1148 /* just in case */ 1149 cpu_dcache_wb_range((vaddr_t)cmem, CURSOR_ARGB_SIZE); 1150 rpi_fb_initcursor(pcursor, hot_x, hot_y); 1151 } 1152 if (pos) { 1153 rpi_fb_movecursor(cursor_x, cursor_y, cursor_on); 1154 } 1155 return 0; 1156 } 1157 #endif 1158 1159 static int 1160 rpi_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, lwp_t *l) 1161 { 1162 1163 switch (cmd) { 1164 case WSDISPLAYIO_SVIDEO: 1165 { 1166 int d = *(int *)data; 1167 if (d == rpi_video_on) 1168 return 0; 1169 rpi_video_on = d; 1170 rpi_fb_set_video(d); 1171 #if defined(RPI_HWCURSOR) 1172 rpi_fb_movecursor(cursor_x, cursor_y, 1173 d ? cursor_on : 0); 1174 #endif 1175 } 1176 return 0; 1177 case WSDISPLAYIO_GVIDEO: 1178 *(int *)data = rpi_video_on; 1179 return 0; 1180 #if defined(RPI_HWCURSOR) 1181 case WSDISPLAYIO_GCURPOS: 1182 { 1183 struct wsdisplay_curpos *cp = (void *)data; 1184 1185 cp->x = cursor_x; 1186 cp->y = cursor_y; 1187 } 1188 return 0; 1189 case WSDISPLAYIO_SCURPOS: 1190 { 1191 struct wsdisplay_curpos *cp = (void *)data; 1192 1193 cursor_x = cp->x; 1194 cursor_y = cp->y; 1195 rpi_fb_movecursor(cursor_x, cursor_y, cursor_on); 1196 } 1197 return 0; 1198 case WSDISPLAYIO_GCURMAX: 1199 { 1200 struct wsdisplay_curpos *cp = (void *)data; 1201 1202 cp->x = 64; 1203 cp->y = 64; 1204 } 1205 return 0; 1206 case WSDISPLAYIO_SCURSOR: 1207 { 1208 struct wsdisplay_cursor *cursor = (void *)data; 1209 1210 return rpi_fb_do_cursor(cursor); 1211 } 1212 #endif 1213 default: 1214 return EPASSTHROUGH; 1215 } 1216 } 1217 1218 #endif 1219 1220 SYSCTL_SETUP(sysctl_machdep_rpi, "sysctl machdep subtree setup (rpi)") 1221 { 1222 sysctl_createv(clog, 0, NULL, NULL, 1223 CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL, 1224 NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL); 1225 1226 sysctl_createv(clog, 0, NULL, NULL, 1227 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 1228 CTLTYPE_INT, "firmware_revision", NULL, NULL, 0, 1229 &vb.vbt_fwrev.rev, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL); 1230 1231 sysctl_createv(clog, 0, NULL, NULL, 1232 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 1233 CTLTYPE_INT, "board_model", NULL, NULL, 0, 1234 &vb.vbt_boardmodel.model, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL); 1235 1236 sysctl_createv(clog, 0, NULL, NULL, 1237 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 1238 CTLTYPE_INT, "board_revision", NULL, NULL, 0, 1239 &vb.vbt_boardrev.rev, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL); 1240 1241 sysctl_createv(clog, 0, NULL, NULL, 1242 CTLFLAG_PERMANENT|CTLFLAG_READONLY|CTLFLAG_HEX|CTLFLAG_PRIVATE, 1243 CTLTYPE_QUAD, "serial", NULL, NULL, 0, 1244 &vb.vbt_serial.sn, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL); 1245 } 1246 1247 #if defined(SOC_BCM2835) 1248 static void 1249 bcm2835_platform_bootstrap(void) 1250 { 1251 1252 bcm2835_bs_tag = arm_generic_bs_tag; 1253 bcm2835_a4x_bs_tag = arm_generic_a4x_bs_tag; 1254 1255 bcm2835_bs_tag.bs_map = bcm2835_bs_map; 1256 bcm2835_bs_tag.bs_mmap = bcm2835_bs_mmap; 1257 bcm2835_a4x_bs_tag.bs_map = bcm2835_bs_map; 1258 bcm2835_a4x_bs_tag.bs_mmap = bcm2835_a4x_bs_mmap; 1259 1260 fdtbus_set_decoderegprop(false); 1261 1262 bcm2835_uartinit(); 1263 1264 bcm2835_bootparams(); 1265 } 1266 #endif 1267 1268 #if defined(SOC_BCM2836) 1269 static void 1270 bcm2836_platform_bootstrap(void) 1271 { 1272 1273 bcm2836_bs_tag = arm_generic_bs_tag; 1274 bcm2836_a4x_bs_tag = arm_generic_a4x_bs_tag; 1275 1276 bcm2836_bs_tag.bs_map = bcm2836_bs_map; 1277 bcm2836_bs_tag.bs_mmap = bcm2836_bs_mmap; 1278 bcm2836_a4x_bs_tag.bs_map = bcm2836_bs_map; 1279 bcm2836_a4x_bs_tag.bs_mmap = bcm2836_a4x_bs_mmap; 1280 1281 fdtbus_set_decoderegprop(false); 1282 1283 bcm2836_uartinit(); 1284 1285 bcm2836_bootparams(); 1286 1287 #ifdef MULTIPROCESSOR 1288 arm_cpu_max = RPI_CPU_MAX; 1289 arm_fdt_cpu_bootstrap(); 1290 #endif 1291 } 1292 1293 static void 1294 bcm2711_platform_bootstrap(void) 1295 { 1296 1297 bcm2711_bs_tag = arm_generic_bs_tag; 1298 bcm2711_a4x_bs_tag = arm_generic_a4x_bs_tag; 1299 1300 bcm2711_bs_tag.bs_map = bcm2711_bs_map; 1301 bcm2711_bs_tag.bs_mmap = bcm2711_bs_mmap; 1302 bcm2711_a4x_bs_tag.bs_map = bcm2711_bs_map; 1303 bcm2711_a4x_bs_tag.bs_mmap = bcm2711_a4x_bs_mmap; 1304 1305 fdtbus_set_decoderegprop(false); 1306 1307 bcm2711_uartinit(); 1308 1309 bcm2711_bootparams(); 1310 1311 #ifdef MULTIPROCESSOR 1312 arm_cpu_max = RPI_CPU_MAX; 1313 arm_fdt_cpu_bootstrap(); 1314 #endif 1315 } 1316 #endif 1317 1318 #if defined(SOC_BCM2835) 1319 static void 1320 bcm2835_platform_init_attach_args(struct fdt_attach_args *faa) 1321 { 1322 1323 faa->faa_bst = &bcm2835_bs_tag; 1324 } 1325 #endif 1326 1327 #if defined(SOC_BCM2836) 1328 static void 1329 bcm2836_platform_init_attach_args(struct fdt_attach_args *faa) 1330 { 1331 1332 faa->faa_bst = &bcm2836_bs_tag; 1333 } 1334 1335 static void 1336 bcm2711_platform_init_attach_args(struct fdt_attach_args *faa) 1337 { 1338 1339 faa->faa_bst = &bcm2711_bs_tag; 1340 } 1341 #endif 1342 1343 1344 static void __noasan 1345 bcm283x_platform_early_putchar(vaddr_t va, paddr_t pa, char c) 1346 { 1347 volatile uint32_t *uartaddr = 1348 cpu_earlydevice_va_p() ? 1349 (volatile uint32_t *)va : 1350 (volatile uint32_t *)pa; 1351 1352 while ((le32toh(uartaddr[PL01XCOM_FR / 4]) & PL01X_FR_TXFF) != 0) 1353 continue; 1354 1355 uartaddr[PL01XCOM_DR / 4] = htole32(c); 1356 1357 while ((le32toh(uartaddr[PL01XCOM_FR / 4]) & PL01X_FR_TXFE) == 0) 1358 continue; 1359 } 1360 1361 static void __noasan 1362 bcm283x_aux_platform_early_putchar(vaddr_t va, paddr_t pa, char c) 1363 { 1364 volatile uint32_t *uartaddr = 1365 cpu_earlydevice_va_p() ? 1366 (volatile uint32_t *)va : 1367 (volatile uint32_t *)pa; 1368 1369 while ((le32toh(uartaddr[com_lsr]) & LSR_TXRDY) == 0) 1370 continue; 1371 1372 uartaddr[com_data] = htole32(c); 1373 } 1374 1375 void __noasan 1376 bcm2835_platform_early_putchar(char c) 1377 { 1378 paddr_t pa = BCM2835_PERIPHERALS_BUS_TO_PHYS(BCM2835_UART0_BASE); 1379 vaddr_t va = BCM2835_IOPHYSTOVIRT(pa); 1380 1381 bcm283x_platform_early_putchar(va, pa, c); 1382 } 1383 1384 void __noasan 1385 bcm2835_aux_platform_early_putchar(char c) 1386 { 1387 paddr_t pa = BCM2835_PERIPHERALS_BUS_TO_PHYS(BCM2835_AUX_UART_BASE); 1388 vaddr_t va = BCM2835_IOPHYSTOVIRT(pa); 1389 1390 bcm283x_aux_platform_early_putchar(va, pa, c); 1391 } 1392 1393 void __noasan 1394 bcm2836_platform_early_putchar(char c) 1395 { 1396 paddr_t pa = BCM2836_PERIPHERALS_BUS_TO_PHYS(BCM2835_UART0_BASE); 1397 vaddr_t va = BCM2835_IOPHYSTOVIRT(pa); 1398 1399 bcm283x_platform_early_putchar(va, pa, c); 1400 } 1401 1402 void __noasan 1403 bcm2837_platform_early_putchar(char c) 1404 { 1405 paddr_t pa = BCM2836_PERIPHERALS_BUS_TO_PHYS(BCM2835_AUX_UART_BASE); 1406 vaddr_t va = BCM2835_IOPHYSTOVIRT(pa); 1407 1408 bcm283x_aux_platform_early_putchar(va, pa, c); 1409 } 1410 1411 void __noasan 1412 bcm2711_platform_early_putchar(char c) 1413 { 1414 paddr_t pa = BCM2711_PERIPHERALS_BUS_TO_PHYS(BCM2835_AUX_UART_BASE); 1415 vaddr_t va = BCM2711_IOPHYSTOVIRT(pa); 1416 1417 bcm283x_aux_platform_early_putchar(va, pa, c); 1418 } 1419 1420 #define BCM283x_REF_FREQ 19200000 1421 1422 static void 1423 bcm283x_platform_device_register(device_t dev, void *aux) 1424 { 1425 prop_dictionary_t dict = device_properties(dev); 1426 1427 if (device_is_a(dev, "bcmdmac") && 1428 vcprop_tag_success_p(&vb.vbt_dmachan.tag)) { 1429 prop_dictionary_set_uint32(dict, 1430 "chanmask", le32toh(vb.vbt_dmachan.mask)); 1431 } 1432 #if NSDHC > 0 1433 if (booted_device == NULL && 1434 device_is_a(dev, "ld") && 1435 device_is_a(device_parent(dev), "sdmmc")) { 1436 booted_partition = 0; 1437 booted_device = dev; 1438 } 1439 #endif 1440 if ((device_is_a(dev, "usmsc") || 1441 device_is_a(dev, "mue") || 1442 device_is_a(dev, "genet")) && 1443 vcprop_tag_success_p(&vb.vbt_macaddr.tag)) { 1444 const uint64_t addr = le64toh(vb.vbt_macaddr.addr); 1445 const uint8_t enaddr[ETHER_ADDR_LEN] = { 1446 (addr >> 0) & 0xff, (addr >> 8) & 0xff, 1447 (addr >> 16) & 0xff, (addr >> 24) & 0xff, 1448 (addr >> 32) & 0xff, (addr >> 40) & 0xff 1449 }; 1450 1451 prop_dictionary_set_data(dict, "mac-address", enaddr, 1452 ETHER_ADDR_LEN); 1453 } 1454 1455 #if NGENFB > 0 1456 if (device_is_a(dev, "genfb")) { 1457 char *ptr; 1458 1459 bcmgenfb_set_console_dev(dev); 1460 bcmgenfb_set_ioctl(&rpi_ioctl); 1461 #ifdef DDB 1462 db_trap_callback = bcmgenfb_ddb_trap_callback; 1463 #endif 1464 if (rpi_fb_init(dict, aux) == false) 1465 return; 1466 if (get_bootconf_option(boot_args, "console", 1467 BOOTOPT_TYPE_STRING, &ptr) && strncmp(ptr, "fb", 2) == 0) { 1468 prop_dictionary_set_bool(dict, "is_console", true); 1469 #if NUKBD > 0 1470 /* allow ukbd to be the console keyboard */ 1471 ukbd_cnattach(); 1472 #endif 1473 } else { 1474 prop_dictionary_set_bool(dict, "is_console", false); 1475 } 1476 } 1477 #endif 1478 } 1479 1480 static u_int 1481 bcm283x_platform_uart_freq(void) 1482 { 1483 1484 /* 1485 * We are safe to access stdout phandle - consinit did before 1486 * calling fp_uart_freq 1487 */ 1488 const int phandle = fdtbus_get_stdout_phandle(); 1489 1490 static const struct device_compatible_entry aux_compat_data[] = { 1491 { .compat = "brcm,bcm2835-aux-uart" }, 1492 DEVICE_COMPAT_EOL 1493 }; 1494 1495 if (of_compatible_match(phandle, aux_compat_data)) 1496 return core_clk * 2; 1497 1498 return uart_clk; 1499 } 1500 1501 #if defined(SOC_BCM2835) 1502 static const struct fdt_platform bcm2835_platform = { 1503 .fp_devmap = bcm2835_platform_devmap, 1504 .fp_bootstrap = bcm2835_platform_bootstrap, 1505 .fp_init_attach_args = bcm2835_platform_init_attach_args, 1506 .fp_device_register = bcm283x_platform_device_register, 1507 .fp_reset = bcm2835_system_reset, 1508 .fp_delay = bcm2835_tmr_delay, 1509 .fp_uart_freq = bcm283x_platform_uart_freq, 1510 }; 1511 1512 FDT_PLATFORM(bcm2835, "brcm,bcm2835", &bcm2835_platform); 1513 #endif 1514 1515 #if defined(SOC_BCM2836) 1516 1517 static const struct fdt_platform bcm2836_platform = { 1518 .fp_devmap = bcm2836_platform_devmap, 1519 .fp_bootstrap = bcm2836_platform_bootstrap, 1520 .fp_init_attach_args = bcm2836_platform_init_attach_args, 1521 .fp_device_register = bcm283x_platform_device_register, 1522 .fp_reset = bcm2835_system_reset, 1523 .fp_delay = gtmr_delay, 1524 .fp_uart_freq = bcm283x_platform_uart_freq, 1525 .fp_mpstart = arm_fdt_cpu_mpstart, 1526 }; 1527 1528 static const struct fdt_platform bcm2837_platform = { 1529 .fp_devmap = bcm2836_platform_devmap, 1530 .fp_bootstrap = bcm2836_platform_bootstrap, 1531 .fp_init_attach_args = bcm2836_platform_init_attach_args, 1532 .fp_device_register = bcm283x_platform_device_register, 1533 .fp_reset = bcm2835_system_reset, 1534 .fp_delay = gtmr_delay, 1535 .fp_uart_freq = bcm283x_platform_uart_freq, 1536 .fp_mpstart = arm_fdt_cpu_mpstart, 1537 }; 1538 1539 static const struct fdt_platform bcm2711_platform = { 1540 .fp_devmap = bcm2711_platform_devmap, 1541 .fp_bootstrap = bcm2711_platform_bootstrap, 1542 .fp_init_attach_args = bcm2711_platform_init_attach_args, 1543 .fp_device_register = bcm283x_platform_device_register, 1544 .fp_reset = bcm2835_system_reset, 1545 .fp_delay = gtmr_delay, 1546 .fp_uart_freq = bcm283x_platform_uart_freq, 1547 .fp_mpstart = arm_fdt_cpu_mpstart, 1548 }; 1549 1550 FDT_PLATFORM(bcm2836, "brcm,bcm2836", &bcm2836_platform); 1551 FDT_PLATFORM(bcm2837, "brcm,bcm2837", &bcm2837_platform); 1552 FDT_PLATFORM(bcm2711, "brcm,bcm2711", &bcm2711_platform); 1553 #endif 1554