linux/drivers/mmc/host/sdhci-dove.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * sdhci-dove.c Support for SDHCI on Marvell's Dove SoC
   4 *
   5 * Author: Saeed Bishara <saeed@marvell.com>
   6 *         Mike Rapoport <mike@compulab.co.il>
   7 * Based on sdhci-cns3xxx.c
   8 */
   9
  10#include <linux/clk.h>
  11#include <linux/err.h>
  12#include <linux/io.h>
  13#include <linux/mmc/host.h>
  14#include <linux/module.h>
  15#include <linux/of.h>
  16
  17#include "sdhci-pltfm.h"
  18
  19static u16 sdhci_dove_readw(struct sdhci_host *host, int reg)
  20{
  21        u16 ret;
  22
  23        switch (reg) {
  24        case SDHCI_HOST_VERSION:
  25        case SDHCI_SLOT_INT_STATUS:
  26                /* those registers don't exist */
  27                return 0;
  28        default:
  29                ret = readw(host->ioaddr + reg);
  30        }
  31        return ret;
  32}
  33
  34static u32 sdhci_dove_readl(struct sdhci_host *host, int reg)
  35{
  36        u32 ret;
  37
  38        ret = readl(host->ioaddr + reg);
  39
  40        switch (reg) {
  41        case SDHCI_CAPABILITIES:
  42                /* Mask the support for 3.0V */
  43                ret &= ~SDHCI_CAN_VDD_300;
  44                break;
  45        }
  46        return ret;
  47}
  48
  49static const struct sdhci_ops sdhci_dove_ops = {
  50        .read_w = sdhci_dove_readw,
  51        .read_l = sdhci_dove_readl,
  52        .set_clock = sdhci_set_clock,
  53        .set_bus_width = sdhci_set_bus_width,
  54        .reset = sdhci_reset,
  55        .set_uhs_signaling = sdhci_set_uhs_signaling,
  56};
  57
  58static const struct sdhci_pltfm_data sdhci_dove_pdata = {
  59        .ops    = &sdhci_dove_ops,
  60        .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
  61                  SDHCI_QUIRK_NO_BUSY_IRQ |
  62                  SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
  63                  SDHCI_QUIRK_FORCE_DMA |
  64                  SDHCI_QUIRK_NO_HISPD_BIT,
  65};
  66
  67static int sdhci_dove_probe(struct platform_device *pdev)
  68{
  69        struct sdhci_host *host;
  70        struct sdhci_pltfm_host *pltfm_host;
  71        int ret;
  72
  73        host = sdhci_pltfm_init(pdev, &sdhci_dove_pdata, 0);
  74        if (IS_ERR(host))
  75                return PTR_ERR(host);
  76
  77        pltfm_host = sdhci_priv(host);
  78        pltfm_host->clk = devm_clk_get(&pdev->dev, NULL);
  79
  80        if (!IS_ERR(pltfm_host->clk))
  81                clk_prepare_enable(pltfm_host->clk);
  82
  83        ret = mmc_of_parse(host->mmc);
  84        if (ret)
  85                goto err_sdhci_add;
  86
  87        ret = sdhci_add_host(host);
  88        if (ret)
  89                goto err_sdhci_add;
  90
  91        return 0;
  92
  93err_sdhci_add:
  94        clk_disable_unprepare(pltfm_host->clk);
  95        sdhci_pltfm_free(pdev);
  96        return ret;
  97}
  98
  99static const struct of_device_id sdhci_dove_of_match_table[] = {
 100        { .compatible = "marvell,dove-sdhci", },
 101        {}
 102};
 103MODULE_DEVICE_TABLE(of, sdhci_dove_of_match_table);
 104
 105static struct platform_driver sdhci_dove_driver = {
 106        .driver         = {
 107                .name   = "sdhci-dove",
 108                .pm     = &sdhci_pltfm_pmops,
 109                .of_match_table = sdhci_dove_of_match_table,
 110        },
 111        .probe          = sdhci_dove_probe,
 112        .remove         = sdhci_pltfm_unregister,
 113};
 114
 115module_platform_driver(sdhci_dove_driver);
 116
 117MODULE_DESCRIPTION("SDHCI driver for Dove");
 118MODULE_AUTHOR("Saeed Bishara <saeed@marvell.com>, "
 119              "Mike Rapoport <mike@compulab.co.il>");
 120MODULE_LICENSE("GPL v2");
 121