linux/drivers/mmc/host/sdhci-st.c
<<
>>
Prefs
   1/*
   2 * Support for SDHCI on STMicroelectronics SoCs
   3 *
   4 * Copyright (C) 2014 STMicroelectronics Ltd
   5 * Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
   6 * Contributors: Peter Griffin <peter.griffin@linaro.org>
   7 *
   8 * Based on sdhci-cns3xxx.c
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2 as
  12 * published by the Free Software Foundation.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 *
  19 */
  20
  21#include <linux/io.h>
  22#include <linux/of.h>
  23#include <linux/module.h>
  24#include <linux/err.h>
  25#include <linux/mmc/host.h>
  26#include <linux/reset.h>
  27#include "sdhci-pltfm.h"
  28
  29struct st_mmc_platform_data {
  30        struct  reset_control *rstc;
  31        struct  clk *icnclk;
  32        void __iomem *top_ioaddr;
  33};
  34
  35/* MMCSS glue logic to setup the HC on some ST SoCs (e.g. STiH407 family) */
  36
  37#define ST_MMC_CCONFIG_REG_1            0x400
  38#define ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT BIT(24)
  39#define ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ BIT(12)
  40#define ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT     BIT(8)
  41#define ST_MMC_CCONFIG_ASYNC_WAKEUP     BIT(0)
  42#define ST_MMC_CCONFIG_1_DEFAULT        \
  43                                ((ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT) | \
  44                                 (ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ) | \
  45                                 (ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT))
  46
  47#define ST_MMC_CCONFIG_REG_2            0x404
  48#define ST_MMC_CCONFIG_HIGH_SPEED       BIT(28)
  49#define ST_MMC_CCONFIG_ADMA2            BIT(24)
  50#define ST_MMC_CCONFIG_8BIT             BIT(20)
  51#define ST_MMC_CCONFIG_MAX_BLK_LEN      16
  52#define  MAX_BLK_LEN_1024               1
  53#define  MAX_BLK_LEN_2048               2
  54#define BASE_CLK_FREQ_200               0xc8
  55#define BASE_CLK_FREQ_100               0x64
  56#define BASE_CLK_FREQ_50                0x32
  57#define ST_MMC_CCONFIG_2_DEFAULT \
  58        (ST_MMC_CCONFIG_HIGH_SPEED | ST_MMC_CCONFIG_ADMA2 | \
  59         ST_MMC_CCONFIG_8BIT | \
  60         (MAX_BLK_LEN_1024 << ST_MMC_CCONFIG_MAX_BLK_LEN))
  61
  62#define ST_MMC_CCONFIG_REG_3                    0x408
  63#define ST_MMC_CCONFIG_EMMC_SLOT_TYPE           BIT(28)
  64#define ST_MMC_CCONFIG_64BIT                    BIT(24)
  65#define ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT      BIT(20)
  66#define ST_MMC_CCONFIG_1P8_VOLT                 BIT(16)
  67#define ST_MMC_CCONFIG_3P0_VOLT                 BIT(12)
  68#define ST_MMC_CCONFIG_3P3_VOLT                 BIT(8)
  69#define ST_MMC_CCONFIG_SUSP_RES_SUPPORT         BIT(4)
  70#define ST_MMC_CCONFIG_SDMA                     BIT(0)
  71#define ST_MMC_CCONFIG_3_DEFAULT        \
  72                         (ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT    | \
  73                          ST_MMC_CCONFIG_3P3_VOLT               | \
  74                          ST_MMC_CCONFIG_SUSP_RES_SUPPORT       | \
  75                          ST_MMC_CCONFIG_SDMA)
  76
  77#define ST_MMC_CCONFIG_REG_4    0x40c
  78#define ST_MMC_CCONFIG_D_DRIVER BIT(20)
  79#define ST_MMC_CCONFIG_C_DRIVER BIT(16)
  80#define ST_MMC_CCONFIG_A_DRIVER BIT(12)
  81#define ST_MMC_CCONFIG_DDR50    BIT(8)
  82#define ST_MMC_CCONFIG_SDR104   BIT(4)
  83#define ST_MMC_CCONFIG_SDR50    BIT(0)
  84#define ST_MMC_CCONFIG_4_DEFAULT        0
  85
  86#define ST_MMC_CCONFIG_REG_5            0x410
  87#define ST_MMC_CCONFIG_TUNING_FOR_SDR50 BIT(8)
  88#define RETUNING_TIMER_CNT_MAX          0xf
  89#define ST_MMC_CCONFIG_5_DEFAULT        0
  90
  91/* I/O configuration for Arasan IP */
  92#define ST_MMC_GP_OUTPUT        0x450
  93#define ST_MMC_GP_OUTPUT_CD     BIT(12)
  94
  95#define ST_MMC_STATUS_R         0x460
  96
  97#define ST_TOP_MMC_DLY_FIX_OFF(x)       (x - 0x8)
  98
  99/* TOP config registers to manage static and dynamic delay */
 100#define ST_TOP_MMC_TX_CLK_DLY                   ST_TOP_MMC_DLY_FIX_OFF(0x8)
 101#define ST_TOP_MMC_RX_CLK_DLY                   ST_TOP_MMC_DLY_FIX_OFF(0xc)
 102/* MMC delay control register */
 103#define ST_TOP_MMC_DLY_CTRL                     ST_TOP_MMC_DLY_FIX_OFF(0x18)
 104#define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_CMD      BIT(0)
 105#define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_PH_SEL   BIT(1)
 106#define ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE       BIT(8)
 107#define ST_TOP_MMC_DLY_CTRL_RX_DLL_ENABLE       BIT(9)
 108#define ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY   BIT(10)
 109#define ST_TOP_MMC_START_DLL_LOCK               BIT(11)
 110
 111/* register to provide the phase-shift value for DLL */
 112#define ST_TOP_MMC_TX_DLL_STEP_DLY              ST_TOP_MMC_DLY_FIX_OFF(0x1c)
 113#define ST_TOP_MMC_RX_DLL_STEP_DLY              ST_TOP_MMC_DLY_FIX_OFF(0x20)
 114#define ST_TOP_MMC_RX_CMD_STEP_DLY              ST_TOP_MMC_DLY_FIX_OFF(0x24)
 115
 116/* phase shift delay on the tx clk 2.188ns */
 117#define ST_TOP_MMC_TX_DLL_STEP_DLY_VALID        0x6
 118
 119#define ST_TOP_MMC_DLY_MAX                      0xf
 120
 121#define ST_TOP_MMC_DYN_DLY_CONF \
 122                (ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE | \
 123                 ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY | \
 124                 ST_TOP_MMC_START_DLL_LOCK)
 125
 126/*
 127 * For clock speeds greater than 90MHz, we need to check that the
 128 * DLL procedure has finished before switching to ultra-speed modes.
 129 */
 130#define CLK_TO_CHECK_DLL_LOCK   90000000
 131
 132static inline void st_mmcss_set_static_delay(void __iomem *ioaddr)
 133{
 134        if (!ioaddr)
 135                return;
 136
 137        writel_relaxed(0x0, ioaddr + ST_TOP_MMC_DLY_CTRL);
 138        writel_relaxed(ST_TOP_MMC_DLY_MAX,
 139                        ioaddr + ST_TOP_MMC_TX_CLK_DLY);
 140}
 141
 142/**
 143 * st_mmcss_cconfig: configure the Arasan HC inside the flashSS.
 144 * @np: dt device node.
 145 * @host: sdhci host
 146 * Description: this function is to configure the Arasan host controller.
 147 * On some ST SoCs, i.e. STiH407 family, the MMC devices inside a dedicated
 148 * flashSS sub-system which needs to be configured to be compliant to eMMC 4.5
 149 * or eMMC4.3.  This has to be done before registering the sdhci host.
 150 */
 151static void st_mmcss_cconfig(struct device_node *np, struct sdhci_host *host)
 152{
 153        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 154        struct mmc_host *mhost = host->mmc;
 155        u32 cconf2, cconf3, cconf4, cconf5;
 156
 157        if (!of_device_is_compatible(np, "st,sdhci-stih407"))
 158                return;
 159
 160        cconf2 = ST_MMC_CCONFIG_2_DEFAULT;
 161        cconf3 = ST_MMC_CCONFIG_3_DEFAULT;
 162        cconf4 = ST_MMC_CCONFIG_4_DEFAULT;
 163        cconf5 = ST_MMC_CCONFIG_5_DEFAULT;
 164
 165        writel_relaxed(ST_MMC_CCONFIG_1_DEFAULT,
 166                        host->ioaddr + ST_MMC_CCONFIG_REG_1);
 167
 168        /* Set clock frequency, default to 50MHz if max-frequency is not
 169         * provided */
 170
 171        switch (mhost->f_max) {
 172        case 200000000:
 173                clk_set_rate(pltfm_host->clk, mhost->f_max);
 174                cconf2 |= BASE_CLK_FREQ_200;
 175                break;
 176        case 100000000:
 177                clk_set_rate(pltfm_host->clk, mhost->f_max);
 178                cconf2 |= BASE_CLK_FREQ_100;
 179                break;
 180        default:
 181                clk_set_rate(pltfm_host->clk, 50000000);
 182                cconf2 |= BASE_CLK_FREQ_50;
 183        }
 184
 185        writel_relaxed(cconf2, host->ioaddr + ST_MMC_CCONFIG_REG_2);
 186
 187        if (!mmc_card_is_removable(mhost))
 188                cconf3 |= ST_MMC_CCONFIG_EMMC_SLOT_TYPE;
 189        else
 190                /* CARD _D ET_CTRL */
 191                writel_relaxed(ST_MMC_GP_OUTPUT_CD,
 192                                host->ioaddr + ST_MMC_GP_OUTPUT);
 193
 194        if (mhost->caps & MMC_CAP_UHS_SDR50) {
 195                /* use 1.8V */
 196                cconf3 |= ST_MMC_CCONFIG_1P8_VOLT;
 197                cconf4 |= ST_MMC_CCONFIG_SDR50;
 198                /* Use tuning */
 199                cconf5 |= ST_MMC_CCONFIG_TUNING_FOR_SDR50;
 200                /* Max timeout for retuning */
 201                cconf5 |= RETUNING_TIMER_CNT_MAX;
 202        }
 203
 204        if (mhost->caps & MMC_CAP_UHS_SDR104) {
 205                /*
 206                 * SDR104 implies the HC can support HS200 mode, so
 207                 * it's mandatory to use 1.8V
 208                 */
 209                cconf3 |= ST_MMC_CCONFIG_1P8_VOLT;
 210                cconf4 |= ST_MMC_CCONFIG_SDR104;
 211                /* Max timeout for retuning */
 212                cconf5 |= RETUNING_TIMER_CNT_MAX;
 213        }
 214
 215        if (mhost->caps & MMC_CAP_UHS_DDR50)
 216                cconf4 |= ST_MMC_CCONFIG_DDR50;
 217
 218        writel_relaxed(cconf3, host->ioaddr + ST_MMC_CCONFIG_REG_3);
 219        writel_relaxed(cconf4, host->ioaddr + ST_MMC_CCONFIG_REG_4);
 220        writel_relaxed(cconf5, host->ioaddr + ST_MMC_CCONFIG_REG_5);
 221}
 222
 223static inline void st_mmcss_set_dll(void __iomem *ioaddr)
 224{
 225        if (!ioaddr)
 226                return;
 227
 228        writel_relaxed(ST_TOP_MMC_DYN_DLY_CONF, ioaddr + ST_TOP_MMC_DLY_CTRL);
 229        writel_relaxed(ST_TOP_MMC_TX_DLL_STEP_DLY_VALID,
 230                        ioaddr + ST_TOP_MMC_TX_DLL_STEP_DLY);
 231}
 232
 233static int st_mmcss_lock_dll(void __iomem *ioaddr)
 234{
 235        unsigned long curr, value;
 236        unsigned long finish = jiffies + HZ;
 237
 238        /* Checks if the DLL procedure is finished */
 239        do {
 240                curr = jiffies;
 241                value = readl(ioaddr + ST_MMC_STATUS_R);
 242                if (value & 0x1)
 243                        return 0;
 244
 245                cpu_relax();
 246        } while (!time_after_eq(curr, finish));
 247
 248        return -EBUSY;
 249}
 250
 251static int sdhci_st_set_dll_for_clock(struct sdhci_host *host)
 252{
 253        int ret = 0;
 254        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 255        struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);
 256
 257        if (host->clock > CLK_TO_CHECK_DLL_LOCK) {
 258                st_mmcss_set_dll(pdata->top_ioaddr);
 259                ret = st_mmcss_lock_dll(host->ioaddr);
 260        }
 261
 262        return ret;
 263}
 264
 265static void sdhci_st_set_uhs_signaling(struct sdhci_host *host,
 266                                        unsigned int uhs)
 267{
 268        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 269        struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);
 270        u16 ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
 271        int ret = 0;
 272
 273        /* Select Bus Speed Mode for host */
 274        ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
 275        switch (uhs) {
 276        /*
 277         * Set V18_EN -- UHS modes do not work without this.
 278         * does not change signaling voltage
 279         */
 280
 281        case MMC_TIMING_UHS_SDR12:
 282                st_mmcss_set_static_delay(pdata->top_ioaddr);
 283                ctrl_2 |= SDHCI_CTRL_UHS_SDR12 | SDHCI_CTRL_VDD_180;
 284                break;
 285        case MMC_TIMING_UHS_SDR25:
 286                st_mmcss_set_static_delay(pdata->top_ioaddr);
 287                ctrl_2 |= SDHCI_CTRL_UHS_SDR25 | SDHCI_CTRL_VDD_180;
 288                break;
 289        case MMC_TIMING_UHS_SDR50:
 290                st_mmcss_set_static_delay(pdata->top_ioaddr);
 291                ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180;
 292                ret = sdhci_st_set_dll_for_clock(host);
 293                break;
 294        case MMC_TIMING_UHS_SDR104:
 295        case MMC_TIMING_MMC_HS200:
 296                st_mmcss_set_static_delay(pdata->top_ioaddr);
 297                ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180;
 298                ret =  sdhci_st_set_dll_for_clock(host);
 299                break;
 300        case MMC_TIMING_UHS_DDR50:
 301        case MMC_TIMING_MMC_DDR52:
 302                st_mmcss_set_static_delay(pdata->top_ioaddr);
 303                ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180;
 304                break;
 305        }
 306
 307        if (ret)
 308                dev_warn(mmc_dev(host->mmc), "Error setting dll for clock "
 309                                                "(uhs %d)\n", uhs);
 310
 311        dev_dbg(mmc_dev(host->mmc), "uhs %d, ctrl_2 %04X\n", uhs, ctrl_2);
 312
 313        sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
 314}
 315
 316static u32 sdhci_st_readl(struct sdhci_host *host, int reg)
 317{
 318        u32 ret;
 319
 320        switch (reg) {
 321        case SDHCI_CAPABILITIES:
 322                ret = readl_relaxed(host->ioaddr + reg);
 323                /* Support 3.3V and 1.8V */
 324                ret &= ~SDHCI_CAN_VDD_300;
 325                break;
 326        default:
 327                ret = readl_relaxed(host->ioaddr + reg);
 328        }
 329        return ret;
 330}
 331
 332static const struct sdhci_ops sdhci_st_ops = {
 333        .get_max_clock = sdhci_pltfm_clk_get_max_clock,
 334        .set_clock = sdhci_set_clock,
 335        .set_bus_width = sdhci_set_bus_width,
 336        .read_l = sdhci_st_readl,
 337        .reset = sdhci_reset,
 338        .set_uhs_signaling = sdhci_st_set_uhs_signaling,
 339};
 340
 341static const struct sdhci_pltfm_data sdhci_st_pdata = {
 342        .ops = &sdhci_st_ops,
 343        .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
 344                SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
 345                SDHCI_QUIRK_NO_HISPD_BIT,
 346        .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
 347                SDHCI_QUIRK2_STOP_WITH_TC,
 348};
 349
 350
 351static int sdhci_st_probe(struct platform_device *pdev)
 352{
 353        struct device_node *np = pdev->dev.of_node;
 354        struct sdhci_host *host;
 355        struct st_mmc_platform_data *pdata;
 356        struct sdhci_pltfm_host *pltfm_host;
 357        struct clk *clk, *icnclk;
 358        int ret = 0;
 359        u16 host_version;
 360        struct resource *res;
 361        struct reset_control *rstc;
 362
 363        clk =  devm_clk_get(&pdev->dev, "mmc");
 364        if (IS_ERR(clk)) {
 365                dev_err(&pdev->dev, "Peripheral clk not found\n");
 366                return PTR_ERR(clk);
 367        }
 368
 369        /* ICN clock isn't compulsory, but use it if it's provided. */
 370        icnclk = devm_clk_get(&pdev->dev, "icn");
 371        if (IS_ERR(icnclk))
 372                icnclk = NULL;
 373
 374        rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
 375        if (IS_ERR(rstc))
 376                rstc = NULL;
 377        else
 378                reset_control_deassert(rstc);
 379
 380        host = sdhci_pltfm_init(pdev, &sdhci_st_pdata, sizeof(*pdata));
 381        if (IS_ERR(host)) {
 382                dev_err(&pdev->dev, "Failed sdhci_pltfm_init\n");
 383                ret = PTR_ERR(host);
 384                goto err_pltfm_init;
 385        }
 386
 387        pltfm_host = sdhci_priv(host);
 388        pdata = sdhci_pltfm_priv(pltfm_host);
 389        pdata->rstc = rstc;
 390
 391        ret = mmc_of_parse(host->mmc);
 392        if (ret) {
 393                dev_err(&pdev->dev, "Failed mmc_of_parse\n");
 394                goto err_of;
 395        }
 396
 397        ret = clk_prepare_enable(clk);
 398        if (ret) {
 399                dev_err(&pdev->dev, "Failed to prepare clock\n");
 400                goto err_of;
 401        }
 402
 403        ret = clk_prepare_enable(icnclk);
 404        if (ret) {
 405                dev_err(&pdev->dev, "Failed to prepare icn clock\n");
 406                goto err_icnclk;
 407        }
 408
 409        /* Configure the FlashSS Top registers for setting eMMC TX/RX delay */
 410        res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 411                                           "top-mmc-delay");
 412        pdata->top_ioaddr = devm_ioremap_resource(&pdev->dev, res);
 413        if (IS_ERR(pdata->top_ioaddr)) {
 414                dev_warn(&pdev->dev, "FlashSS Top Dly registers not available");
 415                pdata->top_ioaddr = NULL;
 416        }
 417
 418        pltfm_host->clk = clk;
 419        pdata->icnclk = icnclk;
 420
 421        /* Configure the Arasan HC inside the flashSS */
 422        st_mmcss_cconfig(np, host);
 423
 424        ret = sdhci_add_host(host);
 425        if (ret) {
 426                dev_err(&pdev->dev, "Failed sdhci_add_host\n");
 427                goto err_out;
 428        }
 429
 430        host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
 431
 432        dev_info(&pdev->dev, "SDHCI ST Initialised: Host Version: 0x%x Vendor Version 0x%x\n",
 433                ((host_version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT),
 434                ((host_version & SDHCI_VENDOR_VER_MASK) >>
 435                SDHCI_VENDOR_VER_SHIFT));
 436
 437        return 0;
 438
 439err_out:
 440        clk_disable_unprepare(icnclk);
 441err_icnclk:
 442        clk_disable_unprepare(clk);
 443err_of:
 444        sdhci_pltfm_free(pdev);
 445err_pltfm_init:
 446        if (rstc)
 447                reset_control_assert(rstc);
 448
 449        return ret;
 450}
 451
 452static int sdhci_st_remove(struct platform_device *pdev)
 453{
 454        struct sdhci_host *host = platform_get_drvdata(pdev);
 455        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 456        struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);
 457        struct reset_control *rstc = pdata->rstc;
 458        int ret;
 459
 460        ret = sdhci_pltfm_unregister(pdev);
 461
 462        clk_disable_unprepare(pdata->icnclk);
 463
 464        if (rstc)
 465                reset_control_assert(rstc);
 466
 467        return ret;
 468}
 469
 470#ifdef CONFIG_PM_SLEEP
 471static int sdhci_st_suspend(struct device *dev)
 472{
 473        struct sdhci_host *host = dev_get_drvdata(dev);
 474        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 475        struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);
 476        int ret;
 477
 478        if (host->tuning_mode != SDHCI_TUNING_MODE_3)
 479                mmc_retune_needed(host->mmc);
 480
 481        ret = sdhci_suspend_host(host);
 482        if (ret)
 483                goto out;
 484
 485        if (pdata->rstc)
 486                reset_control_assert(pdata->rstc);
 487
 488        clk_disable_unprepare(pdata->icnclk);
 489        clk_disable_unprepare(pltfm_host->clk);
 490out:
 491        return ret;
 492}
 493
 494static int sdhci_st_resume(struct device *dev)
 495{
 496        struct sdhci_host *host = dev_get_drvdata(dev);
 497        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 498        struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);
 499        struct device_node *np = dev->of_node;
 500        int ret;
 501
 502        ret = clk_prepare_enable(pltfm_host->clk);
 503        if (ret)
 504                return ret;
 505
 506        ret = clk_prepare_enable(pdata->icnclk);
 507        if (ret) {
 508                clk_disable_unprepare(pltfm_host->clk);
 509                return ret;
 510        }
 511
 512        if (pdata->rstc)
 513                reset_control_deassert(pdata->rstc);
 514
 515        st_mmcss_cconfig(np, host);
 516
 517        return sdhci_resume_host(host);
 518}
 519#endif
 520
 521static SIMPLE_DEV_PM_OPS(sdhci_st_pmops, sdhci_st_suspend, sdhci_st_resume);
 522
 523static const struct of_device_id st_sdhci_match[] = {
 524        { .compatible = "st,sdhci" },
 525        {},
 526};
 527
 528MODULE_DEVICE_TABLE(of, st_sdhci_match);
 529
 530static struct platform_driver sdhci_st_driver = {
 531        .probe = sdhci_st_probe,
 532        .remove = sdhci_st_remove,
 533        .driver = {
 534                   .name = "sdhci-st",
 535                   .pm = &sdhci_st_pmops,
 536                   .of_match_table = of_match_ptr(st_sdhci_match),
 537                  },
 538};
 539
 540module_platform_driver(sdhci_st_driver);
 541
 542MODULE_DESCRIPTION("SDHCI driver for STMicroelectronics SoCs");
 543MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
 544MODULE_LICENSE("GPL v2");
 545MODULE_ALIAS("platform:sdhci-st");
 546