1 /* $NetBSD: bcm283x_platform.c,v 1.55 2026/04/26 12:49:51 tsutsui 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.55 2026/04/26 12:49:51 tsutsui 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 876 static int 877 cpu_enable_bcm2711(int phandle) 878 { 879 bus_space_tag_t iot = &bcm2711_bs_tag; 880 bus_space_handle_t ioh = BCM2711_ARM_LOCAL_VBASE; 881 uint64_t mpidr; 882 883 fdtbus_get_reg64(phandle, 0, &mpidr, NULL); 884 885 const u_int cpuno = __SHIFTOUT(mpidr, MPIDR_AFF0); 886 887 bus_space_write_4(iot, ioh, BCM2836_LOCAL_MAILBOX3_SETN(cpuno), 888 KERN_VTOPHYS((vaddr_t)cpu_mpstart)); 889 890 return 0; 891 } 892 ARM_CPU_METHOD(bcm2836, "brcm,bcm2836-smp", cpu_enable_bcm2836); 893 /* patched in src/sys/arch/arm/dts/bcm2711-cpus.dtsi */ 894 ARM_CPU_METHOD(bcm2711, "brcm,bcm2711-smp", cpu_enable_bcm2711); 895 #endif 896 897 #endif /* SOC_BCM2836 */ 898 899 #if NGENFB > 0 900 static bool 901 rpi_fb_parse_mode(const char *s, uint32_t *pwidth, uint32_t *pheight) 902 { 903 char *x; 904 905 if (strncmp(s, "disable", 7) == 0) 906 return false; 907 908 x = strchr(s, 'x'); 909 if (x) { 910 *pwidth = strtoul(s, NULL, 10); 911 *pheight = strtoul(x + 1, NULL, 10); 912 } 913 914 return true; 915 } 916 917 #define RPI_EDIDSIZE 1024 918 919 static bool 920 rpi_fb_get_edid_mode(uint32_t *pwidth, uint32_t *pheight) 921 { 922 struct edid_info ei; 923 uint32_t res; 924 int error; 925 926 error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_edid, 927 sizeof(vb_edid), &res); 928 if (error) { 929 printf("%s: mbox request failed (%d)\n", __func__, error); 930 return false; 931 } 932 933 if (!vcprop_buffer_success_p(&vb_edid.vb_hdr) || 934 !vcprop_tag_success_p(&vb_edid.vbt_edid.tag) || 935 vb_edid.vbt_edid.status != 0) 936 return false; 937 938 uint8_t *edid_data = kmem_alloc(RPI_EDIDSIZE, KM_SLEEP); 939 940 memset(edid_data, 0, RPI_EDIDSIZE); 941 memcpy(edid_data, vb_edid.vbt_edid.data, 942 sizeof(vb_edid.vbt_edid.data)); 943 edid_parse(edid_data, &ei); 944 #ifdef VERBOSE_INIT_ARM 945 edid_print(&ei); 946 #endif 947 948 if (ei.edid_preferred_mode) { 949 *pwidth = ei.edid_preferred_mode->hdisplay; 950 *pheight = ei.edid_preferred_mode->vdisplay; 951 } 952 953 kmem_free(edid_data, RPI_EDIDSIZE); 954 955 return true; 956 } 957 958 /* 959 * Initialize framebuffer console. 960 * 961 * Some notes about boot parameters: 962 * - If "fb=disable" is present, ignore framebuffer completely. 963 * - If "fb=<width>x<height> is present, use the specified mode. 964 * - If "console=fb" is present, attach framebuffer to console. 965 */ 966 static bool 967 rpi_fb_init(prop_dictionary_t dict, void *aux) 968 { 969 uint32_t width = 0, height = 0; 970 uint32_t res; 971 char *ptr; 972 int integer; 973 int error; 974 bool is_bgr = true; 975 976 if (get_bootconf_option(boot_args, "fb", 977 BOOTOPT_TYPE_STRING, &ptr)) { 978 if (rpi_fb_parse_mode(ptr, &width, &height) == false) 979 return false; 980 } 981 if (width == 0 || height == 0) { 982 rpi_fb_get_edid_mode(&width, &height); 983 } 984 if (width == 0 || height == 0) { 985 width = RPI_FB_WIDTH; 986 height = RPI_FB_HEIGHT; 987 } 988 989 vb_setfb.vbt_res.width = htole32(width); 990 vb_setfb.vbt_res.height = htole32(height); 991 vb_setfb.vbt_vres.width = htole32(width); 992 vb_setfb.vbt_vres.height = htole32(height); 993 error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_setfb, 994 sizeof(vb_setfb), &res); 995 if (error) { 996 printf("%s: mbox request failed (%d)\n", __func__, error); 997 return false; 998 } 999 1000 if (!vcprop_buffer_success_p(&vb_setfb.vb_hdr) || 1001 !vcprop_tag_success_p(&vb_setfb.vbt_res.tag) || 1002 !vcprop_tag_success_p(&vb_setfb.vbt_vres.tag) || 1003 !vcprop_tag_success_p(&vb_setfb.vbt_depth.tag) || 1004 !vcprop_tag_success_p(&vb_setfb.vbt_allocbuf.tag) || 1005 !vcprop_tag_success_p(&vb_setfb.vbt_blank.tag) || 1006 !vcprop_tag_success_p(&vb_setfb.vbt_pitch.tag)) { 1007 printf("%s: prop tag failed\n", __func__); 1008 return false; 1009 } 1010 1011 #ifdef VERBOSE_INIT_ARM 1012 printf("%s: addr = 0x%x size = %d\n", __func__, 1013 le32toh(vb_setfb.vbt_allocbuf.address), 1014 le32toh(vb_setfb.vbt_allocbuf.size)); 1015 printf("%s: depth = %d\n", __func__, le32toh(vb_setfb.vbt_depth.bpp)); 1016 printf("%s: pitch = %d\n", __func__, 1017 le32toh(vb_setfb.vbt_pitch.linebytes)); 1018 printf("%s: width = %d height = %d\n", __func__, 1019 le32toh(vb_setfb.vbt_res.width), le32toh(vb_setfb.vbt_res.height)); 1020 printf("%s: vwidth = %d vheight = %d\n", __func__, 1021 le32toh(vb_setfb.vbt_vres.width), 1022 le32toh(vb_setfb.vbt_vres.height)); 1023 #endif 1024 1025 if (vb_setfb.vbt_allocbuf.address == 0 || 1026 vb_setfb.vbt_allocbuf.size == 0 || 1027 vb_setfb.vbt_res.width == 0 || 1028 vb_setfb.vbt_res.height == 0 || 1029 vb_setfb.vbt_vres.width == 0 || 1030 vb_setfb.vbt_vres.height == 0 || 1031 vb_setfb.vbt_pitch.linebytes == 0) { 1032 printf("%s: failed to set mode %ux%u\n", __func__, 1033 width, height); 1034 return false; 1035 } 1036 1037 prop_dictionary_set_uint32(dict, "width", 1038 le32toh(vb_setfb.vbt_res.width)); 1039 prop_dictionary_set_uint32(dict, "height", 1040 le32toh(vb_setfb.vbt_res.height)); 1041 prop_dictionary_set_uint8(dict, "depth", 1042 le32toh(vb_setfb.vbt_depth.bpp)); 1043 prop_dictionary_set_uint16(dict, "linebytes", 1044 le32toh(vb_setfb.vbt_pitch.linebytes)); 1045 prop_dictionary_set_uint32(dict, "address", 1046 le32toh(vb_setfb.vbt_allocbuf.address)); 1047 1048 /* 1049 * Old firmware uses BGR. New firmware uses RGB. The get and set 1050 * pixel order mailbox properties don't seem to work. The firmware 1051 * adds a kernel cmdline option bcm2708_fb.fbswap=<0|1>, so use it 1052 * to determine pixel order. 0 means BGR, 1 means RGB. 1053 * 1054 * See https://github.com/raspberrypi/linux/issues/514 1055 */ 1056 if (get_bootconf_option(boot_args, "bcm2708_fb.fbswap", 1057 BOOTOPT_TYPE_INT, &integer)) { 1058 is_bgr = integer == 0; 1059 } 1060 prop_dictionary_set_bool(dict, "is_bgr", is_bgr); 1061 1062 /* if "genfb.type=<n>" is passed in cmdline, override wsdisplay type */ 1063 if (get_bootconf_option(boot_args, "genfb.type", 1064 BOOTOPT_TYPE_INT, &integer)) { 1065 prop_dictionary_set_uint32(dict, "wsdisplay_type", integer); 1066 } 1067 1068 #if defined(RPI_HWCURSOR) 1069 struct fdt_attach_args *faa = aux; 1070 bus_space_handle_t hc; 1071 1072 hcursor = rpi_alloc_mem(CURSOR_ARGB_SIZE, PAGE_SIZE, 1073 MEM_FLAG_L1_NONALLOCATING | MEM_FLAG_HINT_PERMALOCK); 1074 pcursor = rpi_lock_mem(hcursor); 1075 #ifdef RPI_IOCTL_DEBUG 1076 printf("hcursor: %08x\n", hcursor); 1077 printf("pcursor: %08x\n", (uint32_t)pcursor); 1078 printf("fb: %08x\n", (uint32_t)vb_setfb.vbt_allocbuf.address); 1079 #endif 1080 if (bus_space_map(faa->faa_bst, pcursor, CURSOR_ARGB_SIZE, 1081 BUS_SPACE_MAP_LINEAR|BUS_SPACE_MAP_PREFETCHABLE, &hc) != 0) { 1082 printf("couldn't map cursor memory\n"); 1083 } else { 1084 int i, j, k; 1085 1086 cmem = bus_space_vaddr(faa->faa_bst, hc); 1087 k = 0; 1088 for (j = 0; j < 64; j++) { 1089 for (i = 0; i < 64; i++) { 1090 cmem[i + k] = 1091 ((i & 8) ^ (j & 8)) ? 0xa0ff0000 : 0xa000ff00; 1092 } 1093 k += 64; 1094 } 1095 cpu_dcache_wb_range((vaddr_t)cmem, CURSOR_ARGB_SIZE); 1096 rpi_fb_initcursor(pcursor, 0, 0); 1097 #ifdef RPI_IOCTL_DEBUG 1098 rpi_fb_movecursor(600, 400, 1); 1099 #else 1100 rpi_fb_movecursor(cursor_x, cursor_y, cursor_on); 1101 #endif 1102 } 1103 #endif 1104 1105 return true; 1106 } 1107 1108 1109 #if defined(RPI_HWCURSOR) 1110 static int 1111 rpi_fb_do_cursor(struct wsdisplay_cursor *cur) 1112 { 1113 int pos = 0; 1114 int shape = 0; 1115 1116 if (cur->which & WSDISPLAY_CURSOR_DOCUR) { 1117 if (cursor_on != cur->enable) { 1118 cursor_on = cur->enable; 1119 pos = 1; 1120 } 1121 } 1122 if (cur->which & WSDISPLAY_CURSOR_DOHOT) { 1123 1124 hot_x = cur->hot.x; 1125 hot_y = cur->hot.y; 1126 pos = 1; 1127 shape = 1; 1128 } 1129 if (cur->which & WSDISPLAY_CURSOR_DOPOS) { 1130 1131 cursor_x = cur->pos.x; 1132 cursor_y = cur->pos.y; 1133 pos = 1; 1134 } 1135 if (cur->which & WSDISPLAY_CURSOR_DOCMAP) { 1136 int i; 1137 uint32_t val; 1138 1139 for (i = 0; i < uimin(cur->cmap.count, 3); i++) { 1140 val = (cur->cmap.red[i] << 16 ) | 1141 (cur->cmap.green[i] << 8) | 1142 (cur->cmap.blue[i] ) | 1143 0xff000000; 1144 cursor_cmap[i + cur->cmap.index + 2] = val; 1145 } 1146 shape = 1; 1147 } 1148 if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) { 1149 int err; 1150 1151 err = copyin(cur->mask, cursor_mask, CURSOR_BITMAP_SIZE); 1152 err += copyin(cur->image, cursor_bitmap, CURSOR_BITMAP_SIZE); 1153 if (err != 0) 1154 return EFAULT; 1155 shape = 1; 1156 } 1157 if (shape) { 1158 int i, j, idx; 1159 uint8_t mask; 1160 1161 for (i = 0; i < CURSOR_BITMAP_SIZE; i++) { 1162 mask = 0x01; 1163 for (j = 0; j < 8; j++) { 1164 idx = ((cursor_mask[i] & mask) ? 2 : 0) | 1165 ((cursor_bitmap[i] & mask) ? 1 : 0); 1166 cmem[i * 8 + j] = cursor_cmap[idx]; 1167 mask = mask << 1; 1168 } 1169 } 1170 /* just in case */ 1171 cpu_dcache_wb_range((vaddr_t)cmem, CURSOR_ARGB_SIZE); 1172 rpi_fb_initcursor(pcursor, hot_x, hot_y); 1173 } 1174 if (pos) { 1175 rpi_fb_movecursor(cursor_x, cursor_y, cursor_on); 1176 } 1177 return 0; 1178 } 1179 #endif 1180 1181 static int 1182 rpi_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, lwp_t *l) 1183 { 1184 1185 switch (cmd) { 1186 case WSDISPLAYIO_SVIDEO: 1187 { 1188 int d = *(int *)data; 1189 if (d == rpi_video_on) 1190 return 0; 1191 rpi_video_on = d; 1192 rpi_fb_set_video(d); 1193 #if defined(RPI_HWCURSOR) 1194 rpi_fb_movecursor(cursor_x, cursor_y, 1195 d ? cursor_on : 0); 1196 #endif 1197 } 1198 return 0; 1199 case WSDISPLAYIO_GVIDEO: 1200 *(int *)data = rpi_video_on; 1201 return 0; 1202 #if defined(RPI_HWCURSOR) 1203 case WSDISPLAYIO_GCURPOS: 1204 { 1205 struct wsdisplay_curpos *cp = (void *)data; 1206 1207 cp->x = cursor_x; 1208 cp->y = cursor_y; 1209 } 1210 return 0; 1211 case WSDISPLAYIO_SCURPOS: 1212 { 1213 struct wsdisplay_curpos *cp = (void *)data; 1214 1215 cursor_x = cp->x; 1216 cursor_y = cp->y; 1217 rpi_fb_movecursor(cursor_x, cursor_y, cursor_on); 1218 } 1219 return 0; 1220 case WSDISPLAYIO_GCURMAX: 1221 { 1222 struct wsdisplay_curpos *cp = (void *)data; 1223 1224 cp->x = 64; 1225 cp->y = 64; 1226 } 1227 return 0; 1228 case WSDISPLAYIO_SCURSOR: 1229 { 1230 struct wsdisplay_cursor *cursor = (void *)data; 1231 1232 return rpi_fb_do_cursor(cursor); 1233 } 1234 #endif 1235 default: 1236 return EPASSTHROUGH; 1237 } 1238 } 1239 1240 #endif 1241 1242 SYSCTL_SETUP(sysctl_machdep_rpi, "sysctl machdep subtree setup (rpi)") 1243 { 1244 sysctl_createv(clog, 0, NULL, NULL, 1245 CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL, 1246 NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL); 1247 1248 sysctl_createv(clog, 0, NULL, NULL, 1249 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 1250 CTLTYPE_INT, "firmware_revision", NULL, NULL, 0, 1251 &vb.vbt_fwrev.rev, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL); 1252 1253 sysctl_createv(clog, 0, NULL, NULL, 1254 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 1255 CTLTYPE_INT, "board_model", NULL, NULL, 0, 1256 &vb.vbt_boardmodel.model, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL); 1257 1258 sysctl_createv(clog, 0, NULL, NULL, 1259 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 1260 CTLTYPE_INT, "board_revision", NULL, NULL, 0, 1261 &vb.vbt_boardrev.rev, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL); 1262 1263 sysctl_createv(clog, 0, NULL, NULL, 1264 CTLFLAG_PERMANENT|CTLFLAG_READONLY|CTLFLAG_HEX|CTLFLAG_PRIVATE, 1265 CTLTYPE_QUAD, "serial", NULL, NULL, 0, 1266 &vb_serial, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL); 1267 } 1268 1269 #if defined(SOC_BCM2835) 1270 static void 1271 bcm2835_platform_bootstrap(void) 1272 { 1273 1274 bcm2835_bs_tag = arm_generic_bs_tag; 1275 bcm2835_a4x_bs_tag = arm_generic_a4x_bs_tag; 1276 1277 bcm2835_bs_tag.bs_map = bcm2835_bs_map; 1278 bcm2835_bs_tag.bs_mmap = bcm2835_bs_mmap; 1279 bcm2835_a4x_bs_tag.bs_map = bcm2835_bs_map; 1280 bcm2835_a4x_bs_tag.bs_mmap = bcm2835_a4x_bs_mmap; 1281 1282 fdtbus_set_decoderegprop(false); 1283 1284 bcm2835_uartinit(); 1285 1286 bcm2835_bootparams(); 1287 } 1288 #endif 1289 1290 #if defined(SOC_BCM2836) 1291 static void 1292 bcm2836_platform_bootstrap(void) 1293 { 1294 1295 bcm2836_bs_tag = arm_generic_bs_tag; 1296 bcm2836_a4x_bs_tag = arm_generic_a4x_bs_tag; 1297 1298 bcm2836_bs_tag.bs_map = bcm2836_bs_map; 1299 bcm2836_bs_tag.bs_mmap = bcm2836_bs_mmap; 1300 bcm2836_a4x_bs_tag.bs_map = bcm2836_bs_map; 1301 bcm2836_a4x_bs_tag.bs_mmap = bcm2836_a4x_bs_mmap; 1302 1303 fdtbus_set_decoderegprop(false); 1304 1305 bcm2836_uartinit(); 1306 1307 bcm2836_bootparams(); 1308 1309 #ifdef MULTIPROCESSOR 1310 arm_cpu_max = RPI_CPU_MAX; 1311 arm_fdt_cpu_bootstrap(); 1312 #endif 1313 } 1314 1315 static void 1316 bcm2711_platform_bootstrap(void) 1317 { 1318 1319 bcm2711_bs_tag = arm_generic_bs_tag; 1320 bcm2711_a4x_bs_tag = arm_generic_a4x_bs_tag; 1321 1322 bcm2711_bs_tag.bs_map = bcm2711_bs_map; 1323 bcm2711_bs_tag.bs_mmap = bcm2711_bs_mmap; 1324 bcm2711_a4x_bs_tag.bs_map = bcm2711_bs_map; 1325 bcm2711_a4x_bs_tag.bs_mmap = bcm2711_a4x_bs_mmap; 1326 1327 fdtbus_set_decoderegprop(false); 1328 1329 bcm2711_uartinit(); 1330 1331 bcm2711_bootparams(); 1332 1333 #ifdef MULTIPROCESSOR 1334 arm_cpu_max = RPI_CPU_MAX; 1335 arm_fdt_cpu_bootstrap(); 1336 #endif 1337 } 1338 #endif 1339 1340 #if defined(SOC_BCM2835) 1341 static void 1342 bcm2835_platform_init_attach_args(struct fdt_attach_args *faa) 1343 { 1344 1345 faa->faa_bst = &bcm2835_bs_tag; 1346 } 1347 #endif 1348 1349 #if defined(SOC_BCM2836) 1350 static void 1351 bcm2836_platform_init_attach_args(struct fdt_attach_args *faa) 1352 { 1353 1354 faa->faa_bst = &bcm2836_bs_tag; 1355 } 1356 1357 static void 1358 bcm2711_platform_init_attach_args(struct fdt_attach_args *faa) 1359 { 1360 1361 faa->faa_bst = &bcm2711_bs_tag; 1362 } 1363 #endif 1364 1365 1366 static void __noasan 1367 bcm283x_platform_early_putchar(vaddr_t va, paddr_t pa, char c) 1368 { 1369 volatile uint32_t *uartaddr = 1370 cpu_earlydevice_va_p() ? 1371 (volatile uint32_t *)va : 1372 (volatile uint32_t *)pa; 1373 1374 while ((le32toh(uartaddr[PL01XCOM_FR / 4]) & PL01X_FR_TXFF) != 0) 1375 continue; 1376 1377 uartaddr[PL01XCOM_DR / 4] = htole32(c); 1378 1379 while ((le32toh(uartaddr[PL01XCOM_FR / 4]) & PL01X_FR_TXFE) == 0) 1380 continue; 1381 } 1382 1383 static void __noasan 1384 bcm283x_aux_platform_early_putchar(vaddr_t va, paddr_t pa, char c) 1385 { 1386 volatile uint32_t *uartaddr = 1387 cpu_earlydevice_va_p() ? 1388 (volatile uint32_t *)va : 1389 (volatile uint32_t *)pa; 1390 1391 while ((le32toh(uartaddr[com_lsr]) & LSR_TXRDY) == 0) 1392 continue; 1393 1394 uartaddr[com_data] = htole32(c); 1395 } 1396 1397 void __noasan 1398 bcm2835_platform_early_putchar(char c) 1399 { 1400 paddr_t pa = BCM2835_PERIPHERALS_BUS_TO_PHYS(BCM2835_UART0_BASE); 1401 vaddr_t va = BCM2835_IOPHYSTOVIRT(pa); 1402 1403 bcm283x_platform_early_putchar(va, pa, c); 1404 } 1405 1406 void __noasan 1407 bcm2835_aux_platform_early_putchar(char c) 1408 { 1409 paddr_t pa = BCM2835_PERIPHERALS_BUS_TO_PHYS(BCM2835_AUX_UART_BASE); 1410 vaddr_t va = BCM2835_IOPHYSTOVIRT(pa); 1411 1412 bcm283x_aux_platform_early_putchar(va, pa, c); 1413 } 1414 1415 void __noasan 1416 bcm2836_platform_early_putchar(char c) 1417 { 1418 paddr_t pa = BCM2836_PERIPHERALS_BUS_TO_PHYS(BCM2835_UART0_BASE); 1419 vaddr_t va = BCM2835_IOPHYSTOVIRT(pa); 1420 1421 bcm283x_platform_early_putchar(va, pa, c); 1422 } 1423 1424 void __noasan 1425 bcm2837_platform_early_putchar(char c) 1426 { 1427 paddr_t pa = BCM2836_PERIPHERALS_BUS_TO_PHYS(BCM2835_AUX_UART_BASE); 1428 vaddr_t va = BCM2835_IOPHYSTOVIRT(pa); 1429 1430 bcm283x_aux_platform_early_putchar(va, pa, c); 1431 } 1432 1433 void __noasan 1434 bcm2711_platform_early_putchar(char c) 1435 { 1436 paddr_t pa = BCM2711_PERIPHERALS_BUS_TO_PHYS(BCM2835_AUX_UART_BASE); 1437 vaddr_t va = BCM2711_IOPHYSTOVIRT(pa); 1438 1439 bcm283x_aux_platform_early_putchar(va, pa, c); 1440 } 1441 1442 #define BCM283x_REF_FREQ 19200000 1443 1444 static void 1445 bcm283x_platform_device_register(device_t dev, void *aux) 1446 { 1447 prop_dictionary_t dict = device_properties(dev); 1448 1449 if (device_is_a(dev, "bcmdmac") && 1450 vcprop_tag_success_p(&vb.vbt_dmachan.tag)) { 1451 prop_dictionary_set_uint32(dict, 1452 "chanmask", le32toh(vb.vbt_dmachan.mask)); 1453 } 1454 #if NSDHC > 0 1455 if (booted_device == NULL && 1456 device_is_a(dev, "ld") && 1457 device_is_a(device_parent(dev), "sdmmc")) { 1458 booted_partition = 0; 1459 booted_device = dev; 1460 } 1461 #endif 1462 if ((device_is_a(dev, "usmsc") || 1463 device_is_a(dev, "mue") || 1464 device_is_a(dev, "genet")) && 1465 vcprop_tag_success_p(&vb.vbt_macaddr.tag)) { 1466 const uint64_t addr = le64toh(vb.vbt_macaddr.addr); 1467 const uint8_t enaddr[ETHER_ADDR_LEN] = { 1468 (addr >> 0) & 0xff, (addr >> 8) & 0xff, 1469 (addr >> 16) & 0xff, (addr >> 24) & 0xff, 1470 (addr >> 32) & 0xff, (addr >> 40) & 0xff 1471 }; 1472 device_setprop_data(dev, "mac-address", enaddr, 1473 sizeof(enaddr)); 1474 } 1475 1476 #if NGENFB > 0 1477 if (device_is_a(dev, "genfb")) { 1478 char *ptr; 1479 1480 bcmgenfb_set_console_dev(dev); 1481 bcmgenfb_set_ioctl(&rpi_ioctl); 1482 #ifdef DDB 1483 db_trap_callback = bcmgenfb_ddb_trap_callback; 1484 #endif 1485 if (rpi_fb_init(dict, aux) == false) 1486 return; 1487 if (get_bootconf_option(boot_args, "console", 1488 BOOTOPT_TYPE_STRING, &ptr) && strncmp(ptr, "fb", 2) == 0) { 1489 device_setprop_bool(dev, "is_console", true); 1490 #if NUKBD > 0 1491 /* allow ukbd to be the console keyboard */ 1492 ukbd_cnattach(); 1493 #endif 1494 } else { 1495 /* XXX Needed? */ 1496 device_setprop_bool(dev, "is_console", false); 1497 } 1498 } 1499 #endif 1500 } 1501 1502 static u_int 1503 bcm283x_platform_uart_freq(void) 1504 { 1505 1506 /* 1507 * We are safe to access stdout phandle - consinit did before 1508 * calling fp_uart_freq 1509 */ 1510 const int phandle = fdtbus_get_stdout_phandle(); 1511 1512 static const struct device_compatible_entry aux_compat_data[] = { 1513 { .compat = "brcm,bcm2835-aux-uart" }, 1514 DEVICE_COMPAT_EOL 1515 }; 1516 1517 if (of_compatible_match(phandle, aux_compat_data)) 1518 return core_clk * 2; 1519 1520 return uart_clk; 1521 } 1522 1523 #if defined(SOC_BCM2835) 1524 static const struct fdt_platform bcm2835_platform = { 1525 .fp_devmap = bcm2835_platform_devmap, 1526 .fp_bootstrap = bcm2835_platform_bootstrap, 1527 .fp_init_attach_args = bcm2835_platform_init_attach_args, 1528 .fp_device_register = bcm283x_platform_device_register, 1529 .fp_reset = bcm2835_system_reset, 1530 .fp_delay = bcm2835_tmr_delay, 1531 .fp_uart_freq = bcm283x_platform_uart_freq, 1532 }; 1533 1534 FDT_PLATFORM(bcm2835, "brcm,bcm2835", &bcm2835_platform); 1535 #endif 1536 1537 #if defined(SOC_BCM2836) 1538 1539 static const struct fdt_platform bcm2836_platform = { 1540 .fp_devmap = bcm2836_platform_devmap, 1541 .fp_bootstrap = bcm2836_platform_bootstrap, 1542 .fp_init_attach_args = bcm2836_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 static const struct fdt_platform bcm2837_platform = { 1551 .fp_devmap = bcm2836_platform_devmap, 1552 .fp_bootstrap = bcm2836_platform_bootstrap, 1553 .fp_init_attach_args = bcm2836_platform_init_attach_args, 1554 .fp_device_register = bcm283x_platform_device_register, 1555 .fp_reset = bcm2835_system_reset, 1556 .fp_delay = gtmr_delay, 1557 .fp_uart_freq = bcm283x_platform_uart_freq, 1558 .fp_mpstart = arm_fdt_cpu_mpstart, 1559 }; 1560 1561 static const struct fdt_platform bcm2711_platform = { 1562 .fp_devmap = bcm2711_platform_devmap, 1563 .fp_bootstrap = bcm2711_platform_bootstrap, 1564 .fp_init_attach_args = bcm2711_platform_init_attach_args, 1565 .fp_device_register = bcm283x_platform_device_register, 1566 .fp_reset = bcm2835_system_reset, 1567 .fp_delay = gtmr_delay, 1568 .fp_uart_freq = bcm283x_platform_uart_freq, 1569 .fp_mpstart = arm_fdt_cpu_mpstart, 1570 }; 1571 1572 FDT_PLATFORM(bcm2836, "brcm,bcm2836", &bcm2836_platform); 1573 FDT_PLATFORM(bcm2837, "brcm,bcm2837", &bcm2837_platform); 1574 FDT_PLATFORM(bcm2711, "brcm,bcm2711", &bcm2711_platform); 1575 #endif 1576