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 * 7ade8a1a6SYing Zhang * See file CREDITS for list of people who contributed to this 8ade8a1a6SYing Zhang * project. 9ade8a1a6SYing Zhang * 10ade8a1a6SYing Zhang * This program is free software; you can redistribute it and/or 11ade8a1a6SYing Zhang * modify it under the terms of the GNU General Public License as 12ade8a1a6SYing Zhang * published by the Free Software Foundation; either version 2 of 13ade8a1a6SYing Zhang * the License, or (at your option) any later version. 14ade8a1a6SYing Zhang * 15ade8a1a6SYing Zhang * This program is distributed in the hope that it will be useful, 16ade8a1a6SYing Zhang * but WITHOUT ANY WARRANTY; without even the implied warranty of 17ade8a1a6SYing Zhang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18ade8a1a6SYing Zhang * GNU General Public License for more details. 19ade8a1a6SYing Zhang * 20ade8a1a6SYing Zhang * You should have received a copy of the GNU General Public License 21ade8a1a6SYing Zhang * along with this program; if not, write to the Free Software 22ade8a1a6SYing Zhang * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 23ade8a1a6SYing Zhang * MA 02111-1307 USA 24ade8a1a6SYing Zhang */ 25ade8a1a6SYing Zhang #include <common.h> 26ade8a1a6SYing Zhang #include <spl.h> 27ade8a1a6SYing Zhang #include <asm/u-boot.h> 28ade8a1a6SYing Zhang #include <asm/utils.h> 29ade8a1a6SYing Zhang #include <mmc.h> 30ade8a1a6SYing Zhang #include <fat.h> 31ade8a1a6SYing Zhang #include <version.h> 32ade8a1a6SYing Zhang 33ade8a1a6SYing Zhang DECLARE_GLOBAL_DATA_PTR; 34ade8a1a6SYing Zhang 3579adb7a2SPeter Korsgaard static int mmc_load_image_raw(struct mmc *mmc) 36ade8a1a6SYing Zhang { 37ade8a1a6SYing Zhang unsigned long err; 38ade8a1a6SYing Zhang u32 image_size_sectors; 39ade8a1a6SYing Zhang struct image_header *header; 40ade8a1a6SYing Zhang 41ade8a1a6SYing Zhang header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - 42ade8a1a6SYing Zhang sizeof(struct image_header)); 43ade8a1a6SYing Zhang 44ade8a1a6SYing Zhang /* read image header to find the image size & load address */ 45ade8a1a6SYing Zhang err = mmc->block_dev.block_read(0, 46ade8a1a6SYing Zhang CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR, 1, 47ade8a1a6SYing Zhang header); 48ade8a1a6SYing Zhang 49ade8a1a6SYing Zhang if (err == 0) 50ade8a1a6SYing Zhang goto end; 51ade8a1a6SYing Zhang 52ade8a1a6SYing Zhang spl_parse_image_header(header); 53ade8a1a6SYing Zhang 54ade8a1a6SYing Zhang /* convert size to sectors - round up */ 55ade8a1a6SYing Zhang image_size_sectors = (spl_image.size + mmc->read_bl_len - 1) / 56ade8a1a6SYing Zhang mmc->read_bl_len; 57ade8a1a6SYing Zhang 58ade8a1a6SYing Zhang /* Read the header too to avoid extra memcpy */ 59ade8a1a6SYing Zhang err = mmc->block_dev.block_read(0, 60ade8a1a6SYing Zhang CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR, 61ade8a1a6SYing Zhang image_size_sectors, (void *)spl_image.load_addr); 62ade8a1a6SYing Zhang 63ade8a1a6SYing Zhang end: 6479adb7a2SPeter Korsgaard if (err == 0) 65ade8a1a6SYing Zhang printf("spl: mmc blk read err - %lu\n", err); 6679adb7a2SPeter Korsgaard 6779adb7a2SPeter Korsgaard return (err == 0); 68ade8a1a6SYing Zhang } 69ade8a1a6SYing Zhang 70ade8a1a6SYing Zhang #ifdef CONFIG_SPL_FAT_SUPPORT 712fabd0bcSPeter Korsgaard static int mmc_load_image_fat(struct mmc *mmc, const char *filename) 72ade8a1a6SYing Zhang { 73ade8a1a6SYing Zhang int err; 74ade8a1a6SYing Zhang struct image_header *header; 75ade8a1a6SYing Zhang 76ade8a1a6SYing Zhang header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - 77ade8a1a6SYing Zhang sizeof(struct image_header)); 78ade8a1a6SYing Zhang 792fabd0bcSPeter Korsgaard err = file_fat_read(filename, header, sizeof(struct image_header)); 80ade8a1a6SYing Zhang if (err <= 0) 81ade8a1a6SYing Zhang goto end; 82ade8a1a6SYing Zhang 83ade8a1a6SYing Zhang spl_parse_image_header(header); 84ade8a1a6SYing Zhang 852fabd0bcSPeter Korsgaard err = file_fat_read(filename, (u8 *)spl_image.load_addr, 0); 86ade8a1a6SYing Zhang 87ade8a1a6SYing Zhang end: 8879adb7a2SPeter Korsgaard if (err <= 0) 89ade8a1a6SYing Zhang printf("spl: error reading image %s, err - %d\n", 902fabd0bcSPeter Korsgaard filename, err); 9179adb7a2SPeter Korsgaard 9279adb7a2SPeter Korsgaard return (err <= 0); 93ade8a1a6SYing Zhang } 94*7ad2cc79SPeter Korsgaard 95*7ad2cc79SPeter Korsgaard #ifdef CONFIG_SPL_OS_BOOT 96*7ad2cc79SPeter Korsgaard static int mmc_load_image_fat_os(struct mmc *mmc) 97*7ad2cc79SPeter Korsgaard { 98*7ad2cc79SPeter Korsgaard int err; 99*7ad2cc79SPeter Korsgaard 100*7ad2cc79SPeter Korsgaard err = file_fat_read(CONFIG_SPL_FAT_LOAD_ARGS_NAME, 101*7ad2cc79SPeter Korsgaard (void *)CONFIG_SYS_SPL_ARGS_ADDR, 0); 102*7ad2cc79SPeter Korsgaard if (err <= 0) { 103*7ad2cc79SPeter Korsgaard printf("spl: error reading image %s, err - %d\n", 104*7ad2cc79SPeter Korsgaard CONFIG_SPL_FAT_LOAD_ARGS_NAME, err); 105*7ad2cc79SPeter Korsgaard return -1; 106*7ad2cc79SPeter Korsgaard } 107*7ad2cc79SPeter Korsgaard 108*7ad2cc79SPeter Korsgaard return mmc_load_image_fat(mmc, CONFIG_SPL_FAT_LOAD_KERNEL_NAME); 109*7ad2cc79SPeter Korsgaard } 110*7ad2cc79SPeter Korsgaard #endif 111*7ad2cc79SPeter Korsgaard 112ade8a1a6SYing Zhang #endif 113ade8a1a6SYing Zhang 114ade8a1a6SYing Zhang void spl_mmc_load_image(void) 115ade8a1a6SYing Zhang { 116ade8a1a6SYing Zhang struct mmc *mmc; 117ade8a1a6SYing Zhang int err; 118ade8a1a6SYing Zhang u32 boot_mode; 119ade8a1a6SYing Zhang 120ade8a1a6SYing Zhang mmc_initialize(gd->bd); 121ade8a1a6SYing Zhang /* We register only one device. So, the dev id is always 0 */ 122ade8a1a6SYing Zhang mmc = find_mmc_device(0); 123ade8a1a6SYing Zhang if (!mmc) { 124ade8a1a6SYing Zhang puts("spl: mmc device not found!!\n"); 125ade8a1a6SYing Zhang hang(); 126ade8a1a6SYing Zhang } 127ade8a1a6SYing Zhang 128ade8a1a6SYing Zhang err = mmc_init(mmc); 129ade8a1a6SYing Zhang if (err) { 130ade8a1a6SYing Zhang printf("spl: mmc init failed: err - %d\n", err); 131ade8a1a6SYing Zhang hang(); 132ade8a1a6SYing Zhang } 13379adb7a2SPeter Korsgaard 134ade8a1a6SYing Zhang boot_mode = spl_boot_mode(); 135ade8a1a6SYing Zhang if (boot_mode == MMCSD_MODE_RAW) { 136ade8a1a6SYing Zhang debug("boot mode - RAW\n"); 13779adb7a2SPeter Korsgaard err = mmc_load_image_raw(mmc); 138ade8a1a6SYing Zhang #ifdef CONFIG_SPL_FAT_SUPPORT 139ade8a1a6SYing Zhang } else if (boot_mode == MMCSD_MODE_FAT) { 140ade8a1a6SYing Zhang debug("boot mode - FAT\n"); 1412fabd0bcSPeter Korsgaard 1422fabd0bcSPeter Korsgaard err = fat_register_device(&mmc->block_dev, 1432fabd0bcSPeter Korsgaard CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION); 1442fabd0bcSPeter Korsgaard if (err) { 1452fabd0bcSPeter Korsgaard printf("spl: fat register err - %d\n", err); 1462fabd0bcSPeter Korsgaard hang(); 1472fabd0bcSPeter Korsgaard } 1482fabd0bcSPeter Korsgaard 149*7ad2cc79SPeter Korsgaard #ifdef CONFIG_SPL_OS_BOOT 150*7ad2cc79SPeter Korsgaard if (spl_start_uboot() || mmc_load_image_fat_os(mmc)) 151*7ad2cc79SPeter Korsgaard #endif 1522fabd0bcSPeter Korsgaard err = mmc_load_image_fat(mmc, CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME); 153ade8a1a6SYing Zhang #endif 154ade8a1a6SYing Zhang } else { 155ade8a1a6SYing Zhang puts("spl: wrong MMC boot mode\n"); 156ade8a1a6SYing Zhang hang(); 157ade8a1a6SYing Zhang } 15879adb7a2SPeter Korsgaard 15979adb7a2SPeter Korsgaard if (err) 16079adb7a2SPeter Korsgaard hang(); 161ade8a1a6SYing Zhang } 162