uboot/common/spl/spl_mmc.c
<<
>>
Prefs
   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 <errno.h>
  14#include <asm/u-boot.h>
  15#include <errno.h>
  16#include <mmc.h>
  17#include <image.h>
  18
  19DECLARE_GLOBAL_DATA_PTR;
  20
  21static int mmc_load_legacy(struct spl_image_info *spl_image, struct mmc *mmc,
  22                           ulong sector, struct image_header *header)
  23{
  24        u32 image_size_sectors;
  25        unsigned long count;
  26        int ret;
  27
  28        ret = spl_parse_image_header(spl_image, header);
  29        if (ret)
  30                return ret;
  31
  32        /* convert size to sectors - round up */
  33        image_size_sectors = (spl_image->size + mmc->read_bl_len - 1) /
  34                             mmc->read_bl_len;
  35
  36        /* Read the header too to avoid extra memcpy */
  37        count = blk_dread(mmc_get_blk_desc(mmc), sector, image_size_sectors,
  38                          (void *)(ulong)spl_image->load_addr);
  39        debug("read %x sectors to %lx\n", image_size_sectors,
  40              spl_image->load_addr);
  41        if (count != image_size_sectors)
  42                return -EIO;
  43
  44        return 0;
  45}
  46
  47static ulong h_spl_load_read(struct spl_load_info *load, ulong sector,
  48                             ulong count, void *buf)
  49{
  50        struct mmc *mmc = load->dev;
  51
  52        return blk_dread(mmc_get_blk_desc(mmc), sector, count, buf);
  53}
  54
  55static __maybe_unused
  56int mmc_load_image_raw_sector(struct spl_image_info *spl_image,
  57                              struct mmc *mmc, unsigned long sector)
  58{
  59        unsigned long count;
  60        struct image_header *header;
  61        int ret = 0;
  62
  63        header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
  64                                         sizeof(struct image_header));
  65
  66        /* read image header to find the image size & load address */
  67        count = blk_dread(mmc_get_blk_desc(mmc), sector, 1, header);
  68        debug("hdr read sector %lx, count=%lu\n", sector, count);
  69        if (count == 0) {
  70                ret = -EIO;
  71                goto end;
  72        }
  73
  74        if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
  75            image_get_magic(header) == FDT_MAGIC) {
  76                struct spl_load_info load;
  77
  78                debug("Found FIT\n");
  79                load.dev = mmc;
  80                load.priv = NULL;
  81                load.filename = NULL;
  82                load.bl_len = mmc->read_bl_len;
  83                load.read = h_spl_load_read;
  84                ret = spl_load_simple_fit(spl_image, &load, sector, header);
  85        } else {
  86                ret = mmc_load_legacy(spl_image, mmc, sector, header);
  87        }
  88
  89end:
  90        if (ret) {
  91#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
  92                puts("mmc_load_image_raw_sector: mmc block read error\n");
  93#endif
  94                return -1;
  95        }
  96
  97        return 0;
  98}
  99
 100static int spl_mmc_get_device_index(u32 boot_device)
 101{
 102        switch (boot_device) {
 103        case BOOT_DEVICE_MMC1:
 104                return 0;
 105        case BOOT_DEVICE_MMC2:
 106        case BOOT_DEVICE_MMC2_2:
 107                return 1;
 108        }
 109
 110#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
 111        printf("spl: unsupported mmc boot device.\n");
 112#endif
 113
 114        return -ENODEV;
 115}
 116
 117static int spl_mmc_find_device(struct mmc **mmcp, u32 boot_device)
 118{
 119#if CONFIG_IS_ENABLED(DM_MMC)
 120        struct udevice *dev;
 121#endif
 122        int err, mmc_dev;
 123
 124        mmc_dev = spl_mmc_get_device_index(boot_device);
 125        if (mmc_dev < 0)
 126                return mmc_dev;
 127
 128        err = mmc_initialize(NULL);
 129        if (err) {
 130#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
 131                printf("spl: could not initialize mmc. error: %d\n", err);
 132#endif
 133                return err;
 134        }
 135
 136#if CONFIG_IS_ENABLED(DM_MMC)
 137        err = uclass_get_device(UCLASS_MMC, mmc_dev, &dev);
 138        if (!err)
 139                *mmcp = mmc_get_mmc_dev(dev);
 140#else
 141        *mmcp = find_mmc_device(mmc_dev);
 142        err = *mmcp ? 0 : -ENODEV;
 143#endif
 144        if (err) {
 145#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
 146                printf("spl: could not find mmc device. error: %d\n", err);
 147#endif
 148                return err;
 149        }
 150
 151        return 0;
 152}
 153
 154#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
 155static int mmc_load_image_raw_partition(struct spl_image_info *spl_image,
 156                                        struct mmc *mmc, int partition)
 157{
 158        disk_partition_t info;
 159        int err;
 160
 161#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE
 162        int type_part;
 163        /* Only support MBR so DOS_ENTRY_NUMBERS */
 164        for (type_part = 1; type_part <= DOS_ENTRY_NUMBERS; type_part++) {
 165                err = part_get_info(mmc_get_blk_desc(mmc), type_part, &info);
 166                if (err)
 167                        continue;
 168                if (info.sys_ind == 
 169                        CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_TYPE) {
 170                        partition = type_part;
 171                        break;
 172                }
 173        }
 174#endif
 175
 176        err = part_get_info(mmc_get_blk_desc(mmc), partition, &info);
 177        if (err) {
 178#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
 179                puts("spl: partition error\n");
 180#endif
 181                return -1;
 182        }
 183
 184#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
 185        return mmc_load_image_raw_sector(spl_image, mmc,
 186                        info.start + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
 187#else
 188        return mmc_load_image_raw_sector(spl_image, mmc, info.start);
 189#endif
 190}
 191#endif
 192
 193#ifdef CONFIG_SPL_OS_BOOT
 194static int mmc_load_image_raw_os(struct spl_image_info *spl_image,
 195                                 struct mmc *mmc)
 196{
 197        unsigned long count;
 198        int ret;
 199
 200        count = blk_dread(mmc_get_blk_desc(mmc),
 201                CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR,
 202                CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS,
 203                (void *) CONFIG_SYS_SPL_ARGS_ADDR);
 204        if (count != CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS) {
 205#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
 206                puts("mmc_load_image_raw_os: mmc block read error\n");
 207#endif
 208                return -1;
 209        }
 210
 211        ret = mmc_load_image_raw_sector(spl_image, mmc,
 212                CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR);
 213        if (ret)
 214                return ret;
 215
 216        if (spl_image->os != IH_OS_LINUX) {
 217                puts("Expected Linux image is not found. Trying to start U-boot\n");
 218                return -ENOENT;
 219        }
 220
 221        return 0;
 222}
 223#else
 224int spl_start_uboot(void)
 225{
 226        return 1;
 227}
 228static int mmc_load_image_raw_os(struct spl_image_info *spl_image,
 229                                 struct mmc *mmc)
 230{
 231        return -ENOSYS;
 232}
 233#endif
 234
 235#ifdef CONFIG_SYS_MMCSD_FS_BOOT_PARTITION
 236static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc)
 237{
 238        int err = -ENOSYS;
 239
 240#ifdef CONFIG_SPL_FAT_SUPPORT
 241        if (!spl_start_uboot()) {
 242                err = spl_load_image_fat_os(spl_image, mmc_get_blk_desc(mmc),
 243                        CONFIG_SYS_MMCSD_FS_BOOT_PARTITION);
 244                if (!err)
 245                        return err;
 246        }
 247#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
 248        err = spl_load_image_fat(spl_image, mmc_get_blk_desc(mmc),
 249                                 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
 250                                 CONFIG_SPL_FS_LOAD_PAYLOAD_NAME);
 251        if (!err)
 252                return err;
 253#endif
 254#endif
 255#ifdef CONFIG_SPL_EXT_SUPPORT
 256        if (!spl_start_uboot()) {
 257                err = spl_load_image_ext_os(spl_image, mmc_get_blk_desc(mmc),
 258                        CONFIG_SYS_MMCSD_FS_BOOT_PARTITION);
 259                if (!err)
 260                        return err;
 261        }
 262#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
 263        err = spl_load_image_ext(spl_image, mmc_get_blk_desc(mmc),
 264                                 CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
 265                                 CONFIG_SPL_FS_LOAD_PAYLOAD_NAME);
 266        if (!err)
 267                return err;
 268#endif
 269#endif
 270
 271#if defined(CONFIG_SPL_FAT_SUPPORT) || defined(CONFIG_SPL_EXT_SUPPORT)
 272        err = -ENOENT;
 273#endif
 274
 275        return err;
 276}
 277#else
 278static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc)
 279{
 280        return -ENOSYS;
 281}
 282#endif
 283
 284int spl_mmc_load_image(struct spl_image_info *spl_image,
 285                       struct spl_boot_device *bootdev)
 286{
 287        struct mmc *mmc = NULL;
 288        u32 boot_mode;
 289        int err = 0;
 290        __maybe_unused int part;
 291
 292        err = spl_mmc_find_device(&mmc, bootdev->boot_device);
 293        if (err)
 294                return err;
 295
 296        err = mmc_init(mmc);
 297        if (err) {
 298#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
 299                printf("spl: mmc init failed with error: %d\n", err);
 300#endif
 301                return err;
 302        }
 303
 304        boot_mode = spl_boot_mode(bootdev->boot_device);
 305        err = -EINVAL;
 306        switch (boot_mode) {
 307        case MMCSD_MODE_EMMCBOOT:
 308                        /*
 309                         * We need to check what the partition is configured to.
 310                         * 1 and 2 match up to boot0 / boot1 and 7 is user data
 311                         * which is the first physical partition (0).
 312                         */
 313                        part = (mmc->part_config >> 3) & PART_ACCESS_MASK;
 314
 315                        if (part == 7)
 316                                part = 0;
 317
 318                        if (CONFIG_IS_ENABLED(MMC_TINY))
 319                                err = mmc_switch_part(mmc, part);
 320                        else
 321                                err = blk_dselect_hwpart(mmc_get_blk_desc(mmc), part);
 322
 323                        if (err) {
 324#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
 325                                puts("spl: mmc partition switch failed\n");
 326#endif
 327                                return err;
 328                        }
 329                        /* Fall through */
 330        case MMCSD_MODE_RAW:
 331                debug("spl: mmc boot mode: raw\n");
 332
 333                if (!spl_start_uboot()) {
 334                        err = mmc_load_image_raw_os(spl_image, mmc);
 335                        if (!err)
 336                                return err;
 337                }
 338#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
 339                err = mmc_load_image_raw_partition(spl_image, mmc,
 340                        CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION);
 341                if (!err)
 342                        return err;
 343#endif
 344#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
 345                err = mmc_load_image_raw_sector(spl_image, mmc,
 346                        CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
 347                if (!err)
 348                        return err;
 349#endif
 350                /* If RAW mode fails, try FS mode. */
 351        case MMCSD_MODE_FS:
 352                debug("spl: mmc boot mode: fs\n");
 353
 354                err = spl_mmc_do_fs_boot(spl_image, mmc);
 355                if (!err)
 356                        return err;
 357
 358                break;
 359#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
 360        default:
 361                puts("spl: mmc: wrong boot mode\n");
 362#endif
 363        }
 364
 365        return err;
 366}
 367
 368SPL_LOAD_IMAGE_METHOD("MMC1", 0, BOOT_DEVICE_MMC1, spl_mmc_load_image);
 369SPL_LOAD_IMAGE_METHOD("MMC2", 0, BOOT_DEVICE_MMC2, spl_mmc_load_image);
 370SPL_LOAD_IMAGE_METHOD("MMC2_2", 0, BOOT_DEVICE_MMC2_2, spl_mmc_load_image);
 371