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 [0xC] = { 109 "Zero W", 110 DTB_DIR "bcm2835-rpi-zero-w.dtb", 111 false, 112 }, 113 }; 114 115 static const struct rpi_model rpi_models_old_scheme[] = { 116 [0x2] = { 117 "Model B", 118 DTB_DIR "bcm2835-rpi-b.dtb", 119 true, 120 }, 121 [0x3] = { 122 "Model B", 123 DTB_DIR "bcm2835-rpi-b.dtb", 124 true, 125 }, 126 [0x4] = { 127 "Model B rev2", 128 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 129 true, 130 }, 131 [0x5] = { 132 "Model B rev2", 133 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 134 true, 135 }, 136 [0x6] = { 137 "Model B rev2", 138 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 139 true, 140 }, 141 [0x7] = { 142 "Model A", 143 DTB_DIR "bcm2835-rpi-a.dtb", 144 false, 145 }, 146 [0x8] = { 147 "Model A", 148 DTB_DIR "bcm2835-rpi-a.dtb", 149 false, 150 }, 151 [0x9] = { 152 "Model A", 153 DTB_DIR "bcm2835-rpi-a.dtb", 154 false, 155 }, 156 [0xd] = { 157 "Model B rev2", 158 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 159 true, 160 }, 161 [0xe] = { 162 "Model B rev2", 163 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 164 true, 165 }, 166 [0xf] = { 167 "Model B rev2", 168 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 169 true, 170 }, 171 [0x10] = { 172 "Model B+", 173 DTB_DIR "bcm2835-rpi-b-plus.dtb", 174 true, 175 }, 176 [0x11] = { 177 "Compute Module", 178 DTB_DIR "bcm2835-rpi-cm.dtb", 179 false, 180 }, 181 [0x12] = { 182 "Model A+", 183 DTB_DIR "bcm2835-rpi-a-plus.dtb", 184 false, 185 }, 186 [0x13] = { 187 "Model B+", 188 DTB_DIR "bcm2835-rpi-b-plus.dtb", 189 true, 190 }, 191 [0x14] = { 192 "Compute Module", 193 DTB_DIR "bcm2835-rpi-cm.dtb", 194 false, 195 }, 196 [0x15] = { 197 "Model A+", 198 DTB_DIR "bcm2835-rpi-a-plus.dtb", 199 false, 200 }, 201 }; 202 203 static uint32_t revision; 204 static uint32_t rev_scheme; 205 static uint32_t rev_type; 206 static const struct rpi_model *model; 207 208 #ifdef CONFIG_ARM64 209 static struct mm_region bcm2837_mem_map[] = { 210 { 211 .virt = 0x00000000UL, 212 .phys = 0x00000000UL, 213 .size = 0x3f000000UL, 214 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | 215 PTE_BLOCK_INNER_SHARE 216 }, { 217 .virt = 0x3f000000UL, 218 .phys = 0x3f000000UL, 219 .size = 0x01000000UL, 220 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | 221 PTE_BLOCK_NON_SHARE | 222 PTE_BLOCK_PXN | PTE_BLOCK_UXN 223 }, { 224 /* List terminator */ 225 0, 226 } 227 }; 228 229 struct mm_region *mem_map = bcm2837_mem_map; 230 #endif 231 232 int dram_init(void) 233 { 234 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_arm_mem, msg, 1); 235 int ret; 236 237 BCM2835_MBOX_INIT_HDR(msg); 238 BCM2835_MBOX_INIT_TAG(&msg->get_arm_mem, GET_ARM_MEMORY); 239 240 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 241 if (ret) { 242 printf("bcm2835: Could not query ARM memory size\n"); 243 return -1; 244 } 245 246 gd->ram_size = msg->get_arm_mem.body.resp.mem_size; 247 248 return 0; 249 } 250 251 static void set_fdtfile(void) 252 { 253 const char *fdtfile; 254 255 if (env_get("fdtfile")) 256 return; 257 258 fdtfile = model->fdtfile; 259 env_set("fdtfile", fdtfile); 260 } 261 262 /* 263 * If the firmware provided a valid FDT at boot time, let's expose it in 264 * ${fdt_addr} so it may be passed unmodified to the kernel. 265 */ 266 static void set_fdt_addr(void) 267 { 268 if (env_get("fdt_addr")) 269 return; 270 271 if (fdt_magic(fw_dtb_pointer) != FDT_MAGIC) 272 return; 273 274 env_set_hex("fdt_addr", fw_dtb_pointer); 275 } 276 277 /* 278 * Prevent relocation from stomping on a firmware provided FDT blob. 279 */ 280 unsigned long board_get_usable_ram_top(unsigned long total_size) 281 { 282 if ((gd->ram_top - fw_dtb_pointer) > SZ_64M) 283 return gd->ram_top; 284 return fw_dtb_pointer & ~0xffff; 285 } 286 287 static void set_usbethaddr(void) 288 { 289 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_mac_address, msg, 1); 290 int ret; 291 292 if (!model->has_onboard_eth) 293 return; 294 295 if (env_get("usbethaddr")) 296 return; 297 298 BCM2835_MBOX_INIT_HDR(msg); 299 BCM2835_MBOX_INIT_TAG(&msg->get_mac_address, GET_MAC_ADDRESS); 300 301 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 302 if (ret) { 303 printf("bcm2835: Could not query MAC address\n"); 304 /* Ignore error; not critical */ 305 return; 306 } 307 308 eth_env_set_enetaddr("usbethaddr", msg->get_mac_address.body.resp.mac); 309 310 if (!env_get("ethaddr")) 311 env_set("ethaddr", env_get("usbethaddr")); 312 313 return; 314 } 315 316 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG 317 static void set_board_info(void) 318 { 319 char s[11]; 320 321 snprintf(s, sizeof(s), "0x%X", revision); 322 env_set("board_revision", s); 323 snprintf(s, sizeof(s), "%d", rev_scheme); 324 env_set("board_rev_scheme", s); 325 /* Can't rename this to board_rev_type since it's an ABI for scripts */ 326 snprintf(s, sizeof(s), "0x%X", rev_type); 327 env_set("board_rev", s); 328 env_set("board_name", model->name); 329 } 330 #endif /* CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG */ 331 332 static void set_serial_number(void) 333 { 334 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_board_serial, msg, 1); 335 int ret; 336 char serial_string[17] = { 0 }; 337 338 if (env_get("serial#")) 339 return; 340 341 BCM2835_MBOX_INIT_HDR(msg); 342 BCM2835_MBOX_INIT_TAG_NO_REQ(&msg->get_board_serial, GET_BOARD_SERIAL); 343 344 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 345 if (ret) { 346 printf("bcm2835: Could not query board serial\n"); 347 /* Ignore error; not critical */ 348 return; 349 } 350 351 snprintf(serial_string, sizeof(serial_string), "%016" PRIx64, 352 msg->get_board_serial.body.resp.serial); 353 env_set("serial#", serial_string); 354 } 355 356 int misc_init_r(void) 357 { 358 set_fdt_addr(); 359 set_fdtfile(); 360 set_usbethaddr(); 361 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG 362 set_board_info(); 363 #endif 364 set_serial_number(); 365 366 return 0; 367 } 368 369 static void get_board_rev(void) 370 { 371 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_board_rev, msg, 1); 372 int ret; 373 const struct rpi_model *models; 374 uint32_t models_count; 375 376 BCM2835_MBOX_INIT_HDR(msg); 377 BCM2835_MBOX_INIT_TAG(&msg->get_board_rev, GET_BOARD_REV); 378 379 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 380 if (ret) { 381 printf("bcm2835: Could not query board revision\n"); 382 /* Ignore error; not critical */ 383 return; 384 } 385 386 /* 387 * For details of old-vs-new scheme, see: 388 * https://github.com/pimoroni/RPi.version/blob/master/RPi/version.py 389 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=99293&p=690282 390 * (a few posts down) 391 * 392 * For the RPi 1, bit 24 is the "warranty bit", so we mask off just the 393 * lower byte to use as the board rev: 394 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=98367&start=250 395 * http://www.raspberrypi.org/forums/viewtopic.php?f=31&t=20594 396 */ 397 revision = msg->get_board_rev.body.resp.rev; 398 if (revision & 0x800000) { 399 rev_scheme = 1; 400 rev_type = (revision >> 4) & 0xff; 401 models = rpi_models_new_scheme; 402 models_count = ARRAY_SIZE(rpi_models_new_scheme); 403 } else { 404 rev_scheme = 0; 405 rev_type = revision & 0xff; 406 models = rpi_models_old_scheme; 407 models_count = ARRAY_SIZE(rpi_models_old_scheme); 408 } 409 if (rev_type >= models_count) { 410 printf("RPI: Board rev 0x%x outside known range\n", rev_type); 411 model = &rpi_model_unknown; 412 } else if (!models[rev_type].name) { 413 printf("RPI: Board rev 0x%x unknown\n", rev_type); 414 model = &rpi_model_unknown; 415 } else { 416 model = &models[rev_type]; 417 } 418 419 printf("RPI %s (0x%x)\n", model->name, revision); 420 } 421 422 #ifndef CONFIG_PL01X_SERIAL 423 static bool rpi_is_serial_active(void) 424 { 425 int serial_gpio = 15; 426 struct udevice *dev; 427 428 /* 429 * The RPi3 disables the mini uart by default. The easiest way to find 430 * out whether it is available is to check if the RX pin is muxed. 431 */ 432 433 if (uclass_first_device(UCLASS_GPIO, &dev) || !dev) 434 return true; 435 436 if (bcm2835_gpio_get_func_id(dev, serial_gpio) != BCM2835_GPIO_ALT5) 437 return false; 438 439 return true; 440 } 441 442 /* Disable mini-UART I/O if it's not pinmuxed to our pins. 443 * The firmware only enables it if explicitly done in config.txt: enable_uart=1 444 */ 445 static void rpi_disable_inactive_uart(void) 446 { 447 struct udevice *dev; 448 struct bcm283x_mu_serial_platdata *plat; 449 450 if (uclass_get_device_by_driver(UCLASS_SERIAL, 451 DM_GET_DRIVER(serial_bcm283x_mu), 452 &dev) || !dev) 453 return; 454 455 if (!rpi_is_serial_active()) { 456 plat = dev_get_platdata(dev); 457 plat->disabled = true; 458 } 459 } 460 #endif 461 462 int board_init(void) 463 { 464 #ifdef CONFIG_HW_WATCHDOG 465 hw_watchdog_init(); 466 #endif 467 #ifndef CONFIG_PL01X_SERIAL 468 rpi_disable_inactive_uart(); 469 #endif 470 471 get_board_rev(); 472 473 gd->bd->bi_boot_params = 0x100; 474 475 return bcm2835_power_on_module(BCM2835_MBOX_POWER_DEVID_USB_HCD); 476 } 477 478 /* 479 * If the firmware passed a device tree use it for U-Boot. 480 */ 481 void *board_fdt_blob_setup(void) 482 { 483 if (fdt_magic(fw_dtb_pointer) != FDT_MAGIC) 484 return NULL; 485 return (void *)fw_dtb_pointer; 486 } 487 488 int ft_board_setup(void *blob, bd_t *bd) 489 { 490 /* 491 * For now, we simply always add the simplefb DT node. Later, we 492 * should be more intelligent, and e.g. only do this if no enabled DT 493 * node exists for the "real" graphics driver. 494 */ 495 lcd_dt_simplefb_add_node(blob); 496 497 #ifdef CONFIG_EFI_LOADER 498 /* Reserve the spin table */ 499 efi_add_memory_map(0, 1, EFI_RESERVED_MEMORY_TYPE, 0); 500 #endif 501 502 return 0; 503 } 504