uboot/drivers/mmc/mmc-uclass.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2015 Google, Inc
   4 * Copyright 2020 NXP
   5 * Written by Simon Glass <sjg@chromium.org>
   6 */
   7
   8#define LOG_CATEGORY UCLASS_MMC
   9
  10#include <common.h>
  11#include <bootdev.h>
  12#include <log.h>
  13#include <mmc.h>
  14#include <dm.h>
  15#include <dm/device-internal.h>
  16#include <dm/device_compat.h>
  17#include <dm/lists.h>
  18#include <linux/compat.h>
  19#include "mmc_private.h"
  20
  21static int dm_mmc_get_b_max(struct udevice *dev, void *dst, lbaint_t blkcnt)
  22{
  23        struct dm_mmc_ops *ops = mmc_get_ops(dev);
  24        struct mmc *mmc = mmc_get_mmc_dev(dev);
  25
  26        if (ops->get_b_max)
  27                return ops->get_b_max(dev, dst, blkcnt);
  28        else
  29                return mmc->cfg->b_max;
  30}
  31
  32int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt)
  33{
  34        return dm_mmc_get_b_max(mmc->dev, dst, blkcnt);
  35}
  36
  37static int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
  38                    struct mmc_data *data)
  39{
  40        struct mmc *mmc = mmc_get_mmc_dev(dev);
  41        struct dm_mmc_ops *ops = mmc_get_ops(dev);
  42        int ret;
  43
  44        mmmc_trace_before_send(mmc, cmd);
  45        if (ops->send_cmd)
  46                ret = ops->send_cmd(dev, cmd, data);
  47        else
  48                ret = -ENOSYS;
  49        mmmc_trace_after_send(mmc, cmd, ret);
  50
  51        return ret;
  52}
  53
  54int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
  55{
  56        return dm_mmc_send_cmd(mmc->dev, cmd, data);
  57}
  58
  59static int dm_mmc_set_ios(struct udevice *dev)
  60{
  61        struct dm_mmc_ops *ops = mmc_get_ops(dev);
  62
  63        if (!ops->set_ios)
  64                return -ENOSYS;
  65        return ops->set_ios(dev);
  66}
  67
  68int mmc_set_ios(struct mmc *mmc)
  69{
  70        return dm_mmc_set_ios(mmc->dev);
  71}
  72
  73static int dm_mmc_wait_dat0(struct udevice *dev, int state, int timeout_us)
  74{
  75        struct dm_mmc_ops *ops = mmc_get_ops(dev);
  76
  77        if (!ops->wait_dat0)
  78                return -ENOSYS;
  79        return ops->wait_dat0(dev, state, timeout_us);
  80}
  81
  82int mmc_wait_dat0(struct mmc *mmc, int state, int timeout_us)
  83{
  84        return dm_mmc_wait_dat0(mmc->dev, state, timeout_us);
  85}
  86
  87static int dm_mmc_get_wp(struct udevice *dev)
  88{
  89        struct dm_mmc_ops *ops = mmc_get_ops(dev);
  90
  91        if (!ops->get_wp)
  92                return -ENOSYS;
  93        return ops->get_wp(dev);
  94}
  95
  96int mmc_getwp(struct mmc *mmc)
  97{
  98        return dm_mmc_get_wp(mmc->dev);
  99}
 100
 101static int dm_mmc_get_cd(struct udevice *dev)
 102{
 103        struct dm_mmc_ops *ops = mmc_get_ops(dev);
 104
 105        if (!ops->get_cd)
 106                return -ENOSYS;
 107        return ops->get_cd(dev);
 108}
 109
 110int mmc_getcd(struct mmc *mmc)
 111{
 112        return dm_mmc_get_cd(mmc->dev);
 113}
 114
 115#ifdef MMC_SUPPORTS_TUNING
 116static int dm_mmc_execute_tuning(struct udevice *dev, uint opcode)
 117{
 118        struct dm_mmc_ops *ops = mmc_get_ops(dev);
 119
 120        if (!ops->execute_tuning)
 121                return -ENOSYS;
 122        return ops->execute_tuning(dev, opcode);
 123}
 124
 125int mmc_execute_tuning(struct mmc *mmc, uint opcode)
 126{
 127        return dm_mmc_execute_tuning(mmc->dev, opcode);
 128}
 129#endif
 130
 131#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
 132static int dm_mmc_set_enhanced_strobe(struct udevice *dev)
 133{
 134        struct dm_mmc_ops *ops = mmc_get_ops(dev);
 135
 136        if (ops->set_enhanced_strobe)
 137                return ops->set_enhanced_strobe(dev);
 138
 139        return -ENOTSUPP;
 140}
 141
 142int mmc_set_enhanced_strobe(struct mmc *mmc)
 143{
 144        return dm_mmc_set_enhanced_strobe(mmc->dev);
 145}
 146#endif
 147
 148static int dm_mmc_hs400_prepare_ddr(struct udevice *dev)
 149{
 150        struct dm_mmc_ops *ops = mmc_get_ops(dev);
 151
 152        if (ops->hs400_prepare_ddr)
 153                return ops->hs400_prepare_ddr(dev);
 154
 155        return 0;
 156}
 157
 158int mmc_hs400_prepare_ddr(struct mmc *mmc)
 159{
 160        return dm_mmc_hs400_prepare_ddr(mmc->dev);
 161}
 162
 163static int dm_mmc_host_power_cycle(struct udevice *dev)
 164{
 165        struct dm_mmc_ops *ops = mmc_get_ops(dev);
 166
 167        if (ops->host_power_cycle)
 168                return ops->host_power_cycle(dev);
 169        return 0;
 170}
 171
 172int mmc_host_power_cycle(struct mmc *mmc)
 173{
 174        return dm_mmc_host_power_cycle(mmc->dev);
 175}
 176
 177static int dm_mmc_deferred_probe(struct udevice *dev)
 178{
 179        struct dm_mmc_ops *ops = mmc_get_ops(dev);
 180
 181        if (ops->deferred_probe)
 182                return ops->deferred_probe(dev);
 183
 184        return 0;
 185}
 186
 187int mmc_deferred_probe(struct mmc *mmc)
 188{
 189        return dm_mmc_deferred_probe(mmc->dev);
 190}
 191
 192static int dm_mmc_reinit(struct udevice *dev)
 193{
 194        struct dm_mmc_ops *ops = mmc_get_ops(dev);
 195
 196        if (ops->reinit)
 197                return ops->reinit(dev);
 198
 199        return 0;
 200}
 201
 202int mmc_reinit(struct mmc *mmc)
 203{
 204        return dm_mmc_reinit(mmc->dev);
 205}
 206
 207int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg)
 208{
 209        int val;
 210
 211        val = dev_read_u32_default(dev, "bus-width", 1);
 212
 213        switch (val) {
 214        case 0x8:
 215                cfg->host_caps |= MMC_MODE_8BIT;
 216                /* fall through */
 217        case 0x4:
 218                cfg->host_caps |= MMC_MODE_4BIT;
 219                /* fall through */
 220        case 0x1:
 221                cfg->host_caps |= MMC_MODE_1BIT;
 222                break;
 223        default:
 224                dev_err(dev, "Invalid \"bus-width\" value %u!\n", val);
 225                return -EINVAL;
 226        }
 227
 228        /* f_max is obtained from the optional "max-frequency" property */
 229        dev_read_u32(dev, "max-frequency", &cfg->f_max);
 230
 231        if (dev_read_bool(dev, "cap-sd-highspeed"))
 232                cfg->host_caps |= MMC_CAP(SD_HS);
 233        if (dev_read_bool(dev, "cap-mmc-highspeed"))
 234                cfg->host_caps |= MMC_CAP(MMC_HS) | MMC_CAP(MMC_HS_52);
 235        if (dev_read_bool(dev, "sd-uhs-sdr12"))
 236                cfg->host_caps |= MMC_CAP(UHS_SDR12);
 237        if (dev_read_bool(dev, "sd-uhs-sdr25"))
 238                cfg->host_caps |= MMC_CAP(UHS_SDR25);
 239        if (dev_read_bool(dev, "sd-uhs-sdr50"))
 240                cfg->host_caps |= MMC_CAP(UHS_SDR50);
 241        if (dev_read_bool(dev, "sd-uhs-sdr104"))
 242                cfg->host_caps |= MMC_CAP(UHS_SDR104);
 243        if (dev_read_bool(dev, "sd-uhs-ddr50"))
 244                cfg->host_caps |= MMC_CAP(UHS_DDR50);
 245        if (dev_read_bool(dev, "mmc-ddr-1_8v"))
 246                cfg->host_caps |= MMC_CAP(MMC_DDR_52);
 247        if (dev_read_bool(dev, "mmc-ddr-1_2v"))
 248                cfg->host_caps |= MMC_CAP(MMC_DDR_52);
 249        if (dev_read_bool(dev, "mmc-hs200-1_8v"))
 250                cfg->host_caps |= MMC_CAP(MMC_HS_200);
 251        if (dev_read_bool(dev, "mmc-hs200-1_2v"))
 252                cfg->host_caps |= MMC_CAP(MMC_HS_200);
 253        if (dev_read_bool(dev, "mmc-hs400-1_8v"))
 254                cfg->host_caps |= MMC_CAP(MMC_HS_400);
 255        if (dev_read_bool(dev, "mmc-hs400-1_2v"))
 256                cfg->host_caps |= MMC_CAP(MMC_HS_400);
 257        if (dev_read_bool(dev, "mmc-hs400-enhanced-strobe"))
 258                cfg->host_caps |= MMC_CAP(MMC_HS_400_ES);
 259
 260        if (dev_read_bool(dev, "non-removable")) {
 261                cfg->host_caps |= MMC_CAP_NONREMOVABLE;
 262        } else {
 263                if (dev_read_bool(dev, "cd-inverted"))
 264                        cfg->host_caps |= MMC_CAP_CD_ACTIVE_HIGH;
 265                if (dev_read_bool(dev, "broken-cd"))
 266                        cfg->host_caps |= MMC_CAP_NEEDS_POLL;
 267        }
 268
 269        if (dev_read_bool(dev, "no-1-8-v")) {
 270                cfg->host_caps &= ~(UHS_CAPS | MMC_MODE_HS200 |
 271                                    MMC_MODE_HS400 | MMC_MODE_HS400_ES);
 272        }
 273
 274        return 0;
 275}
 276
 277struct mmc *mmc_get_mmc_dev(const struct udevice *dev)
 278{
 279        struct mmc_uclass_priv *upriv;
 280
 281        if (!device_active(dev))
 282                return NULL;
 283        upriv = dev_get_uclass_priv(dev);
 284        return upriv->mmc;
 285}
 286
 287#if CONFIG_IS_ENABLED(BLK)
 288struct mmc *find_mmc_device(int dev_num)
 289{
 290        struct udevice *dev, *mmc_dev;
 291        int ret;
 292
 293        ret = blk_find_device(IF_TYPE_MMC, dev_num, &dev);
 294
 295        if (ret) {
 296#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
 297                printf("MMC Device %d not found\n", dev_num);
 298#endif
 299                return NULL;
 300        }
 301
 302        mmc_dev = dev_get_parent(dev);
 303
 304        struct mmc *mmc = mmc_get_mmc_dev(mmc_dev);
 305
 306        return mmc;
 307}
 308
 309int get_mmc_num(void)
 310{
 311        return max((blk_find_max_devnum(IF_TYPE_MMC) + 1), 0);
 312}
 313
 314int mmc_get_next_devnum(void)
 315{
 316        return blk_find_max_devnum(IF_TYPE_MMC);
 317}
 318
 319int mmc_get_blk(struct udevice *dev, struct udevice **blkp)
 320{
 321        struct udevice *blk;
 322        int ret;
 323
 324        device_find_first_child_by_uclass(dev, UCLASS_BLK, &blk);
 325        ret = device_probe(blk);
 326        if (ret)
 327                return ret;
 328        *blkp = blk;
 329
 330        return 0;
 331}
 332
 333struct blk_desc *mmc_get_blk_desc(struct mmc *mmc)
 334{
 335        struct blk_desc *desc;
 336        struct udevice *dev;
 337
 338        device_find_first_child_by_uclass(mmc->dev, UCLASS_BLK, &dev);
 339        if (!dev)
 340                return NULL;
 341        desc = dev_get_uclass_plat(dev);
 342
 343        return desc;
 344}
 345
 346void mmc_do_preinit(void)
 347{
 348        struct udevice *dev;
 349        struct uclass *uc;
 350        int ret;
 351
 352        ret = uclass_get(UCLASS_MMC, &uc);
 353        if (ret)
 354                return;
 355        uclass_foreach_dev(dev, uc) {
 356                struct mmc *m = mmc_get_mmc_dev(dev);
 357
 358                if (!m)
 359                        continue;
 360
 361                m->user_speed_mode = MMC_MODES_END;  /* Initialising user set speed mode */
 362
 363                if (m->preinit)
 364                        mmc_start_init(m);
 365        }
 366}
 367
 368#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
 369void print_mmc_devices(char separator)
 370{
 371        struct udevice *dev;
 372        char *mmc_type;
 373        bool first = true;
 374
 375        for (uclass_first_device(UCLASS_MMC, &dev);
 376             dev;
 377             uclass_next_device(&dev), first = false) {
 378                struct mmc *m = mmc_get_mmc_dev(dev);
 379
 380                if (!first) {
 381                        printf("%c", separator);
 382                        if (separator != '\n')
 383                                puts(" ");
 384                }
 385                if (m->has_init)
 386                        mmc_type = IS_SD(m) ? "SD" : "eMMC";
 387                else
 388                        mmc_type = NULL;
 389
 390                printf("%s: %d", m->cfg->name, mmc_get_blk_desc(m)->devnum);
 391                if (mmc_type)
 392                        printf(" (%s)", mmc_type);
 393        }
 394
 395        printf("\n");
 396}
 397
 398#else
 399void print_mmc_devices(char separator) { }
 400#endif
 401
 402int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
 403{
 404        struct blk_desc *bdesc;
 405        struct udevice *bdev;
 406        int ret;
 407
 408        if (!mmc_get_ops(dev))
 409                return -ENOSYS;
 410
 411        /* Use the fixed index with aliases node's index */
 412        debug("%s: alias devnum=%d\n", __func__, dev_seq(dev));
 413
 414        ret = blk_create_devicef(dev, "mmc_blk", "blk", IF_TYPE_MMC,
 415                        dev_seq(dev), 512, 0, &bdev);
 416        if (ret) {
 417                debug("Cannot create block device\n");
 418                return ret;
 419        }
 420        bdesc = dev_get_uclass_plat(bdev);
 421        mmc->cfg = cfg;
 422        mmc->priv = dev;
 423
 424        ret = bootdev_setup_for_dev(dev, "mmc_bootdev");
 425        if (ret)
 426                return log_msg_ret("bootdev", ret);
 427
 428        /* the following chunk was from mmc_register() */
 429
 430        /* Setup dsr related values */
 431        mmc->dsr_imp = 0;
 432        mmc->dsr = 0xffffffff;
 433        /* Setup the universal parts of the block interface just once */
 434        bdesc->removable = 1;
 435
 436        /* setup initial part type */
 437        bdesc->part_type = cfg->part_type;
 438        mmc->dev = dev;
 439        mmc->user_speed_mode = MMC_MODES_END;
 440        return 0;
 441}
 442
 443int mmc_unbind(struct udevice *dev)
 444{
 445        struct udevice *bdev;
 446        int ret;
 447
 448        device_find_first_child_by_uclass(dev, UCLASS_BLK, &bdev);
 449        if (bdev) {
 450                device_remove(bdev, DM_REMOVE_NORMAL);
 451                device_unbind(bdev);
 452        }
 453        ret = bootdev_unbind_dev(dev);
 454        if (ret)
 455                return log_msg_ret("bootdev", ret);
 456
 457        return 0;
 458}
 459
 460static int mmc_select_hwpart(struct udevice *bdev, int hwpart)
 461{
 462        struct udevice *mmc_dev = dev_get_parent(bdev);
 463        struct mmc *mmc = mmc_get_mmc_dev(mmc_dev);
 464        struct blk_desc *desc = dev_get_uclass_plat(bdev);
 465        int ret;
 466
 467        if (desc->hwpart == hwpart)
 468                return 0;
 469
 470        if (mmc->part_config == MMCPART_NOAVAILABLE)
 471                return -EMEDIUMTYPE;
 472
 473        ret = mmc_switch_part(mmc, hwpart);
 474        if (!ret)
 475                blkcache_invalidate(desc->if_type, desc->devnum);
 476
 477        return ret;
 478}
 479
 480static int mmc_blk_probe(struct udevice *dev)
 481{
 482        struct udevice *mmc_dev = dev_get_parent(dev);
 483        struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc_dev);
 484        struct mmc *mmc = upriv->mmc;
 485        int ret;
 486
 487        ret = mmc_init(mmc);
 488        if (ret) {
 489                debug("%s: mmc_init() failed (err=%d)\n", __func__, ret);
 490                return ret;
 491        }
 492
 493        ret = device_probe(dev);
 494        if (ret) {
 495                debug("Probing %s failed (err=%d)\n", dev->name, ret);
 496
 497                if (CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) ||
 498                    CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) ||
 499                    CONFIG_IS_ENABLED(MMC_HS400_SUPPORT))
 500                        mmc_deinit(mmc);
 501
 502                return ret;
 503        }
 504
 505        return 0;
 506}
 507
 508#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
 509    CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
 510    CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
 511static int mmc_blk_remove(struct udevice *dev)
 512{
 513        struct udevice *mmc_dev = dev_get_parent(dev);
 514        struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc_dev);
 515        struct mmc *mmc = upriv->mmc;
 516
 517        return mmc_deinit(mmc);
 518}
 519#endif
 520
 521static const struct blk_ops mmc_blk_ops = {
 522        .read   = mmc_bread,
 523#if CONFIG_IS_ENABLED(MMC_WRITE)
 524        .write  = mmc_bwrite,
 525        .erase  = mmc_berase,
 526#endif
 527        .select_hwpart  = mmc_select_hwpart,
 528};
 529
 530U_BOOT_DRIVER(mmc_blk) = {
 531        .name           = "mmc_blk",
 532        .id             = UCLASS_BLK,
 533        .ops            = &mmc_blk_ops,
 534        .probe          = mmc_blk_probe,
 535#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
 536    CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
 537    CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
 538        .remove         = mmc_blk_remove,
 539        .flags          = DM_FLAG_OS_PREPARE,
 540#endif
 541};
 542#endif /* CONFIG_BLK */
 543
 544
 545UCLASS_DRIVER(mmc) = {
 546        .id             = UCLASS_MMC,
 547        .name           = "mmc",
 548        .flags          = DM_UC_FLAG_SEQ_ALIAS,
 549        .per_device_auto        = sizeof(struct mmc_uclass_priv),
 550};
 551