1// SPDX-License-Identifier: GPL-2.0 2/* 3 * (C) Copyright 2012-2016 Stephen Warren 4 */ 5 6#include <common.h> 7#include <config.h> 8#include <dm.h> 9#include <env.h> 10#include <efi_loader.h> 11#include <fdt_support.h> 12#include <fdt_simplefb.h> 13#include <init.h> 14#include <memalign.h> 15#include <mmc.h> 16#include <asm/gpio.h> 17#include <asm/arch/mbox.h> 18#include <asm/arch/msg.h> 19#include <asm/arch/sdhci.h> 20#include <asm/global_data.h> 21#include <dm/platform_data/serial_bcm283x_mu.h> 22#ifdef CONFIG_ARM64 23#include <asm/armv8/mmu.h> 24#endif 25#include <watchdog.h> 26#include <dm/pinctrl.h> 27 28DECLARE_GLOBAL_DATA_PTR; 29 30/* Assigned in lowlevel_init.S 31 * Push the variable into the .data section so that it 32 * does not get cleared later. 33 */ 34unsigned long __section(".data") fw_dtb_pointer; 35 36/* TODO(sjg@chromium.org): Move these to the msg.c file */ 37struct msg_get_arm_mem { 38 struct bcm2835_mbox_hdr hdr; 39 struct bcm2835_mbox_tag_get_arm_mem get_arm_mem; 40 u32 end_tag; 41}; 42 43struct msg_get_board_rev { 44 struct bcm2835_mbox_hdr hdr; 45 struct bcm2835_mbox_tag_get_board_rev get_board_rev; 46 u32 end_tag; 47}; 48 49struct msg_get_board_serial { 50 struct bcm2835_mbox_hdr hdr; 51 struct bcm2835_mbox_tag_get_board_serial get_board_serial; 52 u32 end_tag; 53}; 54 55struct msg_get_mac_address { 56 struct bcm2835_mbox_hdr hdr; 57 struct bcm2835_mbox_tag_get_mac_address get_mac_address; 58 u32 end_tag; 59}; 60 61struct msg_get_clock_rate { 62 struct bcm2835_mbox_hdr hdr; 63 struct bcm2835_mbox_tag_get_clock_rate get_clock_rate; 64 u32 end_tag; 65}; 66 67#ifdef CONFIG_ARM64 68#define DTB_DIR "broadcom/" 69#else 70#define DTB_DIR "" 71#endif 72 73/* 74 * https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#raspberry-pi-revision-codes 75 */ 76struct rpi_model { 77 const char *name; 78 const char *fdtfile; 79 bool has_onboard_eth; 80}; 81 82static const struct rpi_model rpi_model_unknown = { 83 "Unknown model", 84 DTB_DIR "bcm283x-rpi-other.dtb", 85 false, 86}; 87 88static const struct rpi_model rpi_models_new_scheme[] = { 89 [0x0] = { 90 "Model A", 91 DTB_DIR "bcm2835-rpi-a.dtb", 92 false, 93 }, 94 [0x1] = { 95 "Model B", 96 DTB_DIR "bcm2835-rpi-b.dtb", 97 true, 98 }, 99 [0x2] = { 100 "Model A+", 101 DTB_DIR "bcm2835-rpi-a-plus.dtb", 102 false, 103 }, 104 [0x3] = { 105 "Model B+", 106 DTB_DIR "bcm2835-rpi-b-plus.dtb", 107 true, 108 }, 109 [0x4] = { 110 "2 Model B", 111 DTB_DIR "bcm2836-rpi-2-b.dtb", 112 true, 113 }, 114 [0x6] = { 115 "Compute Module", 116 DTB_DIR "bcm2835-rpi-cm.dtb", 117 false, 118 }, 119 [0x8] = { 120 "3 Model B", 121 DTB_DIR "bcm2837-rpi-3-b.dtb", 122 true, 123 }, 124 [0x9] = { 125 "Zero", 126 DTB_DIR "bcm2835-rpi-zero.dtb", 127 false, 128 }, 129 [0xA] = { 130 "Compute Module 3", 131 DTB_DIR "bcm2837-rpi-cm3.dtb", 132 false, 133 }, 134 [0xC] = { 135 "Zero W", 136 DTB_DIR "bcm2835-rpi-zero-w.dtb", 137 false, 138 }, 139 [0xD] = { 140 "3 Model B+", 141 DTB_DIR "bcm2837-rpi-3-b-plus.dtb", 142 true, 143 }, 144 [0xE] = { 145 "3 Model A+", 146 DTB_DIR "bcm2837-rpi-3-a-plus.dtb", 147 false, 148 }, 149 [0x10] = { 150 "Compute Module 3+", 151 DTB_DIR "bcm2837-rpi-cm3.dtb", 152 false, 153 }, 154 [0x11] = { 155 "4 Model B", 156 DTB_DIR "bcm2711-rpi-4-b.dtb", 157 true, 158 }, 159 [0x12] = { 160 "Zero 2 W", 161 DTB_DIR "bcm2837-rpi-zero-2-w.dtb", 162 false, 163 }, 164 [0x13] = { 165 "400", 166 DTB_DIR "bcm2711-rpi-400.dtb", 167 true, 168 }, 169 [0x14] = { 170 "Compute Module 4", 171 DTB_DIR "bcm2711-rpi-cm4.dtb", 172 true, 173 }, 174 [0x17] = { 175 "5 Model B", 176 DTB_DIR "bcm2712-rpi-5-b.dtb", 177 true, 178 }, 179}; 180 181static const struct rpi_model rpi_models_old_scheme[] = { 182 [0x2] = { 183 "Model B", 184 DTB_DIR "bcm2835-rpi-b.dtb", 185 true, 186 }, 187 [0x3] = { 188 "Model B", 189 DTB_DIR "bcm2835-rpi-b.dtb", 190 true, 191 }, 192 [0x4] = { 193 "Model B rev2", 194 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 195 true, 196 }, 197 [0x5] = { 198 "Model B rev2", 199 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 200 true, 201 }, 202 [0x6] = { 203 "Model B rev2", 204 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 205 true, 206 }, 207 [0x7] = { 208 "Model A", 209 DTB_DIR "bcm2835-rpi-a.dtb", 210 false, 211 }, 212 [0x8] = { 213 "Model A", 214 DTB_DIR "bcm2835-rpi-a.dtb", 215 false, 216 }, 217 [0x9] = { 218 "Model A", 219 DTB_DIR "bcm2835-rpi-a.dtb", 220 false, 221 }, 222 [0xd] = { 223 "Model B rev2", 224 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 225 true, 226 }, 227 [0xe] = { 228 "Model B rev2", 229 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 230 true, 231 }, 232 [0xf] = { 233 "Model B rev2", 234 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 235 true, 236 }, 237 [0x10] = { 238 "Model B+", 239 DTB_DIR "bcm2835-rpi-b-plus.dtb", 240 true, 241 }, 242 [0x11] = { 243 "Compute Module", 244 DTB_DIR "bcm2835-rpi-cm.dtb", 245 false, 246 }, 247 [0x12] = { 248 "Model A+", 249 DTB_DIR "bcm2835-rpi-a-plus.dtb", 250 false, 251 }, 252 [0x13] = { 253 "Model B+", 254 DTB_DIR "bcm2835-rpi-b-plus.dtb", 255 true, 256 }, 257 [0x14] = { 258 "Compute Module", 259 DTB_DIR "bcm2835-rpi-cm.dtb", 260 false, 261 }, 262 [0x15] = { 263 "Model A+", 264 DTB_DIR "bcm2835-rpi-a-plus.dtb", 265 false, 266 }, 267}; 268 269static uint32_t revision; 270static uint32_t rev_scheme; 271static uint32_t rev_type; 272static const struct rpi_model *model; 273 274int dram_init(void) 275{ 276 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_arm_mem, msg, 1); 277 int ret; 278 279 BCM2835_MBOX_INIT_HDR(msg); 280 BCM2835_MBOX_INIT_TAG(&msg->get_arm_mem, GET_ARM_MEMORY); 281 282 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 283 if (ret) { 284 printf("bcm2835: Could not query ARM memory size\n"); 285 return -1; 286 } 287 288 gd->ram_size = msg->get_arm_mem.body.resp.mem_size; 289 290 /* 291 * In some configurations the memory size returned by VideoCore 292 * is not aligned to the section size, what is mandatory for 293 * the u-boot's memory setup. 294 */ 295 gd->ram_size &= ~MMU_SECTION_SIZE; 296 297 return 0; 298} 299 300#ifdef CONFIG_OF_BOARD 301int dram_init_banksize(void) 302{ 303 int ret; 304 305 ret = fdtdec_setup_memory_banksize(); 306 if (ret) 307 return ret; 308 309 return fdtdec_setup_mem_size_base(); 310} 311#endif 312 313static void set_fdtfile(void) 314{ 315 const char *fdtfile; 316 317 if (env_get("fdtfile")) 318 return; 319 320 fdtfile = model->fdtfile; 321 env_set("fdtfile", fdtfile); 322} 323 324/* 325 * If the firmware provided a valid FDT at boot time, let's expose it in 326 * ${fdt_addr} so it may be passed unmodified to the kernel. 327 */ 328static void set_fdt_addr(void) 329{ 330 if (env_get("fdt_addr")) 331 return; 332 333 if (fdt_magic(fw_dtb_pointer) != FDT_MAGIC) 334 return; 335 336 env_set_hex("fdt_addr", fw_dtb_pointer); 337} 338 339/* 340 * Prevent relocation from stomping on a firmware provided FDT blob. 341 */ 342phys_addr_t board_get_usable_ram_top(phys_size_t total_size) 343{ 344 if ((gd->ram_top - fw_dtb_pointer) > SZ_64M) 345 return gd->ram_top; 346 return fw_dtb_pointer & ~0xffff; 347} 348 349static void set_usbethaddr(void) 350{ 351 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_mac_address, msg, 1); 352 int ret; 353 354 if (!model->has_onboard_eth) 355 return; 356 357 if (env_get("usbethaddr")) 358 return; 359 360 BCM2835_MBOX_INIT_HDR(msg); 361 BCM2835_MBOX_INIT_TAG(&msg->get_mac_address, GET_MAC_ADDRESS); 362 363 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 364 if (ret) { 365 printf("bcm2835: Could not query MAC address\n"); 366 /* Ignore error; not critical */ 367 return; 368 } 369 370 eth_env_set_enetaddr("usbethaddr", msg->get_mac_address.body.resp.mac); 371 372 if (!env_get("ethaddr")) 373 env_set("ethaddr", env_get("usbethaddr")); 374 375 return; 376} 377 378#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG 379static void set_board_info(void) 380{ 381 char s[11]; 382 383 snprintf(s, sizeof(s), "0x%X", revision); 384 env_set("board_revision", s); 385 snprintf(s, sizeof(s), "%d", rev_scheme); 386 env_set("board_rev_scheme", s); 387 /* Can't rename this to board_rev_type since it's an ABI for scripts */ 388 snprintf(s, sizeof(s), "0x%X", rev_type); 389 env_set("board_rev", s); 390 env_set("board_name", model->name); 391} 392#endif /* CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG */ 393 394static void set_serial_number(void) 395{ 396 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_board_serial, msg, 1); 397 int ret; 398 char serial_string[17] = { 0 }; 399 400 if (env_get("serial#")) 401 return; 402 403 BCM2835_MBOX_INIT_HDR(msg); 404 BCM2835_MBOX_INIT_TAG_NO_REQ(&msg->get_board_serial, GET_BOARD_SERIAL); 405 406 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 407 if (ret) { 408 printf("bcm2835: Could not query board serial\n"); 409 /* Ignore error; not critical */ 410 return; 411 } 412 413 snprintf(serial_string, sizeof(serial_string), "%016llx", 414 msg->get_board_serial.body.resp.serial); 415 env_set("serial#", serial_string); 416} 417 418int misc_init_r(void) 419{ 420 set_fdt_addr(); 421 set_fdtfile(); 422 set_usbethaddr(); 423#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG 424 set_board_info(); 425#endif 426 set_serial_number(); 427 428 return 0; 429} 430 431static void get_board_revision(void) 432{ 433 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_board_rev, msg, 1); 434 int ret; 435 const struct rpi_model *models; 436 uint32_t models_count; 437 ofnode node; 438 439 BCM2835_MBOX_INIT_HDR(msg); 440 BCM2835_MBOX_INIT_TAG(&msg->get_board_rev, GET_BOARD_REV); 441 442 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 443 if (ret) { 444 /* Ignore error; not critical */ 445 node = ofnode_path("/system"); 446 if (!ofnode_valid(node)) { 447 printf("bcm2835: Could not find /system node\n"); 448 return; 449 } 450 451 ret = ofnode_read_u32(node, "linux,revision", &revision); 452 if (ret) { 453 printf("bcm2835: Could not find linux,revision\n"); 454 return; 455 } 456 } else { 457 revision = msg->get_board_rev.body.resp.rev; 458 } 459 460 /* 461 * For details of old-vs-new scheme, see: 462 * https://github.com/pimoroni/RPi.version/blob/master/RPi/version.py 463 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=99293&p=690282 464 * (a few posts down) 465 * 466 * For the RPi 1, bit 24 is the "warranty bit", so we mask off just the 467 * lower byte to use as the board rev: 468 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=98367&start=250 469 * http://www.raspberrypi.org/forums/viewtopic.php?f=31&t=20594 470 */ 471 if (revision & 0x800000) { 472 rev_scheme = 1; 473 rev_type = (revision >> 4) & 0xff; 474 models = rpi_models_new_scheme; 475 models_count = ARRAY_SIZE(rpi_models_new_scheme); 476 } else { 477 rev_scheme = 0; 478 rev_type = revision & 0xff; 479 models = rpi_models_old_scheme; 480 models_count = ARRAY_SIZE(rpi_models_old_scheme); 481 } 482 if (rev_type >= models_count) { 483 printf("RPI: Board rev 0x%x outside known range\n", rev_type); 484 model = &rpi_model_unknown; 485 } else if (!models[rev_type].name) { 486 printf("RPI: Board rev 0x%x unknown\n", rev_type); 487 model = &rpi_model_unknown; 488 } else { 489 model = &models[rev_type]; 490 } 491 492 printf("RPI %s (0x%x)\n", model->name, revision); 493} 494 495int board_init(void) 496{ 497#ifdef CONFIG_HW_WATCHDOG 498 hw_watchdog_init(); 499#endif 500 501 get_board_revision(); 502 503 gd->bd->bi_boot_params = 0x100; 504 505 return bcm2835_power_on_module(BCM2835_MBOX_POWER_DEVID_USB_HCD); 506} 507 508/* 509 * If the firmware passed a device tree use it for U-Boot. 510 */ 511void *board_fdt_blob_setup(int *err) 512{ 513 *err = 0; 514 if (fdt_magic(fw_dtb_pointer) != FDT_MAGIC) { 515 *err = -ENXIO; 516 return NULL; 517 } 518 519 return (void *)fw_dtb_pointer; 520} 521 522int copy_property(void *dst, void *src, char *path, char *property) 523{ 524 int dst_offset, src_offset; 525 const fdt32_t *prop; 526 int len; 527 528 src_offset = fdt_path_offset(src, path); 529 dst_offset = fdt_path_offset(dst, path); 530 531 if (src_offset < 0 || dst_offset < 0) 532 return -1; 533 534 prop = fdt_getprop(src, src_offset, property, &len); 535 if (!prop) 536 return -1; 537 538 return fdt_setprop(dst, dst_offset, property, prop, len); 539} 540 541/* Copy tweaks from the firmware dtb to the loaded dtb */ 542void update_fdt_from_fw(void *fdt, void *fw_fdt) 543{ 544 /* Using dtb from firmware directly; leave it alone */ 545 if (fdt == fw_fdt) 546 return; 547 548 /* The firmware provides a more precie model; so copy that */ 549 copy_property(fdt, fw_fdt, "/", "model"); 550 551 /* memory reserve as suggested by the firmware */ 552 copy_property(fdt, fw_fdt, "/", "memreserve"); 553 554 /* Adjust dma-ranges for the SD card and PCI bus as they can depend on 555 * the SoC revision 556 */ 557 copy_property(fdt, fw_fdt, "emmc2bus", "dma-ranges"); 558 copy_property(fdt, fw_fdt, "pcie0", "dma-ranges"); 559 560 /* Bootloader configuration template exposes as nvmem */ 561 if (copy_property(fdt, fw_fdt, "blconfig", "reg") == 0) 562 copy_property(fdt, fw_fdt, "blconfig", "status"); 563 564 /* kernel address randomisation seed as provided by the firmware */ 565 copy_property(fdt, fw_fdt, "/chosen", "kaslr-seed"); 566 567 /* address of the PHY device as provided by the firmware */ 568 copy_property(fdt, fw_fdt, "ethernet0/mdio@e14/ethernet-phy@1", "reg"); 569} 570 571int ft_board_setup(void *blob, struct bd_info *bd) 572{ 573 int node; 574 575 update_fdt_from_fw(blob, (void *)fw_dtb_pointer); 576 577 node = fdt_node_offset_by_compatible(blob, -1, "simple-framebuffer"); 578 if (node < 0) 579 fdt_simplefb_add_node(blob); 580 else 581 fdt_simplefb_enable_and_mem_rsv(blob); 582 583#ifdef CONFIG_EFI_LOADER 584 /* Reserve the spin table */ 585 efi_add_memory_map(0, CONFIG_RPI_EFI_NR_SPIN_PAGES << EFI_PAGE_SHIFT, 586 EFI_RESERVED_MEMORY_TYPE); 587#endif 588 589 return 0; 590} 591