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        mmc->cfg = cfg;
 154        mmc->priv = priv;
 155
 156        return mmc;
 157}
 158
 159void mmc_destroy(struct mmc *mmc)
 160{
 161}
 162#else
 163struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
 164{
 165        struct blk_desc *bdesc;
 166        struct mmc *mmc;
 167
 168        /* quick validation */
 169        if (cfg == NULL || cfg->f_min == 0 ||
 170            cfg->f_max == 0 || cfg->b_max == 0)
 171                return NULL;
 172
 173#if !CONFIG_IS_ENABLED(DM_MMC)
 174        if (cfg->ops == NULL || cfg->ops->send_cmd == NULL)
 175                return NULL;
 176#endif
 177
 178        mmc = calloc(1, sizeof(*mmc));
 179        if (mmc == NULL)
 180                return NULL;
 181
 182        mmc->cfg = cfg;
 183        mmc->priv = priv;
 184
 185        /* the following chunk was mmc_register() */
 186
 187        /* Setup dsr related values */
 188        mmc->dsr_imp = 0;
 189        mmc->dsr = 0xffffffff;
 190        /* Setup the universal parts of the block interface just once */
 191        bdesc = mmc_get_blk_desc(mmc);
 192        bdesc->if_type = IF_TYPE_MMC;
 193        bdesc->removable = 1;
 194        bdesc->devnum = mmc_get_next_devnum();
 195        bdesc->block_read = mmc_bread;
 196        bdesc->block_write = mmc_bwrite;
 197        bdesc->block_erase = mmc_berase;
 198
 199        /* setup initial part type */
 200        bdesc->part_type = mmc->cfg->part_type;
 201        mmc_list_add(mmc);
 202
 203        return mmc;
 204}
 205
 206void mmc_destroy(struct mmc *mmc)
 207{
 208        /* only freeing memory for now */
 209        free(mmc);
 210}
 211#endif
 212
 213static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart)
 214{
 215        struct mmc *mmc = find_mmc_device(desc->devnum);
 216        int ret;
 217
 218        if (!mmc)
 219                return -ENODEV;
 220
 221        if (mmc->block_dev.hwpart == hwpart)
 222                return 0;
 223
 224        if (mmc->part_config == MMCPART_NOAVAILABLE)
 225                return -EMEDIUMTYPE;
 226
 227        ret = mmc_switch_part(mmc, hwpart);
 228        if (ret)
 229                return ret;
 230
 231        return 0;
 232}
 233
 234static int mmc_get_dev(int dev, struct blk_desc **descp)
 235{
 236        struct mmc *mmc = find_mmc_device(dev);
 237        int ret;
 238
 239        if (!mmc)
 240                return -ENODEV;
 241        ret = mmc_init(mmc);
 242        if (ret)
 243                return ret;
 244
 245        *descp = &mmc->block_dev;
 246
 247        return 0;
 248}
 249
 250U_BOOT_LEGACY_BLK(mmc) = {
 251        .if_typename    = "mmc",
 252        .if_type        = IF_TYPE_MMC,
 253        .max_devs       = -1,
 254        .get_dev        = mmc_get_dev,
 255        .select_hwpart  = mmc_select_hwpartp,
 256};
 257