19316e144SStephen Warren /* 2f031f501SStephen Warren * (C) Copyright 2012-2016 Stephen Warren 39316e144SStephen Warren * 4a033171bSStephen Warren * SPDX-License-Identifier: GPL-2.0 59316e144SStephen Warren */ 69316e144SStephen Warren 79316e144SStephen Warren #include <common.h> 8757cd149SLubomir Rintel #include <inttypes.h> 99316e144SStephen Warren #include <config.h> 109316e144SStephen Warren #include <dm.h> 111bcf7a30SAlexander Graf #include <efi_loader.h> 129316e144SStephen Warren #include <fdt_support.h> 13033167c4SNikita Kiryanov #include <fdt_simplefb.h> 149316e144SStephen Warren #include <lcd.h> 15cf92e05cSSimon Glass #include <memalign.h> 169316e144SStephen Warren #include <mmc.h> 179316e144SStephen Warren #include <asm/gpio.h> 189316e144SStephen Warren #include <asm/arch/mbox.h> 1970997d88SSimon Glass #include <asm/arch/msg.h> 209316e144SStephen Warren #include <asm/arch/sdhci.h> 219316e144SStephen Warren #include <asm/global_data.h> 22f031f501SStephen Warren #include <dm/platform_data/serial_bcm283x_mu.h> 23d22a7657SStephen Warren #ifdef CONFIG_ARM64 24d22a7657SStephen Warren #include <asm/armv8/mmu.h> 25d22a7657SStephen Warren #endif 2645a6d231SPaolo Pisati #include <watchdog.h> 279316e144SStephen Warren 289316e144SStephen Warren DECLARE_GLOBAL_DATA_PTR; 299316e144SStephen Warren 30ade243a2SCédric Schieli /* From lowlevel_init.S */ 31ade243a2SCédric Schieli extern unsigned long fw_dtb_pointer; 32ade243a2SCédric Schieli 333e16705dSSimon Glass /* TODO(sjg@chromium.org): Move these to the msg.c file */ 349316e144SStephen Warren struct msg_get_arm_mem { 359316e144SStephen Warren struct bcm2835_mbox_hdr hdr; 369316e144SStephen Warren struct bcm2835_mbox_tag_get_arm_mem get_arm_mem; 379316e144SStephen Warren u32 end_tag; 389316e144SStephen Warren }; 399316e144SStephen Warren 409316e144SStephen Warren struct msg_get_board_rev { 419316e144SStephen Warren struct bcm2835_mbox_hdr hdr; 429316e144SStephen Warren struct bcm2835_mbox_tag_get_board_rev get_board_rev; 439316e144SStephen Warren u32 end_tag; 449316e144SStephen Warren }; 459316e144SStephen Warren 46757cd149SLubomir Rintel struct msg_get_board_serial { 47757cd149SLubomir Rintel struct bcm2835_mbox_hdr hdr; 48757cd149SLubomir Rintel struct bcm2835_mbox_tag_get_board_serial get_board_serial; 49757cd149SLubomir Rintel u32 end_tag; 50757cd149SLubomir Rintel }; 51757cd149SLubomir Rintel 529316e144SStephen Warren struct msg_get_mac_address { 539316e144SStephen Warren struct bcm2835_mbox_hdr hdr; 549316e144SStephen Warren struct bcm2835_mbox_tag_get_mac_address get_mac_address; 559316e144SStephen Warren u32 end_tag; 569316e144SStephen Warren }; 579316e144SStephen Warren 589316e144SStephen Warren struct msg_get_clock_rate { 599316e144SStephen Warren struct bcm2835_mbox_hdr hdr; 609316e144SStephen Warren struct bcm2835_mbox_tag_get_clock_rate get_clock_rate; 619316e144SStephen Warren u32 end_tag; 629316e144SStephen Warren }; 639316e144SStephen Warren 645d3c4ba1STuomas Tynkkynen #ifdef CONFIG_ARM64 655d3c4ba1STuomas Tynkkynen #define DTB_DIR "broadcom/" 665d3c4ba1STuomas Tynkkynen #else 675d3c4ba1STuomas Tynkkynen #define DTB_DIR "" 685d3c4ba1STuomas Tynkkynen #endif 695d3c4ba1STuomas Tynkkynen 70dbe6f1ebSStephen Warren /* 71dbe6f1ebSStephen Warren * http://raspberryalphaomega.org.uk/2013/02/06/automatic-raspberry-pi-board-revision-detection-model-a-b1-and-b2/ 72dbe6f1ebSStephen Warren * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=32733 73c4ea1edbSStephen Warren * http://git.drogon.net/?p=wiringPi;a=blob;f=wiringPi/wiringPi.c;h=503151f61014418b9c42f4476a6086f75cd4e64b;hb=refs/heads/master#l922 74dba060ceSStephen Warren * 75dba060ceSStephen Warren * In http://lists.denx.de/pipermail/u-boot/2016-January/243752.html 76dba060ceSStephen Warren * ("[U-Boot] [PATCH] rpi: fix up Model B entries") Dom Cobley at the RPi 77dba060ceSStephen Warren * Foundation stated that the following source was accurate: 78dba060ceSStephen Warren * https://github.com/AndrewFromMelbourne/raspberry_pi_revision 79dbe6f1ebSStephen Warren */ 80c4ea1edbSStephen Warren struct rpi_model { 819316e144SStephen Warren const char *name; 829316e144SStephen Warren const char *fdtfile; 833207d8fcSStephen Warren bool has_onboard_eth; 84c4ea1edbSStephen Warren }; 85c4ea1edbSStephen Warren 86c4ea1edbSStephen Warren static const struct rpi_model rpi_model_unknown = { 87914627feSStephen Warren "Unknown model", 885d3c4ba1STuomas Tynkkynen DTB_DIR "bcm283x-rpi-other.dtb", 89914627feSStephen Warren false, 90c4ea1edbSStephen Warren }; 91c4ea1edbSStephen Warren 92c4ea1edbSStephen Warren static const struct rpi_model rpi_models_new_scheme[] = { 93dbe6f1ebSStephen Warren [0x4] = { 9446414296SStephen Warren "2 Model B", 955d3c4ba1STuomas Tynkkynen DTB_DIR "bcm2836-rpi-2-b.dtb", 9646414296SStephen Warren true, 9746414296SStephen Warren }, 987233fb31SStephen Warren [0x8] = { 997233fb31SStephen Warren "3 Model B", 1005d3c4ba1STuomas Tynkkynen DTB_DIR "bcm2837-rpi-3-b.dtb", 1017233fb31SStephen Warren true, 1027233fb31SStephen Warren }, 103af7c03eaSStephen Warren [0x9] = { 104af7c03eaSStephen Warren "Zero", 1055d3c4ba1STuomas Tynkkynen DTB_DIR "bcm2835-rpi-zero.dtb", 106af7c03eaSStephen Warren false, 107af7c03eaSStephen Warren }, 108c4ea1edbSStephen Warren }; 109c4ea1edbSStephen Warren 110c4ea1edbSStephen Warren static const struct rpi_model rpi_models_old_scheme[] = { 111dbe6f1ebSStephen Warren [0x2] = { 1127443a9c4SLubomir Rintel "Model B", 1135d3c4ba1STuomas Tynkkynen DTB_DIR "bcm2835-rpi-b.dtb", 1143207d8fcSStephen Warren true, 1159316e144SStephen Warren }, 116dbe6f1ebSStephen Warren [0x3] = { 1177443a9c4SLubomir Rintel "Model B", 1185d3c4ba1STuomas Tynkkynen DTB_DIR "bcm2835-rpi-b.dtb", 1193207d8fcSStephen Warren true, 1209316e144SStephen Warren }, 121dbe6f1ebSStephen Warren [0x4] = { 1227443a9c4SLubomir Rintel "Model B rev2", 1235d3c4ba1STuomas Tynkkynen DTB_DIR "bcm2835-rpi-b-rev2.dtb", 1243207d8fcSStephen Warren true, 1259316e144SStephen Warren }, 126dbe6f1ebSStephen Warren [0x5] = { 1277443a9c4SLubomir Rintel "Model B rev2", 1285d3c4ba1STuomas Tynkkynen DTB_DIR "bcm2835-rpi-b-rev2.dtb", 1293207d8fcSStephen Warren true, 1309316e144SStephen Warren }, 131dbe6f1ebSStephen Warren [0x6] = { 1327443a9c4SLubomir Rintel "Model B rev2", 1335d3c4ba1STuomas Tynkkynen DTB_DIR "bcm2835-rpi-b-rev2.dtb", 1343207d8fcSStephen Warren true, 1359316e144SStephen Warren }, 136dbe6f1ebSStephen Warren [0x7] = { 1379316e144SStephen Warren "Model A", 1385d3c4ba1STuomas Tynkkynen DTB_DIR "bcm2835-rpi-a.dtb", 1393207d8fcSStephen Warren false, 1409316e144SStephen Warren }, 141dbe6f1ebSStephen Warren [0x8] = { 1429316e144SStephen Warren "Model A", 1435d3c4ba1STuomas Tynkkynen DTB_DIR "bcm2835-rpi-a.dtb", 1443207d8fcSStephen Warren false, 1459316e144SStephen Warren }, 146dbe6f1ebSStephen Warren [0x9] = { 1479316e144SStephen Warren "Model A", 1485d3c4ba1STuomas Tynkkynen DTB_DIR "bcm2835-rpi-a.dtb", 1493207d8fcSStephen Warren false, 1509316e144SStephen Warren }, 151dbe6f1ebSStephen Warren [0xd] = { 1529316e144SStephen Warren "Model B rev2", 1535d3c4ba1STuomas Tynkkynen DTB_DIR "bcm2835-rpi-b-rev2.dtb", 1543207d8fcSStephen Warren true, 1559316e144SStephen Warren }, 156dbe6f1ebSStephen Warren [0xe] = { 1579316e144SStephen Warren "Model B rev2", 1585d3c4ba1STuomas Tynkkynen DTB_DIR "bcm2835-rpi-b-rev2.dtb", 1593207d8fcSStephen Warren true, 1609316e144SStephen Warren }, 161dbe6f1ebSStephen Warren [0xf] = { 1629316e144SStephen Warren "Model B rev2", 1635d3c4ba1STuomas Tynkkynen DTB_DIR "bcm2835-rpi-b-rev2.dtb", 1643207d8fcSStephen Warren true, 1659316e144SStephen Warren }, 166dbe6f1ebSStephen Warren [0x10] = { 1679316e144SStephen Warren "Model B+", 1685d3c4ba1STuomas Tynkkynen DTB_DIR "bcm2835-rpi-b-plus.dtb", 1693207d8fcSStephen Warren true, 1709316e144SStephen Warren }, 171dbe6f1ebSStephen Warren [0x11] = { 1729316e144SStephen Warren "Compute Module", 1735d3c4ba1STuomas Tynkkynen DTB_DIR "bcm2835-rpi-cm.dtb", 1743207d8fcSStephen Warren false, 1759316e144SStephen Warren }, 176dbe6f1ebSStephen Warren [0x12] = { 17747705effSStephen Warren "Model A+", 1785d3c4ba1STuomas Tynkkynen DTB_DIR "bcm2835-rpi-a-plus.dtb", 17947705effSStephen Warren false, 18047705effSStephen Warren }, 181dbe6f1ebSStephen Warren [0x13] = { 182787affb4SStephen Warren "Model B+", 1835d3c4ba1STuomas Tynkkynen DTB_DIR "bcm2835-rpi-b-plus.dtb", 184787affb4SStephen Warren true, 185787affb4SStephen Warren }, 186dbe6f1ebSStephen Warren [0x14] = { 187787affb4SStephen Warren "Compute Module", 1885d3c4ba1STuomas Tynkkynen DTB_DIR "bcm2835-rpi-cm.dtb", 189787affb4SStephen Warren false, 190787affb4SStephen Warren }, 191dbe6f1ebSStephen Warren [0x15] = { 19279ad5cefSLubomir Rintel "Model A+", 1935d3c4ba1STuomas Tynkkynen DTB_DIR "bcm2835-rpi-a-plus.dtb", 19479ad5cefSLubomir Rintel false, 19579ad5cefSLubomir Rintel }, 1969316e144SStephen Warren }; 1979316e144SStephen Warren 198c4ea1edbSStephen Warren static uint32_t revision; 199c4ea1edbSStephen Warren static uint32_t rev_scheme; 200c4ea1edbSStephen Warren static uint32_t rev_type; 201c4ea1edbSStephen Warren static const struct rpi_model *model; 2029316e144SStephen Warren 203d22a7657SStephen Warren #ifdef CONFIG_ARM64 204d22a7657SStephen Warren static struct mm_region bcm2837_mem_map[] = { 205d22a7657SStephen Warren { 206cd4b0c5fSYork Sun .virt = 0x00000000UL, 207cd4b0c5fSYork Sun .phys = 0x00000000UL, 208d22a7657SStephen Warren .size = 0x3f000000UL, 209d22a7657SStephen Warren .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | 210d22a7657SStephen Warren PTE_BLOCK_INNER_SHARE 211d22a7657SStephen Warren }, { 212cd4b0c5fSYork Sun .virt = 0x3f000000UL, 213cd4b0c5fSYork Sun .phys = 0x3f000000UL, 214d22a7657SStephen Warren .size = 0x01000000UL, 215d22a7657SStephen Warren .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | 216d22a7657SStephen Warren PTE_BLOCK_NON_SHARE | 217d22a7657SStephen Warren PTE_BLOCK_PXN | PTE_BLOCK_UXN 218d22a7657SStephen Warren }, { 219d22a7657SStephen Warren /* List terminator */ 220d22a7657SStephen Warren 0, 221d22a7657SStephen Warren } 222d22a7657SStephen Warren }; 223d22a7657SStephen Warren 224d22a7657SStephen Warren struct mm_region *mem_map = bcm2837_mem_map; 225d22a7657SStephen Warren #endif 226d22a7657SStephen Warren 2279316e144SStephen Warren int dram_init(void) 2289316e144SStephen Warren { 229927753aeSAlexander Stein ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_arm_mem, msg, 1); 2309316e144SStephen Warren int ret; 2319316e144SStephen Warren 2329316e144SStephen Warren BCM2835_MBOX_INIT_HDR(msg); 2339316e144SStephen Warren BCM2835_MBOX_INIT_TAG(&msg->get_arm_mem, GET_ARM_MEMORY); 2349316e144SStephen Warren 2359316e144SStephen Warren ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 2369316e144SStephen Warren if (ret) { 2379316e144SStephen Warren printf("bcm2835: Could not query ARM memory size\n"); 2389316e144SStephen Warren return -1; 2399316e144SStephen Warren } 2409316e144SStephen Warren 2419316e144SStephen Warren gd->ram_size = msg->get_arm_mem.body.resp.mem_size; 2429316e144SStephen Warren 2439316e144SStephen Warren return 0; 2449316e144SStephen Warren } 2459316e144SStephen Warren 2469316e144SStephen Warren static void set_fdtfile(void) 2479316e144SStephen Warren { 2489316e144SStephen Warren const char *fdtfile; 2499316e144SStephen Warren 2509316e144SStephen Warren if (getenv("fdtfile")) 2519316e144SStephen Warren return; 2529316e144SStephen Warren 253c4ea1edbSStephen Warren fdtfile = model->fdtfile; 254382bee57SSimon Glass env_set("fdtfile", fdtfile); 2559316e144SStephen Warren } 2569316e144SStephen Warren 257ade243a2SCédric Schieli /* 258ade243a2SCédric Schieli * If the firmware provided a valid FDT at boot time, let's expose it in 259ade243a2SCédric Schieli * ${fdt_addr} so it may be passed unmodified to the kernel. 260ade243a2SCédric Schieli */ 261ade243a2SCédric Schieli static void set_fdt_addr(void) 262ade243a2SCédric Schieli { 263ade243a2SCédric Schieli if (getenv("fdt_addr")) 264ade243a2SCédric Schieli return; 265ade243a2SCédric Schieli 266ade243a2SCédric Schieli if (fdt_magic(fw_dtb_pointer) != FDT_MAGIC) 267ade243a2SCédric Schieli return; 268ade243a2SCédric Schieli 269018f5303SSimon Glass env_set_hex("fdt_addr", fw_dtb_pointer); 270ade243a2SCédric Schieli } 271ade243a2SCédric Schieli 272ade243a2SCédric Schieli /* 273ade243a2SCédric Schieli * Prevent relocation from stomping on a firmware provided FDT blob. 274ade243a2SCédric Schieli */ 275ade243a2SCédric Schieli unsigned long board_get_usable_ram_top(unsigned long total_size) 276ade243a2SCédric Schieli { 277ade243a2SCédric Schieli if ((gd->ram_top - fw_dtb_pointer) > SZ_64M) 278ade243a2SCédric Schieli return gd->ram_top; 279ade243a2SCédric Schieli return fw_dtb_pointer & ~0xffff; 280ade243a2SCédric Schieli } 281ade243a2SCédric Schieli 2829316e144SStephen Warren static void set_usbethaddr(void) 2839316e144SStephen Warren { 284927753aeSAlexander Stein ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_mac_address, msg, 1); 2859316e144SStephen Warren int ret; 2869316e144SStephen Warren 287c4ea1edbSStephen Warren if (!model->has_onboard_eth) 2883207d8fcSStephen Warren return; 2893207d8fcSStephen Warren 2909316e144SStephen Warren if (getenv("usbethaddr")) 2919316e144SStephen Warren return; 2929316e144SStephen Warren 2939316e144SStephen Warren BCM2835_MBOX_INIT_HDR(msg); 2949316e144SStephen Warren BCM2835_MBOX_INIT_TAG(&msg->get_mac_address, GET_MAC_ADDRESS); 2959316e144SStephen Warren 2969316e144SStephen Warren ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 2979316e144SStephen Warren if (ret) { 2989316e144SStephen Warren printf("bcm2835: Could not query MAC address\n"); 2999316e144SStephen Warren /* Ignore error; not critical */ 3009316e144SStephen Warren return; 3019316e144SStephen Warren } 3029316e144SStephen Warren 303*fd1e959eSSimon Glass eth_env_set_enetaddr("usbethaddr", msg->get_mac_address.body.resp.mac); 3049316e144SStephen Warren 305859f1437SLubomir Rintel if (!getenv("ethaddr")) 306382bee57SSimon Glass env_set("ethaddr", getenv("usbethaddr")); 307859f1437SLubomir Rintel 3089316e144SStephen Warren return; 3099316e144SStephen Warren } 3109316e144SStephen Warren 311bff78567SGuillaume GARDET #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG 312bff78567SGuillaume GARDET static void set_board_info(void) 313bff78567SGuillaume GARDET { 314c4ea1edbSStephen Warren char s[11]; 315c4ea1edbSStephen Warren 316c4ea1edbSStephen Warren snprintf(s, sizeof(s), "0x%X", revision); 317382bee57SSimon Glass env_set("board_revision", s); 318c4ea1edbSStephen Warren snprintf(s, sizeof(s), "%d", rev_scheme); 319382bee57SSimon Glass env_set("board_rev_scheme", s); 320c4ea1edbSStephen Warren /* Can't rename this to board_rev_type since it's an ABI for scripts */ 321c4ea1edbSStephen Warren snprintf(s, sizeof(s), "0x%X", rev_type); 322382bee57SSimon Glass env_set("board_rev", s); 323382bee57SSimon Glass env_set("board_name", model->name); 324bff78567SGuillaume GARDET } 325bff78567SGuillaume GARDET #endif /* CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG */ 326bff78567SGuillaume GARDET 327757cd149SLubomir Rintel static void set_serial_number(void) 328757cd149SLubomir Rintel { 329757cd149SLubomir Rintel ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_board_serial, msg, 1); 330757cd149SLubomir Rintel int ret; 331757cd149SLubomir Rintel char serial_string[17] = { 0 }; 332757cd149SLubomir Rintel 333757cd149SLubomir Rintel if (getenv("serial#")) 334757cd149SLubomir Rintel return; 335757cd149SLubomir Rintel 336757cd149SLubomir Rintel BCM2835_MBOX_INIT_HDR(msg); 337757cd149SLubomir Rintel BCM2835_MBOX_INIT_TAG_NO_REQ(&msg->get_board_serial, GET_BOARD_SERIAL); 338757cd149SLubomir Rintel 339757cd149SLubomir Rintel ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 340757cd149SLubomir Rintel if (ret) { 341757cd149SLubomir Rintel printf("bcm2835: Could not query board serial\n"); 342757cd149SLubomir Rintel /* Ignore error; not critical */ 343757cd149SLubomir Rintel return; 344757cd149SLubomir Rintel } 345757cd149SLubomir Rintel 346757cd149SLubomir Rintel snprintf(serial_string, sizeof(serial_string), "%016" PRIx64, 347757cd149SLubomir Rintel msg->get_board_serial.body.resp.serial); 348382bee57SSimon Glass env_set("serial#", serial_string); 349757cd149SLubomir Rintel } 350757cd149SLubomir Rintel 3519316e144SStephen Warren int misc_init_r(void) 3529316e144SStephen Warren { 353ade243a2SCédric Schieli set_fdt_addr(); 3549316e144SStephen Warren set_fdtfile(); 3559316e144SStephen Warren set_usbethaddr(); 356bff78567SGuillaume GARDET #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG 357bff78567SGuillaume GARDET set_board_info(); 358bff78567SGuillaume GARDET #endif 359757cd149SLubomir Rintel set_serial_number(); 360757cd149SLubomir Rintel 3619316e144SStephen Warren return 0; 3629316e144SStephen Warren } 3639316e144SStephen Warren 3649316e144SStephen Warren static void get_board_rev(void) 3659316e144SStephen Warren { 366927753aeSAlexander Stein ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_board_rev, msg, 1); 3679316e144SStephen Warren int ret; 368c4ea1edbSStephen Warren const struct rpi_model *models; 369c4ea1edbSStephen Warren uint32_t models_count; 3709316e144SStephen Warren 3719316e144SStephen Warren BCM2835_MBOX_INIT_HDR(msg); 3729316e144SStephen Warren BCM2835_MBOX_INIT_TAG(&msg->get_board_rev, GET_BOARD_REV); 3739316e144SStephen Warren 3749316e144SStephen Warren ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); 3759316e144SStephen Warren if (ret) { 3769316e144SStephen Warren printf("bcm2835: Could not query board revision\n"); 3779316e144SStephen Warren /* Ignore error; not critical */ 3789316e144SStephen Warren return; 3799316e144SStephen Warren } 3809316e144SStephen Warren 38146414296SStephen Warren /* 38246414296SStephen Warren * For details of old-vs-new scheme, see: 38346414296SStephen Warren * https://github.com/pimoroni/RPi.version/blob/master/RPi/version.py 38446414296SStephen Warren * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=99293&p=690282 38546414296SStephen Warren * (a few posts down) 38695b4f112SStephen Warren * 38795b4f112SStephen Warren * For the RPi 1, bit 24 is the "warranty bit", so we mask off just the 38895b4f112SStephen Warren * lower byte to use as the board rev: 38995b4f112SStephen Warren * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=98367&start=250 39095b4f112SStephen Warren * http://www.raspberrypi.org/forums/viewtopic.php?f=31&t=20594 39146414296SStephen Warren */ 392c4ea1edbSStephen Warren revision = msg->get_board_rev.body.resp.rev; 393c4ea1edbSStephen Warren if (revision & 0x800000) { 394c4ea1edbSStephen Warren rev_scheme = 1; 395c4ea1edbSStephen Warren rev_type = (revision >> 4) & 0xff; 396c4ea1edbSStephen Warren models = rpi_models_new_scheme; 397c4ea1edbSStephen Warren models_count = ARRAY_SIZE(rpi_models_new_scheme); 398c4ea1edbSStephen Warren } else { 399c4ea1edbSStephen Warren rev_scheme = 0; 400c4ea1edbSStephen Warren rev_type = revision & 0xff; 401c4ea1edbSStephen Warren models = rpi_models_old_scheme; 402c4ea1edbSStephen Warren models_count = ARRAY_SIZE(rpi_models_old_scheme); 40347705effSStephen Warren } 404c4ea1edbSStephen Warren if (rev_type >= models_count) { 405c4ea1edbSStephen Warren printf("RPI: Board rev 0x%x outside known range\n", rev_type); 406c4ea1edbSStephen Warren model = &rpi_model_unknown; 407c4ea1edbSStephen Warren } else if (!models[rev_type].name) { 408c4ea1edbSStephen Warren printf("RPI: Board rev 0x%x unknown\n", rev_type); 409c4ea1edbSStephen Warren model = &rpi_model_unknown; 410c4ea1edbSStephen Warren } else { 411c4ea1edbSStephen Warren model = &models[rev_type]; 412914627feSStephen Warren } 4139316e144SStephen Warren 414c4ea1edbSStephen Warren printf("RPI %s (0x%x)\n", model->name, revision); 4159316e144SStephen Warren } 4169316e144SStephen Warren 417601147b0SAlexander Graf #ifndef CONFIG_PL01X_SERIAL 418601147b0SAlexander Graf static bool rpi_is_serial_active(void) 419601147b0SAlexander Graf { 420601147b0SAlexander Graf int serial_gpio = 15; 421601147b0SAlexander Graf struct udevice *dev; 422601147b0SAlexander Graf 423601147b0SAlexander Graf /* 424601147b0SAlexander Graf * The RPi3 disables the mini uart by default. The easiest way to find 425601147b0SAlexander Graf * out whether it is available is to check if the RX pin is muxed. 426601147b0SAlexander Graf */ 427601147b0SAlexander Graf 428601147b0SAlexander Graf if (uclass_first_device(UCLASS_GPIO, &dev) || !dev) 429601147b0SAlexander Graf return true; 430601147b0SAlexander Graf 431601147b0SAlexander Graf if (bcm2835_gpio_get_func_id(dev, serial_gpio) != BCM2835_GPIO_ALT5) 432601147b0SAlexander Graf return false; 433601147b0SAlexander Graf 434601147b0SAlexander Graf return true; 435601147b0SAlexander Graf } 436d8396a32SFabian Vogt 437d8396a32SFabian Vogt /* Disable mini-UART I/O if it's not pinmuxed to our pins. 438d8396a32SFabian Vogt * The firmware only enables it if explicitly done in config.txt: enable_uart=1 439d8396a32SFabian Vogt */ 440d8396a32SFabian Vogt static void rpi_disable_inactive_uart(void) 441d8396a32SFabian Vogt { 442d8396a32SFabian Vogt struct udevice *dev; 443d8396a32SFabian Vogt struct bcm283x_mu_serial_platdata *plat; 444d8396a32SFabian Vogt 445d8396a32SFabian Vogt if (uclass_get_device_by_driver(UCLASS_SERIAL, 446d8396a32SFabian Vogt DM_GET_DRIVER(serial_bcm283x_mu), 447d8396a32SFabian Vogt &dev) || !dev) 448d8396a32SFabian Vogt return; 449d8396a32SFabian Vogt 450d8396a32SFabian Vogt if (!rpi_is_serial_active()) { 451d8396a32SFabian Vogt plat = dev_get_platdata(dev); 452d8396a32SFabian Vogt plat->disabled = true; 453d8396a32SFabian Vogt } 454d8396a32SFabian Vogt } 455601147b0SAlexander Graf #endif 456601147b0SAlexander Graf 457d8396a32SFabian Vogt int board_init(void) 458601147b0SAlexander Graf { 45945a6d231SPaolo Pisati #ifdef CONFIG_HW_WATCHDOG 46045a6d231SPaolo Pisati hw_watchdog_init(); 46145a6d231SPaolo Pisati #endif 462601147b0SAlexander Graf #ifndef CONFIG_PL01X_SERIAL 463d8396a32SFabian Vogt rpi_disable_inactive_uart(); 464601147b0SAlexander Graf #endif 465601147b0SAlexander Graf 466d8396a32SFabian Vogt get_board_rev(); 467d8396a32SFabian Vogt 468d8396a32SFabian Vogt gd->bd->bi_boot_params = 0x100; 469d8396a32SFabian Vogt 47070997d88SSimon Glass return bcm2835_power_on_module(BCM2835_MBOX_POWER_DEVID_USB_HCD); 471601147b0SAlexander Graf } 472601147b0SAlexander Graf 47382f766d1SAlex Deymo /* 47482f766d1SAlex Deymo * If the firmware passed a device tree use it for U-Boot. 47582f766d1SAlex Deymo */ 47682f766d1SAlex Deymo void *board_fdt_blob_setup(void) 47782f766d1SAlex Deymo { 47882f766d1SAlex Deymo if (fdt_magic(fw_dtb_pointer) != FDT_MAGIC) 47982f766d1SAlex Deymo return NULL; 48082f766d1SAlex Deymo return (void *)fw_dtb_pointer; 48182f766d1SAlex Deymo } 48282f766d1SAlex Deymo 4839316e144SStephen Warren int ft_board_setup(void *blob, bd_t *bd) 4849316e144SStephen Warren { 4859316e144SStephen Warren /* 4869316e144SStephen Warren * For now, we simply always add the simplefb DT node. Later, we 4879316e144SStephen Warren * should be more intelligent, and e.g. only do this if no enabled DT 4889316e144SStephen Warren * node exists for the "real" graphics driver. 4899316e144SStephen Warren */ 4909316e144SStephen Warren lcd_dt_simplefb_add_node(blob); 4919316e144SStephen Warren 4921bcf7a30SAlexander Graf #ifdef CONFIG_EFI_LOADER 4931bcf7a30SAlexander Graf /* Reserve the spin table */ 4941bcf7a30SAlexander Graf efi_add_memory_map(0, 1, EFI_RESERVED_MEMORY_TYPE, 0); 4951bcf7a30SAlexander Graf #endif 4961bcf7a30SAlexander Graf 4979316e144SStephen Warren return 0; 4989316e144SStephen Warren } 499