1 /* 2 * (C) Copyright 2012-2016 Stephen Warren 3 * 4 * SPDX-License-Identifier: GPL-2.0 5 */ 6 7 #include <common.h> 8 #include <inttypes.h> 9 #include <config.h> 10 #include <dm.h> 11 #include <efi_loader.h> 12 #include <fdt_support.h> 13 #include <fdt_simplefb.h> 14 #include <lcd.h> 15 #include <memalign.h> 16 #include <mmc.h> 17 #include <asm/gpio.h> 18 #include <asm/arch/mbox.h> 19 #include <asm/arch/msg.h> 20 #include <asm/arch/sdhci.h> 21 #include <asm/global_data.h> 22 #include <dm/platform_data/serial_bcm283x_mu.h> 23 #ifdef CONFIG_ARM64 24 #include <asm/armv8/mmu.h> 25 #endif 26 #include <watchdog.h> 27 28 DECLARE_GLOBAL_DATA_PTR; 29 30 /* From lowlevel_init.S */ 31 extern unsigned long fw_dtb_pointer; 32 33 /* TODO(sjg@chromium.org): Move these to the msg.c file */ 34 struct msg_get_arm_mem { 35 struct bcm2835_mbox_hdr hdr; 36 struct bcm2835_mbox_tag_get_arm_mem get_arm_mem; 37 u32 end_tag; 38 }; 39 40 struct msg_get_board_rev { 41 struct bcm2835_mbox_hdr hdr; 42 struct bcm2835_mbox_tag_get_board_rev get_board_rev; 43 u32 end_tag; 44 }; 45 46 struct msg_get_board_serial { 47 struct bcm2835_mbox_hdr hdr; 48 struct bcm2835_mbox_tag_get_board_serial get_board_serial; 49 u32 end_tag; 50 }; 51 52 struct msg_get_mac_address { 53 struct bcm2835_mbox_hdr hdr; 54 struct bcm2835_mbox_tag_get_mac_address get_mac_address; 55 u32 end_tag; 56 }; 57 58 struct msg_get_clock_rate { 59 struct bcm2835_mbox_hdr hdr; 60 struct bcm2835_mbox_tag_get_clock_rate get_clock_rate; 61 u32 end_tag; 62 }; 63 64 #ifdef CONFIG_ARM64 65 #define DTB_DIR "broadcom/" 66 #else 67 #define DTB_DIR "" 68 #endif 69 70 /* 71 * http://raspberryalphaomega.org.uk/2013/02/06/automatic-raspberry-pi-board-revision-detection-model-a-b1-and-b2/ 72 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=32733 73 * http://git.drogon.net/?p=wiringPi;a=blob;f=wiringPi/wiringPi.c;h=503151f61014418b9c42f4476a6086f75cd4e64b;hb=refs/heads/master#l922 74 * 75 * In http://lists.denx.de/pipermail/u-boot/2016-January/243752.html 76 * ("[U-Boot] [PATCH] rpi: fix up Model B entries") Dom Cobley at the RPi 77 * Foundation stated that the following source was accurate: 78 * https://github.com/AndrewFromMelbourne/raspberry_pi_revision 79 */ 80 struct rpi_model { 81 const char *name; 82 const char *fdtfile; 83 bool has_onboard_eth; 84 }; 85 86 static const struct rpi_model rpi_model_unknown = { 87 "Unknown model", 88 DTB_DIR "bcm283x-rpi-other.dtb", 89 false, 90 }; 91 92 static const struct rpi_model rpi_models_new_scheme[] = { 93 [0x4] = { 94 "2 Model B", 95 DTB_DIR "bcm2836-rpi-2-b.dtb", 96 true, 97 }, 98 [0x8] = { 99 "3 Model B", 100 DTB_DIR "bcm2837-rpi-3-b.dtb", 101 true, 102 }, 103 [0x9] = { 104 "Zero", 105 DTB_DIR "bcm2835-rpi-zero.dtb", 106 false, 107 }, 108 }; 109 110 static const struct rpi_model rpi_models_old_scheme[] = { 111 [0x2] = { 112 "Model B", 113 DTB_DIR "bcm2835-rpi-b.dtb", 114 true, 115 }, 116 [0x3] = { 117 "Model B", 118 DTB_DIR "bcm2835-rpi-b.dtb", 119 true, 120 }, 121 [0x4] = { 122 "Model B rev2", 123 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 124 true, 125 }, 126 [0x5] = { 127 "Model B rev2", 128 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 129 true, 130 }, 131 [0x6] = { 132 "Model B rev2", 133 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 134 true, 135 }, 136 [0x7] = { 137 "Model A", 138 DTB_DIR "bcm2835-rpi-a.dtb", 139 false, 140 }, 141 [0x8] = { 142 "Model A", 143 DTB_DIR "bcm2835-rpi-a.dtb", 144 false, 145 }, 146 [0x9] = { 147 "Model A", 148 DTB_DIR "bcm2835-rpi-a.dtb", 149 false, 150 }, 151 [0xd] = { 152 "Model B rev2", 153 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 154 true, 155 }, 156 [0xe] = { 157 "Model B rev2", 158 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 159 true, 160 }, 161 [0xf] = { 162 "Model B rev2", 163 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 164 true, 165 }, 166 [0x10] = { 167 "Model B+", 168 DTB_DIR "bcm2835-rpi-b-plus.dtb", 169 true, 170 }, 171 [0x11] = { 172 "Compute Module", 173 DTB_DIR "bcm2835-rpi-cm.dtb", 174 false, 175 }, 176 [0x12] = { 177 "Model A+", 178 DTB_DIR "bcm2835-rpi-a-plus.dtb", 179 false, 180 }, 181 [0x13] = { 182 "Model B+", 183 DTB_DIR "bcm2835-rpi-b-plus.dtb", 184 true, 185 }, 186 [0x14] = { 187 "Compute Module", 188 DTB_DIR "bcm2835-rpi-cm.dtb", 189 false, 190 }, 191 [0x15] = { 192 "Model A+", 193 DTB_DIR "bcm2835-rpi-a-plus.dtb", 194 false, 195 }, 196 }; 197 198 static uint32_t revision; 199 static uint32_t rev_scheme; 200 static uint32_t rev_type; 201 static const struct rpi_model *model; 202 203 #ifdef CONFIG_ARM64 204 static struct mm_region bcm2837_mem_map[] = { 205 { 206 .virt = 0x00000000UL, 207 .phys = 0x00000000UL, 208 .size = 0x3f000000UL, 209 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | 210 PTE_BLOCK_INNER_SHARE 211 }, { 212 .virt = 0x3f000000UL, 213 .phys = 0x3f000000UL, 214 .size = 0x01000000UL, 215 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | 216 PTE_BLOCK_NON_SHARE | 217 PTE_BLOCK_PXN | PTE_BLOCK_UXN 218 }, { 219 /* List terminator */ 220 0, 221 } 222 }; 223 224 struct mm_region *mem_map = bcm2837_mem_map; 225 #endif 226 227 int dram_init(void) 228 { 229 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_arm_mem, msg, 1); 230 int ret; 231 232 BCM2835_MBOX_INIT_HDR(msg); 233 BCM2835_MBOX_INIT_TAG(&msg->get_arm_mem, GET_ARM_MEMORY); 234 235 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 236 if (ret) { 237 printf("bcm2835: Could not query ARM memory size\n"); 238 return -1; 239 } 240 241 gd->ram_size = msg->get_arm_mem.body.resp.mem_size; 242 243 return 0; 244 } 245 246 static void set_fdtfile(void) 247 { 248 const char *fdtfile; 249 250 if (env_get("fdtfile")) 251 return; 252 253 fdtfile = model->fdtfile; 254 env_set("fdtfile", fdtfile); 255 } 256 257 /* 258 * If the firmware provided a valid FDT at boot time, let's expose it in 259 * ${fdt_addr} so it may be passed unmodified to the kernel. 260 */ 261 static void set_fdt_addr(void) 262 { 263 if (env_get("fdt_addr")) 264 return; 265 266 if (fdt_magic(fw_dtb_pointer) != FDT_MAGIC) 267 return; 268 269 env_set_hex("fdt_addr", fw_dtb_pointer); 270 } 271 272 /* 273 * Prevent relocation from stomping on a firmware provided FDT blob. 274 */ 275 unsigned long board_get_usable_ram_top(unsigned long total_size) 276 { 277 if ((gd->ram_top - fw_dtb_pointer) > SZ_64M) 278 return gd->ram_top; 279 return fw_dtb_pointer & ~0xffff; 280 } 281 282 static void set_usbethaddr(void) 283 { 284 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_mac_address, msg, 1); 285 int ret; 286 287 if (!model->has_onboard_eth) 288 return; 289 290 if (env_get("usbethaddr")) 291 return; 292 293 BCM2835_MBOX_INIT_HDR(msg); 294 BCM2835_MBOX_INIT_TAG(&msg->get_mac_address, GET_MAC_ADDRESS); 295 296 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 297 if (ret) { 298 printf("bcm2835: Could not query MAC address\n"); 299 /* Ignore error; not critical */ 300 return; 301 } 302 303 eth_env_set_enetaddr("usbethaddr", msg->get_mac_address.body.resp.mac); 304 305 if (!env_get("ethaddr")) 306 env_set("ethaddr", env_get("usbethaddr")); 307 308 return; 309 } 310 311 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG 312 static void set_board_info(void) 313 { 314 char s[11]; 315 316 snprintf(s, sizeof(s), "0x%X", revision); 317 env_set("board_revision", s); 318 snprintf(s, sizeof(s), "%d", rev_scheme); 319 env_set("board_rev_scheme", s); 320 /* Can't rename this to board_rev_type since it's an ABI for scripts */ 321 snprintf(s, sizeof(s), "0x%X", rev_type); 322 env_set("board_rev", s); 323 env_set("board_name", model->name); 324 } 325 #endif /* CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG */ 326 327 static void set_serial_number(void) 328 { 329 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_board_serial, msg, 1); 330 int ret; 331 char serial_string[17] = { 0 }; 332 333 if (env_get("serial#")) 334 return; 335 336 BCM2835_MBOX_INIT_HDR(msg); 337 BCM2835_MBOX_INIT_TAG_NO_REQ(&msg->get_board_serial, GET_BOARD_SERIAL); 338 339 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 340 if (ret) { 341 printf("bcm2835: Could not query board serial\n"); 342 /* Ignore error; not critical */ 343 return; 344 } 345 346 snprintf(serial_string, sizeof(serial_string), "%016" PRIx64, 347 msg->get_board_serial.body.resp.serial); 348 env_set("serial#", serial_string); 349 } 350 351 /* Save parameters passed from the bootloader. Initialize these in a non-zero 352 * value to force them to be placed in .data instead of .bss since the .bss 353 * section will be initialized with 0 later in the boot process. */ 354 static u32 _saved_boot_r0 = 1; 355 static u32 _saved_boot_r1 = 2; 356 static u32 _saved_boot_r2 = 3; 357 358 void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) { 359 _saved_boot_r0 = r0; 360 _saved_boot_r1 = r1; 361 _saved_boot_r2 = r2; 362 save_boot_params_ret(); 363 } 364 365 /* Returns whether we got passed a FDT from the bootloader. If it was passed, 366 * it returns the address of it. Otherwise returns NULL. 367 * 368 * The RPi start.elf passes important system configuration like memory sizes 369 * and overlays attached as configured in the config.txt file via a Device Tree. 370 * 371 * start.elf determines whether the kernel (in this case U-Boot) supports DT by 372 * looking at a the tail of the kernel file which is added by mkknlimg tool in 373 * the following repository: 374 * 375 * https://github.com/raspberrypi/tools/blob/master/mkimage/knlinfo 376 * 377 * To force start.elf to pass a combined, ready-to-go DT, you have to use the 378 * mkknlimg tool on the kernel the raspberry bootloader is using, that is, the 379 * u-boot.bin image: 380 * 381 * ./mkknlimg --dtok u-boot.bin /boot/u-boot.bin 382 */ 383 static void* rpi_passed_fdt(void) 384 { 385 if (_saved_boot_r0 != 0 || fdt_check_header((void *)_saved_boot_r2)) 386 return NULL; 387 return (void *)_saved_boot_r2; 388 } 389 390 void* board_fdt_blob_setup(void) 391 { 392 return rpi_passed_fdt(); 393 } 394 395 static void set_boot_args(void) 396 { 397 struct fdt_header *passed_fdt = rpi_passed_fdt(); 398 if (passed_fdt == NULL) 399 return; 400 401 /* Set the machine id from r1 register and FDT from register r2. */ 402 setenv_hex("machid", _saved_boot_r1); 403 setenv_hex("fdt_addr_r", _saved_boot_r2); 404 405 /* Setting fdt_high forces the updated FDT generated by U-Boot to be 406 * placed at this address. We choose to place it 512 KiB before the 407 * passed FDT, limiting the FDT size to 512 KiB. */ 408 setenv_hex("fdt_high", _saved_boot_r2 - 512 * 1024); 409 } 410 411 int misc_init_r(void) 412 { 413 set_fdt_addr(); 414 set_fdtfile(); 415 set_usbethaddr(); 416 set_boot_args(); 417 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG 418 set_board_info(); 419 #endif 420 set_serial_number(); 421 422 return 0; 423 } 424 425 static void get_board_rev(void) 426 { 427 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_board_rev, msg, 1); 428 int ret; 429 const struct rpi_model *models; 430 uint32_t models_count; 431 432 BCM2835_MBOX_INIT_HDR(msg); 433 BCM2835_MBOX_INIT_TAG(&msg->get_board_rev, GET_BOARD_REV); 434 435 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 436 if (ret) { 437 printf("bcm2835: Could not query board revision\n"); 438 /* Ignore error; not critical */ 439 return; 440 } 441 442 /* 443 * For details of old-vs-new scheme, see: 444 * https://github.com/pimoroni/RPi.version/blob/master/RPi/version.py 445 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=99293&p=690282 446 * (a few posts down) 447 * 448 * For the RPi 1, bit 24 is the "warranty bit", so we mask off just the 449 * lower byte to use as the board rev: 450 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=98367&start=250 451 * http://www.raspberrypi.org/forums/viewtopic.php?f=31&t=20594 452 */ 453 revision = msg->get_board_rev.body.resp.rev; 454 if (revision & 0x800000) { 455 rev_scheme = 1; 456 rev_type = (revision >> 4) & 0xff; 457 models = rpi_models_new_scheme; 458 models_count = ARRAY_SIZE(rpi_models_new_scheme); 459 } else { 460 rev_scheme = 0; 461 rev_type = revision & 0xff; 462 models = rpi_models_old_scheme; 463 models_count = ARRAY_SIZE(rpi_models_old_scheme); 464 } 465 if (rev_type >= models_count) { 466 printf("RPI: Board rev 0x%x outside known range\n", rev_type); 467 model = &rpi_model_unknown; 468 } else if (!models[rev_type].name) { 469 printf("RPI: Board rev 0x%x unknown\n", rev_type); 470 model = &rpi_model_unknown; 471 } else { 472 model = &models[rev_type]; 473 } 474 475 printf("RPI %s (0x%x)\n", model->name, revision); 476 } 477 478 #ifndef CONFIG_PL01X_SERIAL 479 static bool rpi_is_serial_active(void) 480 { 481 int serial_gpio = 15; 482 struct udevice *dev; 483 484 /* 485 * The RPi3 disables the mini uart by default. The easiest way to find 486 * out whether it is available is to check if the RX pin is muxed. 487 */ 488 489 if (uclass_first_device(UCLASS_GPIO, &dev) || !dev) 490 return true; 491 492 if (bcm2835_gpio_get_func_id(dev, serial_gpio) != BCM2835_GPIO_ALT5) 493 return false; 494 495 return true; 496 } 497 498 /* Disable mini-UART I/O if it's not pinmuxed to our pins. 499 * The firmware only enables it if explicitly done in config.txt: enable_uart=1 500 */ 501 static void rpi_disable_inactive_uart(void) 502 { 503 struct udevice *dev; 504 struct bcm283x_mu_serial_platdata *plat; 505 506 if (uclass_get_device_by_driver(UCLASS_SERIAL, 507 DM_GET_DRIVER(serial_bcm283x_mu), 508 &dev) || !dev) 509 return; 510 511 if (!rpi_is_serial_active()) { 512 plat = dev_get_platdata(dev); 513 plat->disabled = true; 514 } 515 } 516 #endif 517 518 int board_init(void) 519 { 520 #ifdef CONFIG_HW_WATCHDOG 521 hw_watchdog_init(); 522 #endif 523 #ifndef CONFIG_PL01X_SERIAL 524 rpi_disable_inactive_uart(); 525 #endif 526 527 get_board_rev(); 528 529 gd->bd->bi_boot_params = 0x100; 530 531 return bcm2835_power_on_module(BCM2835_MBOX_POWER_DEVID_USB_HCD); 532 } 533 534 /* 535 * If the firmware passed a device tree use it for U-Boot. 536 */ 537 void *board_fdt_blob_setup(void) 538 { 539 if (fdt_magic(fw_dtb_pointer) != FDT_MAGIC) 540 return NULL; 541 return (void *)fw_dtb_pointer; 542 } 543 544 int ft_board_setup(void *blob, bd_t *bd) 545 { 546 /* 547 * For now, we simply always add the simplefb DT node. Later, we 548 * should be more intelligent, and e.g. only do this if no enabled DT 549 * node exists for the "real" graphics driver. 550 */ 551 lcd_dt_simplefb_add_node(blob); 552 553 #ifdef CONFIG_EFI_LOADER 554 /* Reserve the spin table */ 555 efi_add_memory_map(0, 1, EFI_RESERVED_MEMORY_TYPE, 0); 556 #endif 557 558 return 0; 559 } 560