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