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 27 DECLARE_GLOBAL_DATA_PTR; 28 29 /* From lowlevel_init.S */ 30 extern unsigned long fw_dtb_pointer; 31 32 33 struct msg_get_arm_mem { 34 struct bcm2835_mbox_hdr hdr; 35 struct bcm2835_mbox_tag_get_arm_mem get_arm_mem; 36 u32 end_tag; 37 }; 38 39 struct msg_get_board_rev { 40 struct bcm2835_mbox_hdr hdr; 41 struct bcm2835_mbox_tag_get_board_rev get_board_rev; 42 u32 end_tag; 43 }; 44 45 struct msg_get_board_serial { 46 struct bcm2835_mbox_hdr hdr; 47 struct bcm2835_mbox_tag_get_board_serial get_board_serial; 48 u32 end_tag; 49 }; 50 51 struct msg_get_mac_address { 52 struct bcm2835_mbox_hdr hdr; 53 struct bcm2835_mbox_tag_get_mac_address get_mac_address; 54 u32 end_tag; 55 }; 56 57 struct msg_get_clock_rate { 58 struct bcm2835_mbox_hdr hdr; 59 struct bcm2835_mbox_tag_get_clock_rate get_clock_rate; 60 u32 end_tag; 61 }; 62 63 #ifdef CONFIG_ARM64 64 #define DTB_DIR "broadcom/" 65 #else 66 #define DTB_DIR "" 67 #endif 68 69 /* 70 * http://raspberryalphaomega.org.uk/2013/02/06/automatic-raspberry-pi-board-revision-detection-model-a-b1-and-b2/ 71 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=32733 72 * http://git.drogon.net/?p=wiringPi;a=blob;f=wiringPi/wiringPi.c;h=503151f61014418b9c42f4476a6086f75cd4e64b;hb=refs/heads/master#l922 73 * 74 * In http://lists.denx.de/pipermail/u-boot/2016-January/243752.html 75 * ("[U-Boot] [PATCH] rpi: fix up Model B entries") Dom Cobley at the RPi 76 * Foundation stated that the following source was accurate: 77 * https://github.com/AndrewFromMelbourne/raspberry_pi_revision 78 */ 79 struct rpi_model { 80 const char *name; 81 const char *fdtfile; 82 bool has_onboard_eth; 83 }; 84 85 static const struct rpi_model rpi_model_unknown = { 86 "Unknown model", 87 DTB_DIR "bcm283x-rpi-other.dtb", 88 false, 89 }; 90 91 static const struct rpi_model rpi_models_new_scheme[] = { 92 [0x4] = { 93 "2 Model B", 94 DTB_DIR "bcm2836-rpi-2-b.dtb", 95 true, 96 }, 97 [0x8] = { 98 "3 Model B", 99 DTB_DIR "bcm2837-rpi-3-b.dtb", 100 true, 101 }, 102 [0x9] = { 103 "Zero", 104 DTB_DIR "bcm2835-rpi-zero.dtb", 105 false, 106 }, 107 }; 108 109 static const struct rpi_model rpi_models_old_scheme[] = { 110 [0x2] = { 111 "Model B", 112 DTB_DIR "bcm2835-rpi-b.dtb", 113 true, 114 }, 115 [0x3] = { 116 "Model B", 117 DTB_DIR "bcm2835-rpi-b.dtb", 118 true, 119 }, 120 [0x4] = { 121 "Model B rev2", 122 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 123 true, 124 }, 125 [0x5] = { 126 "Model B rev2", 127 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 128 true, 129 }, 130 [0x6] = { 131 "Model B rev2", 132 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 133 true, 134 }, 135 [0x7] = { 136 "Model A", 137 DTB_DIR "bcm2835-rpi-a.dtb", 138 false, 139 }, 140 [0x8] = { 141 "Model A", 142 DTB_DIR "bcm2835-rpi-a.dtb", 143 false, 144 }, 145 [0x9] = { 146 "Model A", 147 DTB_DIR "bcm2835-rpi-a.dtb", 148 false, 149 }, 150 [0xd] = { 151 "Model B rev2", 152 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 153 true, 154 }, 155 [0xe] = { 156 "Model B rev2", 157 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 158 true, 159 }, 160 [0xf] = { 161 "Model B rev2", 162 DTB_DIR "bcm2835-rpi-b-rev2.dtb", 163 true, 164 }, 165 [0x10] = { 166 "Model B+", 167 DTB_DIR "bcm2835-rpi-b-plus.dtb", 168 true, 169 }, 170 [0x11] = { 171 "Compute Module", 172 DTB_DIR "bcm2835-rpi-cm.dtb", 173 false, 174 }, 175 [0x12] = { 176 "Model A+", 177 DTB_DIR "bcm2835-rpi-a-plus.dtb", 178 false, 179 }, 180 [0x13] = { 181 "Model B+", 182 DTB_DIR "bcm2835-rpi-b-plus.dtb", 183 true, 184 }, 185 [0x14] = { 186 "Compute Module", 187 DTB_DIR "bcm2835-rpi-cm.dtb", 188 false, 189 }, 190 [0x15] = { 191 "Model A+", 192 DTB_DIR "bcm2835-rpi-a-plus.dtb", 193 false, 194 }, 195 }; 196 197 static uint32_t revision; 198 static uint32_t rev_scheme; 199 static uint32_t rev_type; 200 static const struct rpi_model *model; 201 202 #ifdef CONFIG_ARM64 203 static struct mm_region bcm2837_mem_map[] = { 204 { 205 .virt = 0x00000000UL, 206 .phys = 0x00000000UL, 207 .size = 0x3f000000UL, 208 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | 209 PTE_BLOCK_INNER_SHARE 210 }, { 211 .virt = 0x3f000000UL, 212 .phys = 0x3f000000UL, 213 .size = 0x01000000UL, 214 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | 215 PTE_BLOCK_NON_SHARE | 216 PTE_BLOCK_PXN | PTE_BLOCK_UXN 217 }, { 218 /* List terminator */ 219 0, 220 } 221 }; 222 223 struct mm_region *mem_map = bcm2837_mem_map; 224 #endif 225 226 int dram_init(void) 227 { 228 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_arm_mem, msg, 1); 229 int ret; 230 231 BCM2835_MBOX_INIT_HDR(msg); 232 BCM2835_MBOX_INIT_TAG(&msg->get_arm_mem, GET_ARM_MEMORY); 233 234 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 235 if (ret) { 236 printf("bcm2835: Could not query ARM memory size\n"); 237 return -1; 238 } 239 240 gd->ram_size = msg->get_arm_mem.body.resp.mem_size; 241 242 return 0; 243 } 244 245 static void set_fdtfile(void) 246 { 247 const char *fdtfile; 248 249 if (getenv("fdtfile")) 250 return; 251 252 fdtfile = model->fdtfile; 253 setenv("fdtfile", fdtfile); 254 } 255 256 /* 257 * If the firmware provided a valid FDT at boot time, let's expose it in 258 * ${fdt_addr} so it may be passed unmodified to the kernel. 259 */ 260 static void set_fdt_addr(void) 261 { 262 if (getenv("fdt_addr")) 263 return; 264 265 if (fdt_magic(fw_dtb_pointer) != FDT_MAGIC) 266 return; 267 268 setenv_hex("fdt_addr", fw_dtb_pointer); 269 } 270 271 /* 272 * Prevent relocation from stomping on a firmware provided FDT blob. 273 */ 274 unsigned long board_get_usable_ram_top(unsigned long total_size) 275 { 276 if ((gd->ram_top - fw_dtb_pointer) > SZ_64M) 277 return gd->ram_top; 278 return fw_dtb_pointer & ~0xffff; 279 } 280 281 static void set_usbethaddr(void) 282 { 283 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_mac_address, msg, 1); 284 int ret; 285 286 if (!model->has_onboard_eth) 287 return; 288 289 if (getenv("usbethaddr")) 290 return; 291 292 BCM2835_MBOX_INIT_HDR(msg); 293 BCM2835_MBOX_INIT_TAG(&msg->get_mac_address, GET_MAC_ADDRESS); 294 295 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 296 if (ret) { 297 printf("bcm2835: Could not query MAC address\n"); 298 /* Ignore error; not critical */ 299 return; 300 } 301 302 eth_setenv_enetaddr("usbethaddr", msg->get_mac_address.body.resp.mac); 303 304 if (!getenv("ethaddr")) 305 setenv("ethaddr", getenv("usbethaddr")); 306 307 return; 308 } 309 310 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG 311 static void set_board_info(void) 312 { 313 char s[11]; 314 315 snprintf(s, sizeof(s), "0x%X", revision); 316 setenv("board_revision", s); 317 snprintf(s, sizeof(s), "%d", rev_scheme); 318 setenv("board_rev_scheme", s); 319 /* Can't rename this to board_rev_type since it's an ABI for scripts */ 320 snprintf(s, sizeof(s), "0x%X", rev_type); 321 setenv("board_rev", s); 322 setenv("board_name", model->name); 323 } 324 #endif /* CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG */ 325 326 static void set_serial_number(void) 327 { 328 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_board_serial, msg, 1); 329 int ret; 330 char serial_string[17] = { 0 }; 331 332 if (getenv("serial#")) 333 return; 334 335 BCM2835_MBOX_INIT_HDR(msg); 336 BCM2835_MBOX_INIT_TAG_NO_REQ(&msg->get_board_serial, GET_BOARD_SERIAL); 337 338 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 339 if (ret) { 340 printf("bcm2835: Could not query board serial\n"); 341 /* Ignore error; not critical */ 342 return; 343 } 344 345 snprintf(serial_string, sizeof(serial_string), "%016" PRIx64, 346 msg->get_board_serial.body.resp.serial); 347 setenv("serial#", serial_string); 348 } 349 350 int misc_init_r(void) 351 { 352 set_fdt_addr(); 353 set_fdtfile(); 354 set_usbethaddr(); 355 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG 356 set_board_info(); 357 #endif 358 set_serial_number(); 359 360 return 0; 361 } 362 363 static void get_board_rev(void) 364 { 365 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_board_rev, msg, 1); 366 int ret; 367 const struct rpi_model *models; 368 uint32_t models_count; 369 370 BCM2835_MBOX_INIT_HDR(msg); 371 BCM2835_MBOX_INIT_TAG(&msg->get_board_rev, GET_BOARD_REV); 372 373 ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 374 if (ret) { 375 printf("bcm2835: Could not query board revision\n"); 376 /* Ignore error; not critical */ 377 return; 378 } 379 380 /* 381 * For details of old-vs-new scheme, see: 382 * https://github.com/pimoroni/RPi.version/blob/master/RPi/version.py 383 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=99293&p=690282 384 * (a few posts down) 385 * 386 * For the RPi 1, bit 24 is the "warranty bit", so we mask off just the 387 * lower byte to use as the board rev: 388 * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=98367&start=250 389 * http://www.raspberrypi.org/forums/viewtopic.php?f=31&t=20594 390 */ 391 revision = msg->get_board_rev.body.resp.rev; 392 if (revision & 0x800000) { 393 rev_scheme = 1; 394 rev_type = (revision >> 4) & 0xff; 395 models = rpi_models_new_scheme; 396 models_count = ARRAY_SIZE(rpi_models_new_scheme); 397 } else { 398 rev_scheme = 0; 399 rev_type = revision & 0xff; 400 models = rpi_models_old_scheme; 401 models_count = ARRAY_SIZE(rpi_models_old_scheme); 402 } 403 if (rev_type >= models_count) { 404 printf("RPI: Board rev 0x%x outside known range\n", rev_type); 405 model = &rpi_model_unknown; 406 } else if (!models[rev_type].name) { 407 printf("RPI: Board rev 0x%x unknown\n", rev_type); 408 model = &rpi_model_unknown; 409 } else { 410 model = &models[rev_type]; 411 } 412 413 printf("RPI %s (0x%x)\n", model->name, revision); 414 } 415 416 #ifndef CONFIG_PL01X_SERIAL 417 static bool rpi_is_serial_active(void) 418 { 419 int serial_gpio = 15; 420 struct udevice *dev; 421 422 /* 423 * The RPi3 disables the mini uart by default. The easiest way to find 424 * out whether it is available is to check if the RX pin is muxed. 425 */ 426 427 if (uclass_first_device(UCLASS_GPIO, &dev) || !dev) 428 return true; 429 430 if (bcm2835_gpio_get_func_id(dev, serial_gpio) != BCM2835_GPIO_ALT5) 431 return false; 432 433 return true; 434 } 435 436 /* Disable mini-UART I/O if it's not pinmuxed to our pins. 437 * The firmware only enables it if explicitly done in config.txt: enable_uart=1 438 */ 439 static void rpi_disable_inactive_uart(void) 440 { 441 struct udevice *dev; 442 struct bcm283x_mu_serial_platdata *plat; 443 444 if (uclass_get_device_by_driver(UCLASS_SERIAL, 445 DM_GET_DRIVER(serial_bcm283x_mu), 446 &dev) || !dev) 447 return; 448 449 if (!rpi_is_serial_active()) { 450 plat = dev_get_platdata(dev); 451 plat->disabled = true; 452 } 453 } 454 #endif 455 456 int board_init(void) 457 { 458 #ifndef CONFIG_PL01X_SERIAL 459 rpi_disable_inactive_uart(); 460 #endif 461 462 get_board_rev(); 463 464 gd->bd->bi_boot_params = 0x100; 465 466 return bcm2835_power_on_module(BCM2835_MBOX_POWER_DEVID_USB_HCD); 467 } 468 469 int ft_board_setup(void *blob, bd_t *bd) 470 { 471 /* 472 * For now, we simply always add the simplefb DT node. Later, we 473 * should be more intelligent, and e.g. only do this if no enabled DT 474 * node exists for the "real" graphics driver. 475 */ 476 lcd_dt_simplefb_add_node(blob); 477 478 #ifdef CONFIG_EFI_LOADER 479 /* Reserve the spin table */ 480 efi_add_memory_map(0, 1, EFI_RESERVED_MEMORY_TYPE, 0); 481 #endif 482 483 return 0; 484 } 485