1 /* $NetBSD: bcm283x_platform.c,v 1.8 2018/07/16 23:11:47 christos 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.8 2018/07/16 23:11:47 christos 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 #ifdef __aarch64__ 68 #include <aarch64/machdep.h> 69 #endif 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 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 void bcm283x_platform_early_putchar(vaddr_t, paddr_t, char c); 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 117 extern void bcmgenfb_set_console_dev(device_t dev); 118 void bcmgenfb_set_ioctl(int(*)(void *, void *, u_long, void *, int, struct lwp *)); 119 extern void bcmgenfb_ddb_trap_callback(int where); 120 static int rpi_ioctl(void *, void *, u_long, void *, int, lwp_t *); 121 122 extern struct bus_space arm_generic_bs_tag; 123 extern struct bus_space arm_generic_a4x_bs_tag; 124 125 /* Prototypes for all the bus_space structure functions */ 126 bs_protos(arm_generic); 127 bs_protos(arm_generic_a4x); 128 bs_protos(bcm2835); 129 bs_protos(bcm2835_a4x); 130 bs_protos(bcm2836); 131 bs_protos(bcm2836_a4x); 132 133 struct bus_space bcm2835_bs_tag; 134 struct bus_space bcm2835_a4x_bs_tag; 135 struct bus_space bcm2836_bs_tag; 136 struct bus_space bcm2836_a4x_bs_tag; 137 138 int bcm283x_bs_map(void *, bus_addr_t, bus_size_t, int, bus_space_handle_t *); 139 paddr_t bcm283x_bs_mmap(void *, bus_addr_t, off_t, int, int); 140 paddr_t bcm283x_a4x_bs_mmap(void *, bus_addr_t, off_t, int, int); 141 142 int 143 bcm283x_bs_map(void *t, bus_addr_t ba, bus_size_t size, int flag, 144 bus_space_handle_t *bshp) 145 { 146 u_long startpa, endpa, pa; 147 vaddr_t va; 148 149 /* Convert BA to PA */ 150 pa = ba & ~BCM2835_BUSADDR_CACHE_MASK; 151 152 startpa = trunc_page(pa); 153 endpa = round_page(pa + size); 154 155 /* XXX use extent manager to check duplicate mapping */ 156 157 va = uvm_km_alloc(kernel_map, endpa - startpa, 0, 158 UVM_KMF_VAONLY | UVM_KMF_NOWAIT | UVM_KMF_COLORMATCH); 159 if (!va) 160 return ENOMEM; 161 162 *bshp = (bus_space_handle_t)(va + (pa - startpa)); 163 164 int pmapflags; 165 if (flag & BUS_SPACE_MAP_PREFETCHABLE) 166 pmapflags = PMAP_WRITE_COMBINE; 167 else if (flag & BUS_SPACE_MAP_CACHEABLE) 168 pmapflags = 0; 169 else 170 pmapflags = PMAP_NOCACHE; 171 for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) { 172 pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, pmapflags); 173 } 174 pmap_update(pmap_kernel()); 175 176 return 0; 177 } 178 179 paddr_t 180 bcm283x_bs_mmap(void *t, bus_addr_t bpa, off_t offset, int prot, int flags) 181 { 182 /* Convert BA to PA */ 183 const paddr_t pa = bpa & ~BCM2835_BUSADDR_CACHE_MASK; 184 paddr_t bus_flags = 0; 185 186 if (flags & BUS_SPACE_MAP_PREFETCHABLE) 187 bus_flags |= ARM_MMAP_WRITECOMBINE; 188 189 return arm_btop(pa + offset) | bus_flags; 190 } 191 192 paddr_t 193 bcm283x_a4x_bs_mmap(void *t, bus_addr_t bpa, off_t offset, int prot, int flags) 194 { 195 /* Convert BA to PA */ 196 const paddr_t pa = bpa & ~BCM2835_BUSADDR_CACHE_MASK; 197 paddr_t bus_flags = 0; 198 199 if (flags & BUS_SPACE_MAP_PREFETCHABLE) 200 bus_flags |= ARM_MMAP_WRITECOMBINE; 201 202 return arm_btop(pa + 4 * offset) | bus_flags; 203 } 204 205 int 206 bcm2835_bs_map(void *t, bus_addr_t ba, bus_size_t size, int flag, 207 bus_space_handle_t *bshp) 208 { 209 const struct pmap_devmap *pd; 210 bool match = false; 211 u_long pa; 212 213 /* Attempt to find the PA device mapping */ 214 if (ba >= BCM2835_PERIPHERALS_BASE_BUS && 215 ba < BCM2835_PERIPHERALS_BASE_BUS + BCM2835_PERIPHERALS_SIZE) { 216 match = true; 217 pa = BCM2835_PERIPHERALS_BUS_TO_PHYS(ba); 218 } 219 220 if (match && (pd = pmap_devmap_find_pa(pa, size)) != NULL) { 221 /* Device was statically mapped. */ 222 *bshp = pd->pd_va + (pa - pd->pd_pa); 223 return 0; 224 } 225 226 return bcm283x_bs_map(t, ba, size, flag, bshp); 227 } 228 229 int 230 bcm2836_bs_map(void *t, bus_addr_t ba, bus_size_t size, int flag, 231 bus_space_handle_t *bshp) 232 { 233 const struct pmap_devmap *pd; 234 bool match = false; 235 u_long pa; 236 237 /* Attempt to find the PA device mapping */ 238 if (ba >= BCM2835_PERIPHERALS_BASE_BUS && 239 ba < BCM2835_PERIPHERALS_BASE_BUS + BCM2835_PERIPHERALS_SIZE) { 240 match = true; 241 pa = BCM2836_PERIPHERALS_BUS_TO_PHYS(ba); 242 } 243 244 if (ba >= BCM2836_ARM_LOCAL_BASE && 245 ba < BCM2836_ARM_LOCAL_BASE + BCM2836_ARM_LOCAL_SIZE) { 246 match = true; 247 pa = ba; 248 } 249 250 if (match && (pd = pmap_devmap_find_pa(pa, size)) != NULL) { 251 /* Device was statically mapped. */ 252 *bshp = pd->pd_va + (pa - pd->pd_pa); 253 return 0; 254 } 255 256 return bcm283x_bs_map(t, ba, size, flag, bshp); 257 } 258 259 struct arm32_dma_range bcm2835_dma_ranges[] = { 260 [0] = { 261 .dr_sysbase = 0, 262 .dr_busbase = BCM2835_BUSADDR_CACHE_COHERENT, 263 } 264 }; 265 266 struct arm32_dma_range bcm2836_dma_ranges[] = { 267 [0] = { 268 .dr_sysbase = 0, 269 .dr_busbase = BCM2835_BUSADDR_CACHE_DIRECT, 270 } 271 }; 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 BCM2835_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 BCM2835_PERIPHERALS_SIZE), /* 16Mb */ 296 297 DEVMAP_ENTRY(BCM2836_ARM_LOCAL_VBASE, BCM2836_ARM_LOCAL_BASE, 298 BCM2836_ARM_LOCAL_SIZE), 299 300 DEVMAP_ENTRY_END 301 }; 302 303 return devmap; 304 } 305 #endif 306 /* 307 * Macros to translate between physical and virtual for a subset of the 308 * kernel address space. *Not* for general use. 309 */ 310 311 /* 312 * AARCH64 defines its own 313 */ 314 #if !(defined(KERN_VTOPHYS) && defined(KERN_PHYSTOV)) 315 #define KERN_VTOPDIFF KERNEL_BASE_VOFFSET 316 #define KERN_VTOPHYS(va) ((paddr_t)((vaddr_t)va - KERN_VTOPDIFF)) 317 #define KERN_PHYSTOV(pa) ((vaddr_t)((paddr_t)pa + KERN_VTOPDIFF)) 318 #endif 319 320 #ifndef RPI_FB_WIDTH 321 #define RPI_FB_WIDTH 1280 322 #endif 323 #ifndef RPI_FB_HEIGHT 324 #define RPI_FB_HEIGHT 720 325 #endif 326 327 int uart_clk = BCM2835_UART0_CLK; 328 int core_clk; 329 330 static struct { 331 struct vcprop_buffer_hdr vb_hdr; 332 struct vcprop_tag_clockrate vbt_uartclockrate; 333 struct vcprop_tag_clockrate vbt_vpuclockrate; 334 struct vcprop_tag end; 335 } vb_uart __cacheline_aligned = { 336 .vb_hdr = { 337 .vpb_len = sizeof(vb_uart), 338 .vpb_rcode = VCPROP_PROCESS_REQUEST, 339 }, 340 .vbt_uartclockrate = { 341 .tag = { 342 .vpt_tag = VCPROPTAG_GET_CLOCKRATE, 343 .vpt_len = VCPROPTAG_LEN(vb_uart.vbt_uartclockrate), 344 .vpt_rcode = VCPROPTAG_REQUEST 345 }, 346 .id = VCPROP_CLK_UART 347 }, 348 .vbt_vpuclockrate = { 349 .tag = { 350 .vpt_tag = VCPROPTAG_GET_CLOCKRATE, 351 .vpt_len = VCPROPTAG_LEN(vb_uart.vbt_vpuclockrate), 352 .vpt_rcode = VCPROPTAG_REQUEST 353 }, 354 .id = VCPROP_CLK_CORE 355 }, 356 .end = { 357 .vpt_tag = VCPROPTAG_NULL 358 } 359 }; 360 361 static struct { 362 struct vcprop_buffer_hdr vb_hdr; 363 struct vcprop_tag_fwrev vbt_fwrev; 364 struct vcprop_tag_boardmodel vbt_boardmodel; 365 struct vcprop_tag_boardrev vbt_boardrev; 366 struct vcprop_tag_macaddr vbt_macaddr; 367 struct vcprop_tag_memory vbt_memory; 368 struct vcprop_tag_boardserial vbt_serial; 369 struct vcprop_tag_dmachan vbt_dmachan; 370 struct vcprop_tag_cmdline vbt_cmdline; 371 struct vcprop_tag_clockrate vbt_emmcclockrate; 372 struct vcprop_tag_clockrate vbt_armclockrate; 373 struct vcprop_tag_clockrate vbt_vpuclockrate; 374 struct vcprop_tag end; 375 } vb __cacheline_aligned = { 376 .vb_hdr = { 377 .vpb_len = sizeof(vb), 378 .vpb_rcode = VCPROP_PROCESS_REQUEST, 379 }, 380 .vbt_fwrev = { 381 .tag = { 382 .vpt_tag = VCPROPTAG_GET_FIRMWAREREV, 383 .vpt_len = VCPROPTAG_LEN(vb.vbt_fwrev), 384 .vpt_rcode = VCPROPTAG_REQUEST 385 }, 386 }, 387 .vbt_boardmodel = { 388 .tag = { 389 .vpt_tag = VCPROPTAG_GET_BOARDMODEL, 390 .vpt_len = VCPROPTAG_LEN(vb.vbt_boardmodel), 391 .vpt_rcode = VCPROPTAG_REQUEST 392 }, 393 }, 394 .vbt_boardrev = { 395 .tag = { 396 .vpt_tag = VCPROPTAG_GET_BOARDREVISION, 397 .vpt_len = VCPROPTAG_LEN(vb.vbt_boardrev), 398 .vpt_rcode = VCPROPTAG_REQUEST 399 }, 400 }, 401 .vbt_macaddr = { 402 .tag = { 403 .vpt_tag = VCPROPTAG_GET_MACADDRESS, 404 .vpt_len = VCPROPTAG_LEN(vb.vbt_macaddr), 405 .vpt_rcode = VCPROPTAG_REQUEST 406 }, 407 }, 408 .vbt_memory = { 409 .tag = { 410 .vpt_tag = VCPROPTAG_GET_ARMMEMORY, 411 .vpt_len = VCPROPTAG_LEN(vb.vbt_memory), 412 .vpt_rcode = VCPROPTAG_REQUEST 413 }, 414 }, 415 .vbt_serial = { 416 .tag = { 417 .vpt_tag = VCPROPTAG_GET_BOARDSERIAL, 418 .vpt_len = VCPROPTAG_LEN(vb.vbt_serial), 419 .vpt_rcode = VCPROPTAG_REQUEST 420 }, 421 }, 422 .vbt_dmachan = { 423 .tag = { 424 .vpt_tag = VCPROPTAG_GET_DMACHAN, 425 .vpt_len = VCPROPTAG_LEN(vb.vbt_dmachan), 426 .vpt_rcode = VCPROPTAG_REQUEST 427 }, 428 }, 429 .vbt_cmdline = { 430 .tag = { 431 .vpt_tag = VCPROPTAG_GET_CMDLINE, 432 .vpt_len = VCPROPTAG_LEN(vb.vbt_cmdline), 433 .vpt_rcode = VCPROPTAG_REQUEST 434 }, 435 }, 436 .vbt_emmcclockrate = { 437 .tag = { 438 .vpt_tag = VCPROPTAG_GET_CLOCKRATE, 439 .vpt_len = VCPROPTAG_LEN(vb.vbt_emmcclockrate), 440 .vpt_rcode = VCPROPTAG_REQUEST 441 }, 442 .id = VCPROP_CLK_EMMC 443 }, 444 .vbt_armclockrate = { 445 .tag = { 446 .vpt_tag = VCPROPTAG_GET_CLOCKRATE, 447 .vpt_len = VCPROPTAG_LEN(vb.vbt_armclockrate), 448 .vpt_rcode = VCPROPTAG_REQUEST 449 }, 450 .id = VCPROP_CLK_ARM 451 }, 452 .vbt_vpuclockrate = { 453 .tag = { 454 .vpt_tag = VCPROPTAG_GET_CLOCKRATE, 455 .vpt_len = VCPROPTAG_LEN(vb.vbt_vpuclockrate), 456 .vpt_rcode = VCPROPTAG_REQUEST 457 }, 458 .id = VCPROP_CLK_CORE 459 }, 460 .end = { 461 .vpt_tag = VCPROPTAG_NULL 462 } 463 }; 464 465 #if NGENFB > 0 466 static struct { 467 struct vcprop_buffer_hdr vb_hdr; 468 struct vcprop_tag_edidblock vbt_edid; 469 struct vcprop_tag end; 470 } vb_edid __cacheline_aligned = { 471 .vb_hdr = { 472 .vpb_len = sizeof(vb_edid), 473 .vpb_rcode = VCPROP_PROCESS_REQUEST, 474 }, 475 .vbt_edid = { 476 .tag = { 477 .vpt_tag = VCPROPTAG_GET_EDID_BLOCK, 478 .vpt_len = VCPROPTAG_LEN(vb_edid.vbt_edid), 479 .vpt_rcode = VCPROPTAG_REQUEST, 480 }, 481 .blockno = 0, 482 }, 483 .end = { 484 .vpt_tag = VCPROPTAG_NULL 485 } 486 }; 487 488 static struct { 489 struct vcprop_buffer_hdr vb_hdr; 490 struct vcprop_tag_fbres vbt_res; 491 struct vcprop_tag_fbres vbt_vres; 492 struct vcprop_tag_fbdepth vbt_depth; 493 struct vcprop_tag_fbalpha vbt_alpha; 494 struct vcprop_tag_allocbuf vbt_allocbuf; 495 struct vcprop_tag_blankscreen vbt_blank; 496 struct vcprop_tag_fbpitch vbt_pitch; 497 struct vcprop_tag end; 498 } vb_setfb __cacheline_aligned = { 499 .vb_hdr = { 500 .vpb_len = sizeof(vb_setfb), 501 .vpb_rcode = VCPROP_PROCESS_REQUEST, 502 }, 503 .vbt_res = { 504 .tag = { 505 .vpt_tag = VCPROPTAG_SET_FB_RES, 506 .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_res), 507 .vpt_rcode = VCPROPTAG_REQUEST, 508 }, 509 .width = 0, 510 .height = 0, 511 }, 512 .vbt_vres = { 513 .tag = { 514 .vpt_tag = VCPROPTAG_SET_FB_VRES, 515 .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_vres), 516 .vpt_rcode = VCPROPTAG_REQUEST, 517 }, 518 .width = 0, 519 .height = 0, 520 }, 521 .vbt_depth = { 522 .tag = { 523 .vpt_tag = VCPROPTAG_SET_FB_DEPTH, 524 .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_depth), 525 .vpt_rcode = VCPROPTAG_REQUEST, 526 }, 527 .bpp = 32, 528 }, 529 .vbt_alpha = { 530 .tag = { 531 .vpt_tag = VCPROPTAG_SET_FB_ALPHA_MODE, 532 .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_alpha), 533 .vpt_rcode = VCPROPTAG_REQUEST, 534 }, 535 .state = VCPROP_ALPHA_IGNORED, 536 }, 537 .vbt_allocbuf = { 538 .tag = { 539 .vpt_tag = VCPROPTAG_ALLOCATE_BUFFER, 540 .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_allocbuf), 541 .vpt_rcode = VCPROPTAG_REQUEST, 542 }, 543 .address = PAGE_SIZE, /* alignment */ 544 }, 545 .vbt_blank = { 546 .tag = { 547 .vpt_tag = VCPROPTAG_BLANK_SCREEN, 548 .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_blank), 549 .vpt_rcode = VCPROPTAG_REQUEST, 550 }, 551 .state = VCPROP_BLANK_OFF, 552 }, 553 .vbt_pitch = { 554 .tag = { 555 .vpt_tag = VCPROPTAG_GET_FB_PITCH, 556 .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_pitch), 557 .vpt_rcode = VCPROPTAG_REQUEST, 558 }, 559 }, 560 .end = { 561 .vpt_tag = VCPROPTAG_NULL, 562 }, 563 }; 564 565 #endif 566 567 static int rpi_video_on = WSDISPLAYIO_VIDEO_ON; 568 569 #if defined(RPI_HWCURSOR) 570 #define CURSOR_BITMAP_SIZE (64 * 8) 571 #define CURSOR_ARGB_SIZE (64 * 64 * 4) 572 static uint32_t hcursor = 0; 573 static bus_addr_t pcursor = 0; 574 static uint32_t *cmem = NULL; 575 static int cursor_x = 0, cursor_y = 0, hot_x = 0, hot_y = 0, cursor_on = 0; 576 static uint32_t cursor_cmap[4]; 577 static uint8_t cursor_mask[8 * 64], cursor_bitmap[8 * 64]; 578 #endif 579 580 u_int 581 bcm283x_clk_get_rate_uart(void) 582 { 583 584 if (vcprop_tag_success_p(&vb_uart.vbt_uartclockrate.tag)) 585 return vb_uart.vbt_uartclockrate.rate; 586 return 0; 587 } 588 589 u_int 590 bcm283x_clk_get_rate_vpu(void) 591 { 592 593 if (vcprop_tag_success_p(&vb.vbt_vpuclockrate.tag) && 594 vb.vbt_vpuclockrate.rate > 0) { 595 return vb.vbt_vpuclockrate.rate; 596 } 597 return 0; 598 } 599 600 u_int 601 bcm283x_clk_get_rate_emmc(void) 602 { 603 604 if (vcprop_tag_success_p(&vb.vbt_emmcclockrate.tag) && 605 vb.vbt_emmcclockrate.rate > 0) { 606 return vb.vbt_emmcclockrate.rate; 607 } 608 return 0; 609 } 610 611 612 613 static void 614 bcm283x_uartinit(bus_space_tag_t iot, bus_space_handle_t ioh) 615 { 616 uint32_t res; 617 618 bcm2835_mbox_write(iot, ioh, BCMMBOX_CHANARM2VC, 619 KERN_VTOPHYS((vaddr_t)&vb_uart)); 620 621 bcm2835_mbox_read(iot, ioh, BCMMBOX_CHANARM2VC, &res); 622 623 cpu_dcache_inv_range((vaddr_t)&vb_uart, sizeof(vb_uart)); 624 625 if (vcprop_tag_success_p(&vb_uart.vbt_uartclockrate.tag)) 626 uart_clk = vb_uart.vbt_uartclockrate.rate; 627 if (vcprop_tag_success_p(&vb_uart.vbt_vpuclockrate.tag)) 628 core_clk = vb_uart.vbt_vpuclockrate.rate; 629 } 630 631 #if defined(SOC_BCM2835) 632 static void 633 bcm2835_uartinit(void) 634 { 635 const paddr_t pa = BCM2835_PERIPHERALS_BUS_TO_PHYS(BCM2835_ARMMBOX_BASE); 636 const bus_space_tag_t iot = &bcm2835_bs_tag; 637 const bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(pa); 638 639 bcm283x_uartinit(iot, ioh); 640 } 641 #endif 642 643 #if defined(SOC_BCM2836) 644 static void 645 bcm2836_uartinit(void) 646 { 647 const paddr_t pa = BCM2836_PERIPHERALS_BUS_TO_PHYS(BCM2835_ARMMBOX_BASE); 648 const bus_space_tag_t iot = &bcm2836_bs_tag; 649 const bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(pa); 650 651 bcm283x_uartinit(iot, ioh); 652 } 653 #endif 654 655 #define BCM283x_MINIMUM_SPLIT (128U * 1024 * 1024) 656 657 static size_t bcm283x_memorysize; 658 659 static void 660 bcm283x_bootparams(bus_space_tag_t iot, bus_space_handle_t ioh) 661 { 662 uint32_t res; 663 664 bcm2835_mbox_write(iot, ioh, BCMMBOX_CHANPM, ( 665 #if (NSDHC > 0) 666 (1 << VCPM_POWER_SDCARD) | 667 #endif 668 #if (NPLCOM > 0) 669 (1 << VCPM_POWER_UART0) | 670 #endif 671 #if (NBCMDWCTWO > 0) 672 (1 << VCPM_POWER_USB) | 673 #endif 674 #if (NBSCIIC > 0) 675 (1 << VCPM_POWER_I2C0) | (1 << VCPM_POWER_I2C1) | 676 /* (1 << VCPM_POWER_I2C2) | */ 677 #endif 678 #if (NBCMSPI > 0) 679 (1 << VCPM_POWER_SPI) | 680 #endif 681 0) << 4); 682 683 bcm2835_mbox_write(iot, ioh, BCMMBOX_CHANARM2VC, 684 KERN_VTOPHYS((vaddr_t)&vb)); 685 686 bcm2835_mbox_read(iot, ioh, BCMMBOX_CHANARM2VC, &res); 687 688 cpu_dcache_inv_range((vaddr_t)&vb, sizeof(vb)); 689 690 if (!vcprop_buffer_success_p(&vb.vb_hdr)) { 691 bootconfig.dramblocks = 1; 692 bootconfig.dram[0].address = 0x0; 693 bootconfig.dram[0].pages = atop(BCM283x_MINIMUM_SPLIT); 694 return; 695 } 696 697 struct vcprop_tag_memory *vptp_mem = &vb.vbt_memory; 698 if (vcprop_tag_success_p(&vptp_mem->tag)) { 699 size_t n = vcprop_tag_resplen(&vptp_mem->tag) / 700 sizeof(struct vcprop_memory); 701 702 bcm283x_memorysize = 0; 703 bootconfig.dramblocks = 0; 704 705 for (int i = 0; i < n && i < DRAM_BLOCKS; i++) { 706 bootconfig.dram[i].address = vptp_mem->mem[i].base; 707 bootconfig.dram[i].pages = atop(vptp_mem->mem[i].size); 708 bootconfig.dramblocks++; 709 710 bcm283x_memorysize += vptp_mem->mem[i].size; 711 } 712 } 713 714 if (vcprop_tag_success_p(&vb.vbt_armclockrate.tag)) 715 curcpu()->ci_data.cpu_cc_freq = vb.vbt_armclockrate.rate; 716 717 #ifdef VERBOSE_INIT_ARM 718 if (vcprop_tag_success_p(&vb.vbt_memory.tag)) { 719 printf("%s: memory size %d\n", __func__, 720 vb.vbt_armclockrate.rate); 721 } 722 if (vcprop_tag_success_p(&vb.vbt_armclockrate.tag)) 723 printf("%s: arm clock %d\n", __func__, 724 vb.vbt_armclockrate.rate); 725 if (vcprop_tag_success_p(&vb.vbt_fwrev.tag)) 726 printf("%s: firmware rev %x\n", __func__, 727 vb.vbt_fwrev.rev); 728 if (vcprop_tag_success_p(&vb.vbt_boardmodel.tag)) 729 printf("%s: board model %x\n", __func__, 730 vb.vbt_boardmodel.model); 731 if (vcprop_tag_success_p(&vb.vbt_macaddr.tag)) 732 printf("%s: mac-address %" PRIx64 "\n", __func__, 733 vb.vbt_macaddr.addr); 734 if (vcprop_tag_success_p(&vb.vbt_boardrev.tag)) 735 printf("%s: board rev %x\n", __func__, 736 vb.vbt_boardrev.rev); 737 if (vcprop_tag_success_p(&vb.vbt_serial.tag)) 738 printf("%s: board serial %" PRIx64 "\n", __func__, 739 vb.vbt_serial.sn); 740 if (vcprop_tag_success_p(&vb.vbt_dmachan.tag)) 741 printf("%s: DMA channel mask 0x%08x\n", __func__, 742 vb.vbt_dmachan.mask); 743 744 if (vcprop_tag_success_p(&vb.vbt_cmdline.tag)) 745 printf("%s: cmdline %s\n", __func__, 746 vb.vbt_cmdline.cmdline); 747 #endif 748 } 749 750 #if defined(SOC_BCM2835) 751 static void 752 bcm2835_bootparams(void) 753 { 754 const paddr_t pa = BCM2835_PERIPHERALS_BUS_TO_PHYS(BCM2835_ARMMBOX_BASE); 755 const bus_space_tag_t iot = &bcm2835_bs_tag; 756 const bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(pa); 757 758 bcm283x_bootparams(iot, ioh); 759 } 760 #endif 761 762 #if defined(SOC_BCM2836) 763 static void 764 bcm2836_bootparams(void) 765 { 766 const paddr_t pa = BCM2836_PERIPHERALS_BUS_TO_PHYS(BCM2835_ARMMBOX_BASE); 767 const bus_space_tag_t iot = &bcm2836_bs_tag; 768 const bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(pa); 769 770 bcm283x_bootparams(iot, ioh); 771 } 772 773 static void 774 bcm2836_bootstrap(void) 775 { 776 #define RPI_CPU_MAX 4 777 778 #ifdef VERBOSE_INIT_ARM 779 #define DPRINTF(...) printf(__VA_ARGS__) 780 #else 781 #define DPRINTF(...) 782 #endif 783 784 #ifdef MULTIPROCESSOR 785 arm_cpu_max = RPI_CPU_MAX; 786 DPRINTF("%s: %d cpus present\n", __func__, arm_cpu_max); 787 #ifdef __arm__ 788 extern int cortex_mmuinfo; 789 cortex_mmuinfo = armreg_ttbr_read(); 790 DPRINTF("%s: cortex_mmuinfo %x\n", __func__, cortex_mmuinfo); 791 #endif 792 #endif /* MULTIPROCESSOR */ 793 794 #ifdef __aarch64__ 795 /* 796 * XXX: use psci_fdt_bootstrap() 797 */ 798 extern void aarch64_mpstart(void); 799 for (int i = 1; i < RPI_CPU_MAX; i++) { 800 /* 801 * Reference: 802 * armstubs/armstub8.S 803 * in https://github.com/raspberrypi/tools 804 */ 805 volatile uint64_t *cpu_release_addr; 806 #define RPI3_ARMSTUB8_SPINADDR_BASE 0x000000d8 807 cpu_release_addr = (void *) 808 AARCH64_PA_TO_KVA(RPI3_ARMSTUB8_SPINADDR_BASE + i * 8); 809 *cpu_release_addr = aarch64_kern_vtophys((vaddr_t)aarch64_mpstart); 810 811 /* need flush cache. secondary processors are cache disabled */ 812 cpu_dcache_wb_range((vaddr_t)cpu_release_addr, sizeof(cpu_release_addr)); 813 __asm __volatile("sev" ::: "memory"); 814 815 #if defined(VERBOSE_INIT_ARM) && defined(EARLYCONS) 816 /* wait secondary processor's debug output */ 817 gtmr_delay(100000); 818 #endif 819 } 820 #endif /* __aarch64__ */ 821 822 #ifdef __arm__ 823 /* 824 * Even if no options MULTIPROCESSOR, 825 * It is need to initialize the secondary CPU, 826 * and go into wfi loop (cortex_mpstart), 827 * otherwise system would be freeze... 828 */ 829 extern void cortex_mpstart(void); 830 831 for (size_t i = 1; i < RPI_CPU_MAX; i++) { 832 bus_space_tag_t iot = &bcm2836_bs_tag; 833 bus_space_handle_t ioh = BCM2836_ARM_LOCAL_VBASE; 834 835 bus_space_write_4(iot, ioh, 836 BCM2836_LOCAL_MAILBOX3_SETN(i), 837 (uint32_t)cortex_mpstart); 838 } 839 #endif 840 841 #ifdef MULTIPROCESSOR 842 /* Wake up AP in case firmware has placed it in WFE state */ 843 __asm __volatile("sev" ::: "memory"); 844 845 for (int loop = 0; loop < 16; loop++) { 846 if (arm_cpu_hatched == __BITS(arm_cpu_max - 1, 1)) 847 break; 848 gtmr_delay(10000); 849 } 850 851 for (size_t i = 1; i < arm_cpu_max; i++) { 852 if ((arm_cpu_hatched & (1 << i)) == 0) { 853 printf("%s: warning: cpu%zu failed to hatch\n", 854 __func__, i); 855 } 856 } 857 #if defined(VERBOSE_INIT_ARM) && defined(EARLYCONS) 858 /* for viewability of secondary processor's debug outputs */ 859 printf("\n"); 860 #endif 861 #endif 862 } 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 < min(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 = bcm283x_bs_mmap; 1237 bcm2835_a4x_bs_tag.bs_map = bcm2835_bs_map; 1238 bcm2835_a4x_bs_tag.bs_mmap = bcm283x_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 = bcm283x_bs_mmap; 1258 bcm2836_a4x_bs_tag.bs_map = bcm2836_bs_map; 1259 bcm2836_a4x_bs_tag.bs_mmap = bcm283x_a4x_bs_mmap; 1260 1261 fdtbus_set_decoderegprop(false); 1262 1263 bcm2836_uartinit(); 1264 1265 bcm2836_bootparams(); 1266 1267 bcm2836_bootstrap(); 1268 } 1269 #endif 1270 1271 #if defined(SOC_BCM2835) 1272 static void 1273 bcm2835_platform_init_attach_args(struct fdt_attach_args *faa) 1274 { 1275 1276 faa->faa_bst = &bcm2835_bs_tag; 1277 faa->faa_a4x_bst = &bcm2835_a4x_bs_tag; 1278 faa->faa_dmat = &bcm2835_bus_dma_tag; 1279 1280 bcm2835_bus_dma_tag._ranges = bcm2835_dma_ranges; 1281 bcm2835_bus_dma_tag._nranges = __arraycount(bcm2835_dma_ranges); 1282 bcm2835_dma_ranges[0].dr_len = bcm283x_memorysize; 1283 } 1284 #endif 1285 1286 #if defined(SOC_BCM2836) 1287 static void 1288 bcm2836_platform_init_attach_args(struct fdt_attach_args *faa) 1289 { 1290 1291 faa->faa_bst = &bcm2836_bs_tag; 1292 faa->faa_a4x_bst = &bcm2836_a4x_bs_tag; 1293 faa->faa_dmat = &bcm2835_bus_dma_tag; 1294 1295 bcm2835_bus_dma_tag._ranges = bcm2836_dma_ranges; 1296 bcm2835_bus_dma_tag._nranges = __arraycount(bcm2836_dma_ranges); 1297 bcm2836_dma_ranges[0].dr_len = bcm283x_memorysize; 1298 } 1299 #endif 1300 1301 1302 void 1303 bcm283x_platform_early_putchar(vaddr_t va, paddr_t pa, char c) 1304 { 1305 volatile uint32_t *uartaddr = 1306 cpu_earlydevice_va_p() ? 1307 (volatile uint32_t *)va : 1308 (volatile uint32_t *)pa; 1309 1310 while ((uartaddr[PL01XCOM_FR / 4] & PL01X_FR_TXFF) != 0) 1311 continue; 1312 1313 uartaddr[PL01XCOM_DR / 4] = c; 1314 1315 while ((uartaddr[PL01XCOM_FR / 4] & PL01X_FR_TXFE) == 0) 1316 continue; 1317 } 1318 1319 void 1320 bcm2835_platform_early_putchar(char c) 1321 { 1322 paddr_t pa = BCM2835_PERIPHERALS_BUS_TO_PHYS(BCM2835_UART0_BASE); 1323 vaddr_t va = BCM2835_IOPHYSTOVIRT(pa); 1324 1325 bcm283x_platform_early_putchar(va, pa, c); 1326 } 1327 1328 void 1329 bcm2836_platform_early_putchar(char c) 1330 { 1331 paddr_t pa = BCM2836_PERIPHERALS_BUS_TO_PHYS(BCM2835_UART0_BASE); 1332 vaddr_t va = BCM2835_IOPHYSTOVIRT(pa); 1333 1334 bcm283x_platform_early_putchar(va, pa, c); 1335 } 1336 1337 #define BCM283x_REF_FREQ 19200000 1338 1339 void 1340 bcm2837_platform_early_putchar(char c) 1341 { 1342 #define AUCONSADDR_PA BCM2836_PERIPHERALS_BUS_TO_PHYS(BCM2835_AUX_UART_BASE) 1343 #define AUCONSADDR_VA BCM2835_IOPHYSTOVIRT(AUCONSADDR_PA) 1344 volatile uint32_t *uartaddr = 1345 cpu_earlydevice_va_p() ? 1346 (volatile uint32_t *)AUCONSADDR_VA : 1347 (volatile uint32_t *)AUCONSADDR_PA; 1348 1349 while ((uartaddr[com_lsr] & LSR_TXRDY) == 0) 1350 ; 1351 1352 uartaddr[com_data] = c; 1353 } 1354 1355 static void 1356 bcm283x_platform_device_register(device_t dev, void *aux) 1357 { 1358 prop_dictionary_t dict = device_properties(dev); 1359 1360 if (device_is_a(dev, "bcmdmac") && 1361 vcprop_tag_success_p(&vb.vbt_dmachan.tag)) { 1362 prop_dictionary_set_uint32(dict, 1363 "chanmask", vb.vbt_dmachan.mask); 1364 } 1365 #if NSDHC > 0 1366 if (booted_device == NULL && 1367 device_is_a(dev, "ld") && 1368 device_is_a(device_parent(dev), "sdmmc")) { 1369 booted_partition = 0; 1370 booted_device = dev; 1371 } 1372 #endif 1373 if (device_is_a(dev, "usmsc") && 1374 vcprop_tag_success_p(&vb.vbt_macaddr.tag)) { 1375 const uint8_t enaddr[ETHER_ADDR_LEN] = { 1376 (vb.vbt_macaddr.addr >> 0) & 0xff, 1377 (vb.vbt_macaddr.addr >> 8) & 0xff, 1378 (vb.vbt_macaddr.addr >> 16) & 0xff, 1379 (vb.vbt_macaddr.addr >> 24) & 0xff, 1380 (vb.vbt_macaddr.addr >> 32) & 0xff, 1381 (vb.vbt_macaddr.addr >> 40) & 0xff 1382 }; 1383 1384 prop_data_t pd = prop_data_create_data(enaddr, ETHER_ADDR_LEN); 1385 KASSERT(pd != NULL); 1386 if (prop_dictionary_set(device_properties(dev), "mac-address", 1387 pd) == false) { 1388 aprint_error_dev(dev, 1389 "WARNING: Unable to set mac-address property\n"); 1390 } 1391 prop_object_release(pd); 1392 } 1393 1394 #if NGENFB > 0 1395 if (device_is_a(dev, "genfb")) { 1396 char *ptr; 1397 1398 bcmgenfb_set_console_dev(dev); 1399 bcmgenfb_set_ioctl(&rpi_ioctl); 1400 #ifdef DDB 1401 db_trap_callback = bcmgenfb_ddb_trap_callback; 1402 #endif 1403 if (rpi_fb_init(dict, aux) == false) 1404 return; 1405 if (get_bootconf_option(boot_args, "console", 1406 BOOTOPT_TYPE_STRING, &ptr) && strncmp(ptr, "fb", 2) == 0) { 1407 prop_dictionary_set_bool(dict, "is_console", true); 1408 #if NUKBD > 0 1409 /* allow ukbd to be the console keyboard */ 1410 ukbd_cnattach(); 1411 #endif 1412 } else { 1413 prop_dictionary_set_bool(dict, "is_console", false); 1414 } 1415 } 1416 #endif 1417 } 1418 1419 static u_int 1420 bcm283x_platform_uart_freq(void) 1421 { 1422 1423 return uart_clk; 1424 } 1425 1426 #if defined(SOC_BCM2835) 1427 static const struct arm_platform bcm2835_platform = { 1428 .devmap = bcm2835_platform_devmap, 1429 .bootstrap = bcm2835_platform_bootstrap, 1430 .init_attach_args = bcm2835_platform_init_attach_args, 1431 .early_putchar = bcm2835_platform_early_putchar, 1432 .device_register = bcm283x_platform_device_register, 1433 .reset = bcm2835_system_reset, 1434 .delay = bcm2835_tmr_delay, 1435 .uart_freq = bcm283x_platform_uart_freq, 1436 }; 1437 1438 ARM_PLATFORM(bcm2835, "brcm,bcm2835", &bcm2835_platform); 1439 #endif 1440 1441 #if defined(SOC_BCM2836) 1442 static u_int 1443 bcm2837_platform_uart_freq(void) 1444 { 1445 1446 return core_clk * 2; 1447 } 1448 1449 static const struct arm_platform bcm2836_platform = { 1450 .devmap = bcm2836_platform_devmap, 1451 .bootstrap = bcm2836_platform_bootstrap, 1452 .init_attach_args = bcm2836_platform_init_attach_args, 1453 .early_putchar = bcm2836_platform_early_putchar, 1454 .device_register = bcm283x_platform_device_register, 1455 .reset = bcm2835_system_reset, 1456 .delay = gtmr_delay, 1457 .uart_freq = bcm283x_platform_uart_freq, 1458 }; 1459 1460 static const struct arm_platform bcm2837_platform = { 1461 .devmap = bcm2836_platform_devmap, 1462 .bootstrap = bcm2836_platform_bootstrap, 1463 .init_attach_args = bcm2836_platform_init_attach_args, 1464 .early_putchar = bcm2837_platform_early_putchar, 1465 .device_register = bcm283x_platform_device_register, 1466 .reset = bcm2835_system_reset, 1467 .delay = gtmr_delay, 1468 .uart_freq = bcm2837_platform_uart_freq, 1469 }; 1470 1471 ARM_PLATFORM(bcm2836, "brcm,bcm2836", &bcm2836_platform); 1472 ARM_PLATFORM(bcm2837, "brcm,bcm2837", &bcm2837_platform); 1473 #endif 1474