1 /* 2 * (C) Copyright 2010 3 * Texas Instruments, <www.ti.com> 4 * 5 * Aneesh V <aneesh@ti.com> 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 #include <common.h> 10 #include <dm.h> 11 #include <spl.h> 12 #include <linux/compiler.h> 13 #include <asm/u-boot.h> 14 #include <mmc.h> 15 #include <image.h> 16 17 DECLARE_GLOBAL_DATA_PTR; 18 19 static int mmc_load_image_raw_sector(struct mmc *mmc, unsigned long sector) 20 { 21 unsigned long count; 22 u32 image_size_sectors; 23 struct image_header *header; 24 25 header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - 26 sizeof(struct image_header)); 27 28 /* read image header to find the image size & load address */ 29 count = mmc->block_dev.block_read(0, sector, 1, header); 30 debug("read sector %lx, count=%lu\n", sector, count); 31 if (count == 0) 32 goto end; 33 34 if (image_get_magic(header) != IH_MAGIC) { 35 puts("bad magic\n"); 36 return -1; 37 } 38 39 spl_parse_image_header(header); 40 41 /* convert size to sectors - round up */ 42 image_size_sectors = (spl_image.size + mmc->read_bl_len - 1) / 43 mmc->read_bl_len; 44 45 /* Read the header too to avoid extra memcpy */ 46 count = mmc->block_dev.block_read(0, sector, image_size_sectors, 47 (void *)spl_image.load_addr); 48 debug("read %x sectors to %x\n", image_size_sectors, 49 spl_image.load_addr); 50 51 end: 52 if (count == 0) { 53 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 54 puts("spl: mmc block read error\n"); 55 #endif 56 return -1; 57 } 58 59 return 0; 60 } 61 62 #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION 63 static int mmc_load_image_raw_partition(struct mmc *mmc, int partition) 64 { 65 disk_partition_t info; 66 int err; 67 68 err = get_partition_info(&mmc->block_dev, partition, &info); 69 if (err) { 70 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 71 puts("spl: partition error\n"); 72 #endif 73 return -1; 74 } 75 76 #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 77 return mmc_load_image_raw_sector(mmc, info.start + 78 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); 79 #else 80 return mmc_load_image_raw_sector(mmc, info.start); 81 #endif 82 } 83 #endif 84 85 #ifdef CONFIG_SPL_OS_BOOT 86 static int mmc_load_image_raw_os(struct mmc *mmc) 87 { 88 unsigned long count; 89 90 count = mmc->block_dev.block_read(0, 91 CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR, 92 CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS, 93 (void *) CONFIG_SYS_SPL_ARGS_ADDR); 94 if (count == 0) { 95 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 96 puts("spl: mmc block read error\n"); 97 #endif 98 return -1; 99 } 100 101 return mmc_load_image_raw_sector(mmc, 102 CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR); 103 } 104 #endif 105 106 void spl_mmc_load_image(void) 107 { 108 struct mmc *mmc; 109 u32 boot_mode; 110 int err = 0; 111 __maybe_unused int part; 112 113 #ifdef CONFIG_DM_MMC 114 struct udevice *dev; 115 116 mmc_initialize(NULL); 117 err = uclass_get_device(UCLASS_MMC, 0, &dev); 118 mmc = NULL; 119 if (!err) 120 mmc = mmc_get_mmc_dev(dev); 121 #else 122 mmc_initialize(gd->bd); 123 124 /* We register only one device. So, the dev id is always 0 */ 125 mmc = find_mmc_device(0); 126 if (!mmc) { 127 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 128 puts("spl: mmc device not found\n"); 129 #endif 130 hang(); 131 } 132 #endif 133 134 if (!err) 135 err = mmc_init(mmc); 136 137 if (err) { 138 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 139 printf("spl: mmc init failed with error: %d\n", err); 140 #endif 141 hang(); 142 } 143 144 boot_mode = spl_boot_mode(); 145 switch (boot_mode) { 146 case MMCSD_MODE_RAW: 147 debug("spl: mmc boot mode: raw\n"); 148 149 #ifdef CONFIG_SPL_OS_BOOT 150 if (!spl_start_uboot()) { 151 err = mmc_load_image_raw_os(mmc); 152 if (!err) 153 return; 154 } 155 #endif 156 #if defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION) 157 err = mmc_load_image_raw_partition(mmc, 158 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION); 159 if (!err) 160 return; 161 #elif defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR) 162 err = mmc_load_image_raw_sector(mmc, 163 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); 164 if (!err) 165 return; 166 #endif 167 case MMCSD_MODE_FS: 168 debug("spl: mmc boot mode: fs\n"); 169 170 #ifdef CONFIG_SYS_MMCSD_FS_BOOT_PARTITION 171 #ifdef CONFIG_SPL_FAT_SUPPORT 172 #ifdef CONFIG_SPL_OS_BOOT 173 if (!spl_start_uboot()) { 174 err = spl_load_image_fat_os(&mmc->block_dev, 175 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION); 176 if (!err) 177 return; 178 } 179 #endif 180 #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME 181 err = spl_load_image_fat(&mmc->block_dev, 182 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, 183 CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); 184 if (!err) 185 return; 186 #endif 187 #endif 188 #ifdef CONFIG_SPL_EXT_SUPPORT 189 #ifdef CONFIG_SPL_OS_BOOT 190 if (!spl_start_uboot()) { 191 err = spl_load_image_ext_os(&mmc->block_dev, 192 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION); 193 if (!err) 194 return; 195 } 196 #endif 197 #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME 198 err = spl_load_image_ext(&mmc->block_dev, 199 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, 200 CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); 201 if (!err) 202 return; 203 #endif 204 #endif 205 #endif 206 #ifdef CONFIG_SUPPORT_EMMC_BOOT 207 case MMCSD_MODE_EMMCBOOT: 208 /* 209 * We need to check what the partition is configured to. 210 * 1 and 2 match up to boot0 / boot1 and 7 is user data 211 * which is the first physical partition (0). 212 */ 213 part = (mmc->part_config >> 3) & PART_ACCESS_MASK; 214 215 if (part == 7) 216 part = 0; 217 218 if (mmc_switch_part(0, part)) { 219 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 220 puts("spl: mmc partition switch failed\n"); 221 #endif 222 hang(); 223 } 224 225 #ifdef CONFIG_SPL_OS_BOOT 226 if (!spl_start_uboot()) { 227 err = mmc_load_image_raw_os(mmc); 228 if (!err) 229 return; 230 } 231 #endif 232 #if defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION) 233 err = mmc_load_image_raw_partition(mmc, 234 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION); 235 if (!err) 236 return; 237 #elif defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR) 238 err = mmc_load_image_raw_sector(mmc, 239 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); 240 if (!err) 241 return; 242 #endif 243 #endif 244 case MMCSD_MODE_UNDEFINED: 245 default: 246 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 247 if (err) 248 puts("spl: mmc: no boot mode left to try\n"); 249 else 250 puts("spl: mmc: wrong boot mode\n"); 251 #endif 252 hang(); 253 } 254 } 255