1ade8a1a6SYing Zhang /* 2ade8a1a6SYing Zhang * (C) Copyright 2010 3ade8a1a6SYing Zhang * Texas Instruments, <www.ti.com> 4ade8a1a6SYing Zhang * 5ade8a1a6SYing Zhang * Aneesh V <aneesh@ti.com> 6ade8a1a6SYing Zhang * 71a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 8ade8a1a6SYing Zhang */ 9ade8a1a6SYing Zhang #include <common.h> 10ade8a1a6SYing Zhang #include <spl.h> 11*91199f4aSPaul Kocialkowski #include <linux/compiler.h> 12ade8a1a6SYing Zhang #include <asm/u-boot.h> 13ade8a1a6SYing Zhang #include <mmc.h> 14e4c444b3STom Rini #include <image.h> 15ade8a1a6SYing Zhang 16ade8a1a6SYing Zhang DECLARE_GLOBAL_DATA_PTR; 17ade8a1a6SYing Zhang 18b97300b6SPaul Kocialkowski static int mmc_load_image_raw_sector(struct mmc *mmc, unsigned long sector) 19ade8a1a6SYing Zhang { 20ade8a1a6SYing Zhang unsigned long err; 21ade8a1a6SYing Zhang u32 image_size_sectors; 22ade8a1a6SYing Zhang struct image_header *header; 23ade8a1a6SYing Zhang 24ade8a1a6SYing Zhang header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - 25ade8a1a6SYing Zhang sizeof(struct image_header)); 26ade8a1a6SYing Zhang 27ade8a1a6SYing Zhang /* read image header to find the image size & load address */ 28721931f8SPeter Korsgaard err = mmc->block_dev.block_read(0, sector, 1, header); 29ade8a1a6SYing Zhang if (err == 0) 30ade8a1a6SYing Zhang goto end; 31ade8a1a6SYing Zhang 32e4c444b3STom Rini if (image_get_magic(header) != IH_MAGIC) 33e4c444b3STom Rini return -1; 34e4c444b3STom Rini 35ade8a1a6SYing Zhang spl_parse_image_header(header); 36ade8a1a6SYing Zhang 37ade8a1a6SYing Zhang /* convert size to sectors - round up */ 38ade8a1a6SYing Zhang image_size_sectors = (spl_image.size + mmc->read_bl_len - 1) / 39ade8a1a6SYing Zhang mmc->read_bl_len; 40ade8a1a6SYing Zhang 41ade8a1a6SYing Zhang /* Read the header too to avoid extra memcpy */ 42721931f8SPeter Korsgaard err = mmc->block_dev.block_read(0, sector, image_size_sectors, 43721931f8SPeter Korsgaard (void *)spl_image.load_addr); 44ade8a1a6SYing Zhang 45ade8a1a6SYing Zhang end: 468112f5faSPaul Burton #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 4779adb7a2SPeter Korsgaard if (err == 0) 48*91199f4aSPaul Kocialkowski printf("spl: mmc block read error\n"); 498112f5faSPaul Burton #endif 5079adb7a2SPeter Korsgaard 5179adb7a2SPeter Korsgaard return (err == 0); 52ade8a1a6SYing Zhang } 53ade8a1a6SYing Zhang 54b97300b6SPaul Kocialkowski #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION 55b97300b6SPaul Kocialkowski static int mmc_load_image_raw_partition(struct mmc *mmc, int partition) 56b97300b6SPaul Kocialkowski { 57b97300b6SPaul Kocialkowski disk_partition_t info; 58b97300b6SPaul Kocialkowski 59b97300b6SPaul Kocialkowski if (get_partition_info(&mmc->block_dev, partition, &info)) { 60b97300b6SPaul Kocialkowski #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 61b97300b6SPaul Kocialkowski printf("spl: partition error\n"); 62b97300b6SPaul Kocialkowski #endif 63b97300b6SPaul Kocialkowski return -1; 64b97300b6SPaul Kocialkowski } 65b97300b6SPaul Kocialkowski 66b97300b6SPaul Kocialkowski return mmc_load_image_raw_sector(mmc, info.start); 67b97300b6SPaul Kocialkowski } 68b97300b6SPaul Kocialkowski #endif 69b97300b6SPaul Kocialkowski 702b75b0adSPeter Korsgaard #ifdef CONFIG_SPL_OS_BOOT 712b75b0adSPeter Korsgaard static int mmc_load_image_raw_os(struct mmc *mmc) 722b75b0adSPeter Korsgaard { 73*91199f4aSPaul Kocialkowski unsigned long err; 74*91199f4aSPaul Kocialkowski 75*91199f4aSPaul Kocialkowski err = mmc->block_dev.block_read(0, 762b75b0adSPeter Korsgaard CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR, 772b75b0adSPeter Korsgaard CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS, 78*91199f4aSPaul Kocialkowski (void *)CONFIG_SYS_SPL_ARGS_ADDR); 79*91199f4aSPaul Kocialkowski if (err) { 808112f5faSPaul Burton #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 81*91199f4aSPaul Kocialkowski printf("spl: mmc block read error\n"); 828112f5faSPaul Burton #endif 832b75b0adSPeter Korsgaard return -1; 842b75b0adSPeter Korsgaard } 852b75b0adSPeter Korsgaard 86b97300b6SPaul Kocialkowski return mmc_load_image_raw_sector(mmc, 87b97300b6SPaul Kocialkowski CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR); 882b75b0adSPeter Korsgaard } 892b75b0adSPeter Korsgaard #endif 902b75b0adSPeter Korsgaard 91ade8a1a6SYing Zhang void spl_mmc_load_image(void) 92ade8a1a6SYing Zhang { 93ade8a1a6SYing Zhang struct mmc *mmc; 94ade8a1a6SYing Zhang u32 boot_mode; 95*91199f4aSPaul Kocialkowski int err; 96*91199f4aSPaul Kocialkowski __maybe_unused int part; 97ade8a1a6SYing Zhang 98ade8a1a6SYing Zhang mmc_initialize(gd->bd); 99*91199f4aSPaul Kocialkowski 100ade8a1a6SYing Zhang /* We register only one device. So, the dev id is always 0 */ 101ade8a1a6SYing Zhang mmc = find_mmc_device(0); 102ade8a1a6SYing Zhang if (!mmc) { 1038112f5faSPaul Burton #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 104*91199f4aSPaul Kocialkowski puts("spl: mmc device not found\n"); 1058112f5faSPaul Burton #endif 106ade8a1a6SYing Zhang hang(); 107ade8a1a6SYing Zhang } 108ade8a1a6SYing Zhang 109ade8a1a6SYing Zhang err = mmc_init(mmc); 110ade8a1a6SYing Zhang if (err) { 1118112f5faSPaul Burton #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 112*91199f4aSPaul Kocialkowski printf("spl: mmc init failed with error: %d\n", err); 1138112f5faSPaul Burton #endif 114ade8a1a6SYing Zhang hang(); 115ade8a1a6SYing Zhang } 11679adb7a2SPeter Korsgaard 117ade8a1a6SYing Zhang boot_mode = spl_boot_mode(); 118*91199f4aSPaul Kocialkowski switch (boot_mode) { 119*91199f4aSPaul Kocialkowski case MMCSD_MODE_RAW: 120*91199f4aSPaul Kocialkowski debug("spl: mmc boot mode: raw\n"); 121*91199f4aSPaul Kocialkowski 1222b75b0adSPeter Korsgaard #ifdef CONFIG_SPL_OS_BOOT 123*91199f4aSPaul Kocialkowski if (!spl_start_uboot()) { 124*91199f4aSPaul Kocialkowski err = mmc_load_image_raw_os(mmc); 125*91199f4aSPaul Kocialkowski if (!err) 126*91199f4aSPaul Kocialkowski return; 127*91199f4aSPaul Kocialkowski } 1282b75b0adSPeter Korsgaard #endif 129b97300b6SPaul Kocialkowski #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION 130b97300b6SPaul Kocialkowski err = mmc_load_image_raw_partition(mmc, 131b97300b6SPaul Kocialkowski CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION); 132b97300b6SPaul Kocialkowski #else 133b97300b6SPaul Kocialkowski err = mmc_load_image_raw_sector(mmc, 134721931f8SPeter Korsgaard CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); 135b97300b6SPaul Kocialkowski #endif 136*91199f4aSPaul Kocialkowski if (!err) 137*91199f4aSPaul Kocialkowski return; 138592f9222SGuillaume GARDET #if defined(CONFIG_SPL_FAT_SUPPORT) || defined(CONFIG_SPL_EXT_SUPPORT) 139*91199f4aSPaul Kocialkowski case MMCSD_MODE_FS: 140*91199f4aSPaul Kocialkowski debug("spl: mmc boot mode: fs\n"); 141*91199f4aSPaul Kocialkowski 142592f9222SGuillaume GARDET #ifdef CONFIG_SPL_FAT_SUPPORT 1437ad2cc79SPeter Korsgaard #ifdef CONFIG_SPL_OS_BOOT 144*91199f4aSPaul Kocialkowski if (!spl_start_uboot()) { 145*91199f4aSPaul Kocialkowski err = spl_load_image_fat_os(&mmc->block_dev, 146*91199f4aSPaul Kocialkowski CONFIG_SYS_MMCSD_FS_BOOT_PARTITION); 147*91199f4aSPaul Kocialkowski if (!err) 148*91199f4aSPaul Kocialkowski return; 149*91199f4aSPaul Kocialkowski } 1507ad2cc79SPeter Korsgaard #endif 151773b5940SDan Murphy err = spl_load_image_fat(&mmc->block_dev, 152e2ccdf89SPaul Kocialkowski CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, 153205b4f33SGuillaume GARDET CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); 154*91199f4aSPaul Kocialkowski if (!err) 155*91199f4aSPaul Kocialkowski return; 156*91199f4aSPaul Kocialkowski #endif 157592f9222SGuillaume GARDET #ifdef CONFIG_SPL_EXT_SUPPORT 158592f9222SGuillaume GARDET #ifdef CONFIG_SPL_OS_BOOT 159*91199f4aSPaul Kocialkowski if (!spl_start_uboot()) { 160*91199f4aSPaul Kocialkowski err = spl_load_image_ext_os(&mmc->block_dev, 161*91199f4aSPaul Kocialkowski CONFIG_SYS_MMCSD_FS_BOOT_PARTITION); 162*91199f4aSPaul Kocialkowski if (!err) 163*91199f4aSPaul Kocialkowski return; 164*91199f4aSPaul Kocialkowski } 165ade8a1a6SYing Zhang #endif 166592f9222SGuillaume GARDET err = spl_load_image_ext(&mmc->block_dev, 167e2ccdf89SPaul Kocialkowski CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, 168592f9222SGuillaume GARDET CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); 169*91199f4aSPaul Kocialkowski if (!err) 170*91199f4aSPaul Kocialkowski return; 171*91199f4aSPaul Kocialkowski #endif 172*91199f4aSPaul Kocialkowski #endif 1737dbe63bcSTom Rini #ifdef CONFIG_SUPPORT_EMMC_BOOT 174*91199f4aSPaul Kocialkowski case MMCSD_MODE_EMMCBOOT: 1757dbe63bcSTom Rini /* 1767dbe63bcSTom Rini * We need to check what the partition is configured to. 1777dbe63bcSTom Rini * 1 and 2 match up to boot0 / boot1 and 7 is user data 1787dbe63bcSTom Rini * which is the first physical partition (0). 1797dbe63bcSTom Rini */ 180*91199f4aSPaul Kocialkowski part = (mmc->part_config >> 3) & PART_ACCESS_MASK; 1817dbe63bcSTom Rini 1827dbe63bcSTom Rini if (part == 7) 1837dbe63bcSTom Rini part = 0; 1847dbe63bcSTom Rini 1857dbe63bcSTom Rini if (mmc_switch_part(0, part)) { 1867dbe63bcSTom Rini #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 187*91199f4aSPaul Kocialkowski puts("spl: mmc partition switch failed\n"); 1887dbe63bcSTom Rini #endif 1897dbe63bcSTom Rini hang(); 1907dbe63bcSTom Rini } 191*91199f4aSPaul Kocialkowski 1927dbe63bcSTom Rini #ifdef CONFIG_SPL_OS_BOOT 193*91199f4aSPaul Kocialkowski if (!spl_start_uboot()) { 194*91199f4aSPaul Kocialkowski err = mmc_load_image_raw_os(mmc); 195*91199f4aSPaul Kocialkowski if (!err) 196*91199f4aSPaul Kocialkowski return; 197*91199f4aSPaul Kocialkowski } 1987dbe63bcSTom Rini #endif 199b97300b6SPaul Kocialkowski err = mmc_load_image_raw_sector(mmc, 2007dbe63bcSTom Rini CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); 201*91199f4aSPaul Kocialkowski if (!err) 202*91199f4aSPaul Kocialkowski return; 2037dbe63bcSTom Rini #endif 2042c84c9a4SGuillaume GARDET case MMCSD_MODE_UNDEFINED: 2052c84c9a4SGuillaume GARDET default: 2068112f5faSPaul Burton #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 207*91199f4aSPaul Kocialkowski if (err) 208*91199f4aSPaul Kocialkowski puts("spl: mmc: no boot mode left to try\n"); 209*91199f4aSPaul Kocialkowski else 210*91199f4aSPaul Kocialkowski puts("spl: mmc: wrong boot mode\n"); 2118112f5faSPaul Burton #endif 212ade8a1a6SYing Zhang hang(); 213ade8a1a6SYing Zhang } 214ade8a1a6SYing Zhang } 215