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