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