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 int misc_init_r(void) 352 { 353 set_fdt_addr(); 354 set_fdtfile(); 355 set_usbethaddr(); 356 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG 357 set_board_info(); 358 #endif 359 set_serial_number(); 360 361 return 0; 362 } 363 364 static void get_board_rev(void) 365 { 366 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_board_rev, msg, 1); 367 int ret; 368 const struct rpi_model *models; 369 uint32_t models_count; 370 371 BCM2835_MBOX_INIT_HDR(msg); 372 BCM2835_MBOX_INIT_TAG(&msg->get_board_rev, GET_BOARD_REV); 373 374 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 375 if (ret) { 376 printf("bcm2835: Could not query board revision\n"); 377 /* Ignore error; not critical */ 378 return; 379 } 380 381 /* 382 * For details of old-vs-new scheme, see: 383 * https://github.com/pimoroni/RPi.version/blob/master/RPi/version.py 384 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=99293&p=690282 385 * (a few posts down) 386 * 387 * For the RPi 1, bit 24 is the "warranty bit", so we mask off just the 388 * lower byte to use as the board rev: 389 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=98367&start=250 390 * http://www.raspberrypi.org/forums/viewtopic.php?f=31&t=20594 391 */ 392 revision = msg->get_board_rev.body.resp.rev; 393 if (revision & 0x800000) { 394 rev_scheme = 1; 395 rev_type = (revision >> 4) & 0xff; 396 models = rpi_models_new_scheme; 397 models_count = ARRAY_SIZE(rpi_models_new_scheme); 398 } else { 399 rev_scheme = 0; 400 rev_type = revision & 0xff; 401 models = rpi_models_old_scheme; 402 models_count = ARRAY_SIZE(rpi_models_old_scheme); 403 } 404 if (rev_type >= models_count) { 405 printf("RPI: Board rev 0x%x outside known range\n", rev_type); 406 model = &rpi_model_unknown; 407 } else if (!models[rev_type].name) { 408 printf("RPI: Board rev 0x%x unknown\n", rev_type); 409 model = &rpi_model_unknown; 410 } else { 411 model = &models[rev_type]; 412 } 413 414 printf("RPI %s (0x%x)\n", model->name, revision); 415 } 416 417 #ifndef CONFIG_PL01X_SERIAL 418 static bool rpi_is_serial_active(void) 419 { 420 int serial_gpio = 15; 421 struct udevice *dev; 422 423 /* 424 * The RPi3 disables the mini uart by default. The easiest way to find 425 * out whether it is available is to check if the RX pin is muxed. 426 */ 427 428 if (uclass_first_device(UCLASS_GPIO, &dev) || !dev) 429 return true; 430 431 if (bcm2835_gpio_get_func_id(dev, serial_gpio) != BCM2835_GPIO_ALT5) 432 return false; 433 434 return true; 435 } 436 437 /* Disable mini-UART I/O if it's not pinmuxed to our pins. 438 * The firmware only enables it if explicitly done in config.txt: enable_uart=1 439 */ 440 static void rpi_disable_inactive_uart(void) 441 { 442 struct udevice *dev; 443 struct bcm283x_mu_serial_platdata *plat; 444 445 if (uclass_get_device_by_driver(UCLASS_SERIAL, 446 DM_GET_DRIVER(serial_bcm283x_mu), 447 &dev) || !dev) 448 return; 449 450 if (!rpi_is_serial_active()) { 451 plat = dev_get_platdata(dev); 452 plat->disabled = true; 453 } 454 } 455 #endif 456 457 int board_init(void) 458 { 459 #ifdef CONFIG_HW_WATCHDOG 460 hw_watchdog_init(); 461 #endif 462 #ifndef CONFIG_PL01X_SERIAL 463 rpi_disable_inactive_uart(); 464 #endif 465 466 get_board_rev(); 467 468 gd->bd->bi_boot_params = 0x100; 469 470 return bcm2835_power_on_module(BCM2835_MBOX_POWER_DEVID_USB_HCD); 471 } 472 473 /* 474 * If the firmware passed a device tree use it for U-Boot. 475 */ 476 void *board_fdt_blob_setup(void) 477 { 478 if (fdt_magic(fw_dtb_pointer) != FDT_MAGIC) 479 return NULL; 480 return (void *)fw_dtb_pointer; 481 } 482 483 int ft_board_setup(void *blob, bd_t *bd) 484 { 485 /* 486 * For now, we simply always add the simplefb DT node. Later, we 487 * should be more intelligent, and e.g. only do this if no enabled DT 488 * node exists for the "real" graphics driver. 489 */ 490 lcd_dt_simplefb_add_node(blob); 491 492 #ifdef CONFIG_EFI_LOADER 493 /* Reserve the spin table */ 494 efi_add_memory_map(0, 1, EFI_RESERVED_MEMORY_TYPE, 0); 495 #endif 496 497 return 0; 498 } 499