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