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> 11ade8a1a6SYing Zhang #include <asm/u-boot.h> 12ade8a1a6SYing Zhang #include <mmc.h> 13ade8a1a6SYing Zhang #include <fat.h> 14ade8a1a6SYing Zhang #include <version.h> 15e4c444b3STom Rini #include <image.h> 16ade8a1a6SYing Zhang 17ade8a1a6SYing Zhang DECLARE_GLOBAL_DATA_PTR; 18ade8a1a6SYing Zhang 19721931f8SPeter Korsgaard static int mmc_load_image_raw(struct mmc *mmc, unsigned long sector) 20ade8a1a6SYing Zhang { 21ade8a1a6SYing Zhang unsigned long err; 22ade8a1a6SYing Zhang u32 image_size_sectors; 23ade8a1a6SYing Zhang struct image_header *header; 24ade8a1a6SYing Zhang 25ade8a1a6SYing Zhang header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - 26ade8a1a6SYing Zhang sizeof(struct image_header)); 27ade8a1a6SYing Zhang 28ade8a1a6SYing Zhang /* read image header to find the image size & load address */ 29721931f8SPeter Korsgaard err = mmc->block_dev.block_read(0, sector, 1, header); 30ade8a1a6SYing Zhang if (err == 0) 31ade8a1a6SYing Zhang goto end; 32ade8a1a6SYing Zhang 33e4c444b3STom Rini if (image_get_magic(header) != IH_MAGIC) 34e4c444b3STom Rini return -1; 35e4c444b3STom Rini 36ade8a1a6SYing Zhang spl_parse_image_header(header); 37ade8a1a6SYing Zhang 38ade8a1a6SYing Zhang /* convert size to sectors - round up */ 39ade8a1a6SYing Zhang image_size_sectors = (spl_image.size + mmc->read_bl_len - 1) / 40ade8a1a6SYing Zhang mmc->read_bl_len; 41ade8a1a6SYing Zhang 42ade8a1a6SYing Zhang /* Read the header too to avoid extra memcpy */ 43721931f8SPeter Korsgaard err = mmc->block_dev.block_read(0, sector, image_size_sectors, 44721931f8SPeter Korsgaard (void *)spl_image.load_addr); 45ade8a1a6SYing Zhang 46ade8a1a6SYing Zhang end: 47*8112f5faSPaul Burton #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 4879adb7a2SPeter Korsgaard if (err == 0) 49ade8a1a6SYing Zhang printf("spl: mmc blk read err - %lu\n", err); 50*8112f5faSPaul Burton #endif 5179adb7a2SPeter Korsgaard 5279adb7a2SPeter Korsgaard return (err == 0); 53ade8a1a6SYing Zhang } 54ade8a1a6SYing Zhang 552b75b0adSPeter Korsgaard #ifdef CONFIG_SPL_OS_BOOT 562b75b0adSPeter Korsgaard static int mmc_load_image_raw_os(struct mmc *mmc) 572b75b0adSPeter Korsgaard { 582b75b0adSPeter Korsgaard if (!mmc->block_dev.block_read(0, 592b75b0adSPeter Korsgaard CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR, 602b75b0adSPeter Korsgaard CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS, 612b75b0adSPeter Korsgaard (void *)CONFIG_SYS_SPL_ARGS_ADDR)) { 62*8112f5faSPaul Burton #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 632b75b0adSPeter Korsgaard printf("mmc args blk read error\n"); 64*8112f5faSPaul Burton #endif 652b75b0adSPeter Korsgaard return -1; 662b75b0adSPeter Korsgaard } 672b75b0adSPeter Korsgaard 682b75b0adSPeter Korsgaard return mmc_load_image_raw(mmc, CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR); 692b75b0adSPeter Korsgaard } 702b75b0adSPeter Korsgaard #endif 712b75b0adSPeter Korsgaard 72ade8a1a6SYing Zhang #ifdef CONFIG_SPL_FAT_SUPPORT 732fabd0bcSPeter Korsgaard static int mmc_load_image_fat(struct mmc *mmc, const char *filename) 74ade8a1a6SYing Zhang { 75ade8a1a6SYing Zhang int err; 76ade8a1a6SYing Zhang struct image_header *header; 77ade8a1a6SYing Zhang 78ade8a1a6SYing Zhang header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - 79ade8a1a6SYing Zhang sizeof(struct image_header)); 80ade8a1a6SYing Zhang 812fabd0bcSPeter Korsgaard err = file_fat_read(filename, header, sizeof(struct image_header)); 82ade8a1a6SYing Zhang if (err <= 0) 83ade8a1a6SYing Zhang goto end; 84ade8a1a6SYing Zhang 85ade8a1a6SYing Zhang spl_parse_image_header(header); 86ade8a1a6SYing Zhang 872fabd0bcSPeter Korsgaard err = file_fat_read(filename, (u8 *)spl_image.load_addr, 0); 88ade8a1a6SYing Zhang 89ade8a1a6SYing Zhang end: 90*8112f5faSPaul Burton #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 9179adb7a2SPeter Korsgaard if (err <= 0) 92ade8a1a6SYing Zhang printf("spl: error reading image %s, err - %d\n", 932fabd0bcSPeter Korsgaard filename, err); 94*8112f5faSPaul Burton #endif 9579adb7a2SPeter Korsgaard 9679adb7a2SPeter Korsgaard return (err <= 0); 97ade8a1a6SYing Zhang } 987ad2cc79SPeter Korsgaard 997ad2cc79SPeter Korsgaard #ifdef CONFIG_SPL_OS_BOOT 1007ad2cc79SPeter Korsgaard static int mmc_load_image_fat_os(struct mmc *mmc) 1017ad2cc79SPeter Korsgaard { 1027ad2cc79SPeter Korsgaard int err; 1037ad2cc79SPeter Korsgaard 1047ad2cc79SPeter Korsgaard err = file_fat_read(CONFIG_SPL_FAT_LOAD_ARGS_NAME, 1057ad2cc79SPeter Korsgaard (void *)CONFIG_SYS_SPL_ARGS_ADDR, 0); 1067ad2cc79SPeter Korsgaard if (err <= 0) { 107*8112f5faSPaul Burton #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 1087ad2cc79SPeter Korsgaard printf("spl: error reading image %s, err - %d\n", 1097ad2cc79SPeter Korsgaard CONFIG_SPL_FAT_LOAD_ARGS_NAME, err); 110*8112f5faSPaul Burton #endif 1117ad2cc79SPeter Korsgaard return -1; 1127ad2cc79SPeter Korsgaard } 1137ad2cc79SPeter Korsgaard 1147ad2cc79SPeter Korsgaard return mmc_load_image_fat(mmc, CONFIG_SPL_FAT_LOAD_KERNEL_NAME); 1157ad2cc79SPeter Korsgaard } 1167ad2cc79SPeter Korsgaard #endif 1177ad2cc79SPeter Korsgaard 118ade8a1a6SYing Zhang #endif 119ade8a1a6SYing Zhang 120ade8a1a6SYing Zhang void spl_mmc_load_image(void) 121ade8a1a6SYing Zhang { 122ade8a1a6SYing Zhang struct mmc *mmc; 123ade8a1a6SYing Zhang int err; 124ade8a1a6SYing Zhang u32 boot_mode; 125ade8a1a6SYing Zhang 126ade8a1a6SYing Zhang mmc_initialize(gd->bd); 127ade8a1a6SYing Zhang /* We register only one device. So, the dev id is always 0 */ 128ade8a1a6SYing Zhang mmc = find_mmc_device(0); 129ade8a1a6SYing Zhang if (!mmc) { 130*8112f5faSPaul Burton #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 131ade8a1a6SYing Zhang puts("spl: mmc device not found!!\n"); 132*8112f5faSPaul Burton #endif 133ade8a1a6SYing Zhang hang(); 134ade8a1a6SYing Zhang } 135ade8a1a6SYing Zhang 136ade8a1a6SYing Zhang err = mmc_init(mmc); 137ade8a1a6SYing Zhang if (err) { 138*8112f5faSPaul Burton #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 139ade8a1a6SYing Zhang printf("spl: mmc init failed: err - %d\n", err); 140*8112f5faSPaul Burton #endif 141ade8a1a6SYing Zhang hang(); 142ade8a1a6SYing Zhang } 14379adb7a2SPeter Korsgaard 144ade8a1a6SYing Zhang boot_mode = spl_boot_mode(); 145ade8a1a6SYing Zhang if (boot_mode == MMCSD_MODE_RAW) { 146ade8a1a6SYing Zhang debug("boot mode - RAW\n"); 1472b75b0adSPeter Korsgaard #ifdef CONFIG_SPL_OS_BOOT 1482b75b0adSPeter Korsgaard if (spl_start_uboot() || mmc_load_image_raw_os(mmc)) 1492b75b0adSPeter Korsgaard #endif 150721931f8SPeter Korsgaard err = mmc_load_image_raw(mmc, 151721931f8SPeter Korsgaard CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); 152ade8a1a6SYing Zhang #ifdef CONFIG_SPL_FAT_SUPPORT 153ade8a1a6SYing Zhang } else if (boot_mode == MMCSD_MODE_FAT) { 154ade8a1a6SYing Zhang debug("boot mode - FAT\n"); 1552fabd0bcSPeter Korsgaard 1562fabd0bcSPeter Korsgaard err = fat_register_device(&mmc->block_dev, 1572fabd0bcSPeter Korsgaard CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION); 1582fabd0bcSPeter Korsgaard if (err) { 159*8112f5faSPaul Burton #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 1602fabd0bcSPeter Korsgaard printf("spl: fat register err - %d\n", err); 161*8112f5faSPaul Burton #endif 1622fabd0bcSPeter Korsgaard hang(); 1632fabd0bcSPeter Korsgaard } 1642fabd0bcSPeter Korsgaard 1657ad2cc79SPeter Korsgaard #ifdef CONFIG_SPL_OS_BOOT 1667ad2cc79SPeter Korsgaard if (spl_start_uboot() || mmc_load_image_fat_os(mmc)) 1677ad2cc79SPeter Korsgaard #endif 1682fabd0bcSPeter Korsgaard err = mmc_load_image_fat(mmc, CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME); 169ade8a1a6SYing Zhang #endif 170ade8a1a6SYing Zhang } else { 171*8112f5faSPaul Burton #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 172ade8a1a6SYing Zhang puts("spl: wrong MMC boot mode\n"); 173*8112f5faSPaul Burton #endif 174ade8a1a6SYing Zhang hang(); 175ade8a1a6SYing Zhang } 17679adb7a2SPeter Korsgaard 17779adb7a2SPeter Korsgaard if (err) 17879adb7a2SPeter Korsgaard hang(); 179ade8a1a6SYing Zhang } 180