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