uboot/drivers/mmc/rockchip_sdhci.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2016 Fuzhou Rockchip Electronics Co., Ltd
   4 *
   5 * Rockchip SD Host Controller Interface
   6 */
   7
   8#include <common.h>
   9#include <dm.h>
  10#include <dt-structs.h>
  11#include <linux/err.h>
  12#include <linux/libfdt.h>
  13#include <malloc.h>
  14#include <mapmem.h>
  15#include <sdhci.h>
  16#include <clk.h>
  17
  18/* 400KHz is max freq for card ID etc. Use that as min */
  19#define EMMC_MIN_FREQ   400000
  20
  21struct rockchip_sdhc_plat {
  22#if CONFIG_IS_ENABLED(OF_PLATDATA)
  23        struct dtd_rockchip_rk3399_sdhci_5_1 dtplat;
  24#endif
  25        struct mmc_config cfg;
  26        struct mmc mmc;
  27};
  28
  29struct rockchip_sdhc {
  30        struct sdhci_host host;
  31        void *base;
  32};
  33
  34static int arasan_sdhci_probe(struct udevice *dev)
  35{
  36        struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
  37        struct rockchip_sdhc_plat *plat = dev_get_platdata(dev);
  38        struct rockchip_sdhc *prv = dev_get_priv(dev);
  39        struct sdhci_host *host = &prv->host;
  40        int max_frequency, ret;
  41        struct clk clk;
  42
  43#if CONFIG_IS_ENABLED(OF_PLATDATA)
  44        struct dtd_rockchip_rk3399_sdhci_5_1 *dtplat = &plat->dtplat;
  45
  46        host->name = dev->name;
  47        host->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]);
  48        max_frequency = dtplat->max_frequency;
  49        ret = clk_get_by_driver_info(dev, dtplat->clocks, &clk);
  50#else
  51        max_frequency = dev_read_u32_default(dev, "max-frequency", 0);
  52        ret = clk_get_by_index(dev, 0, &clk);
  53#endif
  54        if (!ret) {
  55                ret = clk_set_rate(&clk, max_frequency);
  56                if (IS_ERR_VALUE(ret))
  57                        printf("%s clk set rate fail!\n", __func__);
  58        } else {
  59                printf("%s fail to get clk\n", __func__);
  60        }
  61
  62        host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD;
  63        host->max_clk = max_frequency;
  64        /*
  65         * The sdhci-driver only supports 4bit and 8bit, as sdhci_setup_cfg
  66         * doesn't allow us to clear MMC_MODE_4BIT.  Consequently, we don't
  67         * check for other bus-width values.
  68         */
  69        if (host->bus_width == 8)
  70                host->host_caps |= MMC_MODE_8BIT;
  71
  72        host->mmc = &plat->mmc;
  73        host->mmc->priv = &prv->host;
  74        host->mmc->dev = dev;
  75        upriv->mmc = host->mmc;
  76
  77        ret = sdhci_setup_cfg(&plat->cfg, host, 0, EMMC_MIN_FREQ);
  78        if (ret)
  79                return ret;
  80
  81        return sdhci_probe(dev);
  82}
  83
  84static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
  85{
  86#if !CONFIG_IS_ENABLED(OF_PLATDATA)
  87        struct sdhci_host *host = dev_get_priv(dev);
  88
  89        host->name = dev->name;
  90        host->ioaddr = dev_read_addr_ptr(dev);
  91        host->bus_width = dev_read_u32_default(dev, "bus-width", 4);
  92#endif
  93
  94        return 0;
  95}
  96
  97static int rockchip_sdhci_bind(struct udevice *dev)
  98{
  99        struct rockchip_sdhc_plat *plat = dev_get_platdata(dev);
 100
 101        return sdhci_bind(dev, &plat->mmc, &plat->cfg);
 102}
 103
 104static const struct udevice_id arasan_sdhci_ids[] = {
 105        { .compatible = "arasan,sdhci-5.1" },
 106        { }
 107};
 108
 109U_BOOT_DRIVER(arasan_sdhci_drv) = {
 110        .name           = "rockchip_rk3399_sdhci_5_1",
 111        .id             = UCLASS_MMC,
 112        .of_match       = arasan_sdhci_ids,
 113        .ofdata_to_platdata = arasan_sdhci_ofdata_to_platdata,
 114        .ops            = &sdhci_ops,
 115        .bind           = rockchip_sdhci_bind,
 116        .probe          = arasan_sdhci_probe,
 117        .priv_auto_alloc_size = sizeof(struct rockchip_sdhc),
 118        .platdata_auto_alloc_size = sizeof(struct rockchip_sdhc_plat),
 119};
 120