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