uboot/drivers/mmc/aspeed_sdhci.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2019 IBM Corp.
   4 * Eddie James <eajames@linux.ibm.com>
   5 */
   6
   7#include <common.h>
   8#include <clk.h>
   9#include <dm.h>
  10#include <malloc.h>
  11#include <sdhci.h>
  12#include <linux/err.h>
  13#include <dm/lists.h>
  14
  15struct aspeed_sdhci_plat {
  16        struct mmc_config cfg;
  17        struct mmc mmc;
  18};
  19
  20static int aspeed_sdhci_probe(struct udevice *dev)
  21{
  22        struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
  23        struct aspeed_sdhci_plat *plat = dev_get_plat(dev);
  24        struct sdhci_host *host = dev_get_priv(dev);
  25        u32 max_clk;
  26        struct clk clk;
  27        int ret;
  28
  29        ret = clk_get_by_index(dev, 0, &clk);
  30        if (ret) {
  31                debug("%s: clock get failed %d\n", __func__, ret);
  32                return ret;
  33        }
  34
  35        ret = clk_enable(&clk);
  36        if (ret) {
  37                debug("%s: clock enable failed %d\n", __func__, ret);
  38                goto free;
  39        }
  40
  41        host->name = dev->name;
  42        host->ioaddr = dev_read_addr_ptr(dev);
  43
  44        max_clk = clk_get_rate(&clk);
  45        if (IS_ERR_VALUE(max_clk)) {
  46                ret = max_clk;
  47                debug("%s: clock rate get failed %d\n", __func__, ret);
  48                goto err;
  49        }
  50
  51        host->max_clk = max_clk;
  52        host->mmc = &plat->mmc;
  53        host->mmc->dev = dev;
  54        host->mmc->priv = host;
  55        upriv->mmc = host->mmc;
  56
  57        ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0);
  58        if (ret)
  59                goto err;
  60
  61        ret = sdhci_probe(dev);
  62        if (ret)
  63                goto err;
  64
  65        return 0;
  66
  67err:
  68        clk_disable(&clk);
  69free:
  70        clk_free(&clk);
  71        return ret;
  72}
  73
  74static int aspeed_sdhci_bind(struct udevice *dev)
  75{
  76        struct aspeed_sdhci_plat *plat = dev_get_plat(dev);
  77
  78        return sdhci_bind(dev, &plat->mmc, &plat->cfg);
  79}
  80
  81static const struct udevice_id aspeed_sdhci_ids[] = {
  82        { .compatible = "aspeed,ast2400-sdhci" },
  83        { .compatible = "aspeed,ast2500-sdhci" },
  84        { .compatible = "aspeed,ast2600-sdhci" },
  85        { }
  86};
  87
  88U_BOOT_DRIVER(aspeed_sdhci_drv) = {
  89        .name           = "aspeed_sdhci",
  90        .id             = UCLASS_MMC,
  91        .of_match       = aspeed_sdhci_ids,
  92        .ops            = &sdhci_ops,
  93        .bind           = aspeed_sdhci_bind,
  94        .probe          = aspeed_sdhci_probe,
  95        .priv_auto      = sizeof(struct sdhci_host),
  96        .plat_auto      = sizeof(struct aspeed_sdhci_plat),
  97};
  98
  99
 100static int aspeed_sdc_probe(struct udevice *parent)
 101{
 102        struct clk clk;
 103        int ret;
 104
 105        ret = clk_get_by_index(parent, 0, &clk);
 106        if (ret) {
 107                debug("%s: clock get failed %d\n", __func__, ret);
 108                return ret;
 109        }
 110
 111        ret = clk_enable(&clk);
 112        if (ret) {
 113                debug("%s: clock enable failed %d\n", __func__, ret);
 114                return ret;
 115        }
 116
 117        return 0;
 118}
 119
 120static const struct udevice_id aspeed_sdc_ids[] = {
 121        { .compatible = "aspeed,ast2400-sd-controller" },
 122        { .compatible = "aspeed,ast2500-sd-controller" },
 123        { .compatible = "aspeed,ast2600-sd-controller" },
 124        { }
 125};
 126
 127U_BOOT_DRIVER(aspeed_sdc_drv) = {
 128        .name           = "aspeed_sdc",
 129        .id             = UCLASS_MISC,
 130        .of_match       = aspeed_sdc_ids,
 131        .probe          = aspeed_sdc_probe,
 132};
 133