uboot/drivers/mmc/mmc_legacy.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2016 Google, Inc
   4 * Written by Simon Glass <sjg@chromium.org>
   5 */
   6
   7#include <common.h>
   8#include <malloc.h>
   9#include <mmc.h>
  10#include "mmc_private.h"
  11
  12static struct list_head mmc_devices;
  13static int cur_dev_num = -1;
  14
  15#if CONFIG_IS_ENABLED(MMC_TINY)
  16static struct mmc mmc_static;
  17struct mmc *find_mmc_device(int dev_num)
  18{
  19        return &mmc_static;
  20}
  21
  22void mmc_do_preinit(void)
  23{
  24        struct mmc *m = &mmc_static;
  25#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
  26        mmc_set_preinit(m, 1);
  27#endif
  28        if (m->preinit)
  29                mmc_start_init(m);
  30}
  31
  32struct blk_desc *mmc_get_blk_desc(struct mmc *mmc)
  33{
  34        return &mmc->block_dev;
  35}
  36#else
  37struct mmc *find_mmc_device(int dev_num)
  38{
  39        struct mmc *m;
  40        struct list_head *entry;
  41
  42        list_for_each(entry, &mmc_devices) {
  43                m = list_entry(entry, struct mmc, link);
  44
  45                if (m->block_dev.devnum == dev_num)
  46                        return m;
  47        }
  48
  49#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
  50        printf("MMC Device %d not found\n", dev_num);
  51#endif
  52
  53        return NULL;
  54}
  55
  56int mmc_get_next_devnum(void)
  57{
  58        return cur_dev_num++;
  59}
  60
  61struct blk_desc *mmc_get_blk_desc(struct mmc *mmc)
  62{
  63        return &mmc->block_dev;
  64}
  65
  66int get_mmc_num(void)
  67{
  68        return cur_dev_num;
  69}
  70
  71void mmc_do_preinit(void)
  72{
  73        struct mmc *m;
  74        struct list_head *entry;
  75
  76        list_for_each(entry, &mmc_devices) {
  77                m = list_entry(entry, struct mmc, link);
  78
  79#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
  80                mmc_set_preinit(m, 1);
  81#endif
  82                if (m->preinit)
  83                        mmc_start_init(m);
  84        }
  85}
  86#endif
  87
  88void mmc_list_init(void)
  89{
  90        INIT_LIST_HEAD(&mmc_devices);
  91        cur_dev_num = 0;
  92}
  93
  94void mmc_list_add(struct mmc *mmc)
  95{
  96        INIT_LIST_HEAD(&mmc->link);
  97
  98        list_add_tail(&mmc->link, &mmc_devices);
  99}
 100
 101#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
 102void print_mmc_devices(char separator)
 103{
 104        struct mmc *m;
 105        struct list_head *entry;
 106        char *mmc_type;
 107
 108        list_for_each(entry, &mmc_devices) {
 109                m = list_entry(entry, struct mmc, link);
 110
 111                if (m->has_init)
 112                        mmc_type = IS_SD(m) ? "SD" : "eMMC";
 113                else
 114                        mmc_type = NULL;
 115
 116                printf("%s: %d", m->cfg->name, m->block_dev.devnum);
 117                if (mmc_type)
 118                        printf(" (%s)", mmc_type);
 119
 120                if (entry->next != &mmc_devices) {
 121                        printf("%c", separator);
 122                        if (separator != '\n')
 123                                puts(" ");
 124                }
 125        }
 126
 127        printf("\n");
 128}
 129
 130#else
 131void print_mmc_devices(char separator) { }
 132#endif
 133
 134#if CONFIG_IS_ENABLED(MMC_TINY)
 135static struct mmc mmc_static = {
 136        .dsr_imp                = 0,
 137        .dsr                    = 0xffffffff,
 138        .block_dev = {
 139                .if_type        = IF_TYPE_MMC,
 140                .removable      = 1,
 141                .devnum         = 0,
 142                .block_read     = mmc_bread,
 143                .block_write    = mmc_bwrite,
 144                .block_erase    = mmc_berase,
 145                .part_type      = 0,
 146        },
 147};
 148
 149struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
 150{
 151        struct mmc *mmc = &mmc_static;
 152
 153        /* First MMC device registered, fail to register a new one.
 154         * Given users are not expecting this to fail, instead
 155         * of failing let's just return the only MMC device
 156         */
 157        if (mmc->cfg) {
 158                debug("Warning: MMC_TINY doesn't support multiple MMC devices\n");
 159                return mmc;
 160        }
 161
 162        mmc->cfg = cfg;
 163        mmc->priv = priv;
 164
 165        return mmc;
 166}
 167
 168void mmc_destroy(struct mmc *mmc)
 169{
 170}
 171#else
 172struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
 173{
 174        struct blk_desc *bdesc;
 175        struct mmc *mmc;
 176
 177        /* quick validation */
 178        if (cfg == NULL || cfg->f_min == 0 ||
 179            cfg->f_max == 0 || cfg->b_max == 0)
 180                return NULL;
 181
 182#if !CONFIG_IS_ENABLED(DM_MMC)
 183        if (cfg->ops == NULL || cfg->ops->send_cmd == NULL)
 184                return NULL;
 185#endif
 186
 187        mmc = calloc(1, sizeof(*mmc));
 188        if (mmc == NULL)
 189                return NULL;
 190
 191        mmc->cfg = cfg;
 192        mmc->priv = priv;
 193
 194        /* the following chunk was mmc_register() */
 195
 196        /* Setup dsr related values */
 197        mmc->dsr_imp = 0;
 198        mmc->dsr = 0xffffffff;
 199        /* Setup the universal parts of the block interface just once */
 200        bdesc = mmc_get_blk_desc(mmc);
 201        bdesc->if_type = IF_TYPE_MMC;
 202        bdesc->removable = 1;
 203        bdesc->devnum = mmc_get_next_devnum();
 204        bdesc->block_read = mmc_bread;
 205        bdesc->block_write = mmc_bwrite;
 206        bdesc->block_erase = mmc_berase;
 207
 208        /* setup initial part type */
 209        bdesc->part_type = mmc->cfg->part_type;
 210        mmc_list_add(mmc);
 211
 212        return mmc;
 213}
 214
 215void mmc_destroy(struct mmc *mmc)
 216{
 217        /* only freeing memory for now */
 218        free(mmc);
 219}
 220#endif
 221
 222static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart)
 223{
 224        struct mmc *mmc = find_mmc_device(desc->devnum);
 225        int ret;
 226
 227        if (!mmc)
 228                return -ENODEV;
 229
 230        if (mmc->block_dev.hwpart == hwpart)
 231                return 0;
 232
 233        if (mmc->part_config == MMCPART_NOAVAILABLE)
 234                return -EMEDIUMTYPE;
 235
 236        ret = mmc_switch_part(mmc, hwpart);
 237        if (ret)
 238                return ret;
 239
 240        return 0;
 241}
 242
 243static int mmc_get_dev(int dev, struct blk_desc **descp)
 244{
 245        struct mmc *mmc = find_mmc_device(dev);
 246        int ret;
 247
 248        if (!mmc)
 249                return -ENODEV;
 250        ret = mmc_init(mmc);
 251        if (ret)
 252                return ret;
 253
 254        *descp = &mmc->block_dev;
 255
 256        return 0;
 257}
 258
 259U_BOOT_LEGACY_BLK(mmc) = {
 260        .if_typename    = "mmc",
 261        .if_type        = IF_TYPE_MMC,
 262        .max_devs       = -1,
 263        .get_dev        = mmc_get_dev,
 264        .select_hwpart  = mmc_select_hwpartp,
 265};
 266