uboot/drivers/mmc/k3_arsan_sdhci.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
   4 *
   5 * Texas Instruments' K3 SD Host Controller Interface
   6 */
   7
   8#include <clk.h>
   9#include <common.h>
  10#include <dm.h>
  11#include <malloc.h>
  12#include <power-domain.h>
  13#include <sdhci.h>
  14
  15#define K3_ARASAN_SDHCI_MIN_FREQ        0
  16
  17struct k3_arasan_sdhci_plat {
  18        struct mmc_config cfg;
  19        struct mmc mmc;
  20        unsigned int f_max;
  21};
  22
  23static int k3_arasan_sdhci_probe(struct udevice *dev)
  24{
  25        struct k3_arasan_sdhci_plat *plat = dev_get_platdata(dev);
  26        struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
  27        struct sdhci_host *host = dev_get_priv(dev);
  28        struct power_domain sdhci_pwrdmn;
  29        struct clk clk;
  30        unsigned long clock;
  31        int ret;
  32
  33        ret = power_domain_get_by_index(dev, &sdhci_pwrdmn, 0);
  34        if (ret) {
  35                dev_err(dev, "failed to get power domain\n");
  36                return ret;
  37        }
  38
  39        ret = power_domain_on(&sdhci_pwrdmn);
  40        if (ret) {
  41                dev_err(dev, "Power domain on failed\n");
  42                return ret;
  43        }
  44
  45        ret = clk_get_by_index(dev, 0, &clk);
  46        if (ret) {
  47                dev_err(dev, "failed to get clock\n");
  48                return ret;
  49        }
  50
  51        clock = clk_get_rate(&clk);
  52        if (IS_ERR_VALUE(clock)) {
  53                dev_err(dev, "failed to get rate\n");
  54                return clock;
  55        }
  56
  57        host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD |
  58                       SDHCI_QUIRK_BROKEN_R1B;
  59
  60        host->max_clk = clock;
  61
  62        ret = sdhci_setup_cfg(&plat->cfg, host, plat->f_max,
  63                              K3_ARASAN_SDHCI_MIN_FREQ);
  64        host->mmc = &plat->mmc;
  65        if (ret)
  66                return ret;
  67        host->mmc->priv = host;
  68        host->mmc->dev = dev;
  69        upriv->mmc = host->mmc;
  70
  71        return sdhci_probe(dev);
  72}
  73
  74static int k3_arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
  75{
  76        struct k3_arasan_sdhci_plat *plat = dev_get_platdata(dev);
  77        struct sdhci_host *host = dev_get_priv(dev);
  78
  79        host->name = dev->name;
  80        host->ioaddr = (void *)dev_read_addr(dev);
  81        host->bus_width = dev_read_u32_default(dev, "bus-width", 4);
  82        plat->f_max = dev_read_u32_default(dev, "max-frequency", 0);
  83
  84        return 0;
  85}
  86
  87static int k3_arasan_sdhci_bind(struct udevice *dev)
  88{
  89        struct k3_arasan_sdhci_plat *plat = dev_get_platdata(dev);
  90
  91        return sdhci_bind(dev, &plat->mmc, &plat->cfg);
  92}
  93
  94static const struct udevice_id k3_arasan_sdhci_ids[] = {
  95        { .compatible = "arasan,sdhci-5.1" },
  96        { }
  97};
  98
  99U_BOOT_DRIVER(k3_arasan_sdhci_drv) = {
 100        .name           = "k3_arasan_sdhci",
 101        .id             = UCLASS_MMC,
 102        .of_match       = k3_arasan_sdhci_ids,
 103        .ofdata_to_platdata = k3_arasan_sdhci_ofdata_to_platdata,
 104        .ops            = &sdhci_ops,
 105        .bind           = k3_arasan_sdhci_bind,
 106        .probe          = k3_arasan_sdhci_probe,
 107        .priv_auto_alloc_size = sizeof(struct sdhci_host),
 108        .platdata_auto_alloc_size = sizeof(struct k3_arasan_sdhci_plat),
 109};
 110