Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Support for SDHCI on STMicroelectronics SoCs
0004  *
0005  * Copyright (C) 2014 STMicroelectronics Ltd
0006  * Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
0007  * Contributors: Peter Griffin <peter.griffin@linaro.org>
0008  *
0009  * Based on sdhci-cns3xxx.c
0010  */
0011 
0012 #include <linux/io.h>
0013 #include <linux/of.h>
0014 #include <linux/module.h>
0015 #include <linux/err.h>
0016 #include <linux/mmc/host.h>
0017 #include <linux/reset.h>
0018 #include "sdhci-pltfm.h"
0019 
0020 struct st_mmc_platform_data {
0021     struct  reset_control *rstc;
0022     struct  clk *icnclk;
0023     void __iomem *top_ioaddr;
0024 };
0025 
0026 /* MMCSS glue logic to setup the HC on some ST SoCs (e.g. STiH407 family) */
0027 
0028 #define ST_MMC_CCONFIG_REG_1        0x400
0029 #define ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT BIT(24)
0030 #define ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ BIT(12)
0031 #define ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT BIT(8)
0032 #define ST_MMC_CCONFIG_ASYNC_WAKEUP BIT(0)
0033 #define ST_MMC_CCONFIG_1_DEFAULT    \
0034                 ((ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT) | \
0035                  (ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ) | \
0036                  (ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT))
0037 
0038 #define ST_MMC_CCONFIG_REG_2        0x404
0039 #define ST_MMC_CCONFIG_HIGH_SPEED   BIT(28)
0040 #define ST_MMC_CCONFIG_ADMA2        BIT(24)
0041 #define ST_MMC_CCONFIG_8BIT     BIT(20)
0042 #define ST_MMC_CCONFIG_MAX_BLK_LEN  16
0043 #define  MAX_BLK_LEN_1024       1
0044 #define  MAX_BLK_LEN_2048       2
0045 #define BASE_CLK_FREQ_200       0xc8
0046 #define BASE_CLK_FREQ_100       0x64
0047 #define BASE_CLK_FREQ_50        0x32
0048 #define ST_MMC_CCONFIG_2_DEFAULT \
0049     (ST_MMC_CCONFIG_HIGH_SPEED | ST_MMC_CCONFIG_ADMA2 | \
0050      ST_MMC_CCONFIG_8BIT | \
0051      (MAX_BLK_LEN_1024 << ST_MMC_CCONFIG_MAX_BLK_LEN))
0052 
0053 #define ST_MMC_CCONFIG_REG_3            0x408
0054 #define ST_MMC_CCONFIG_EMMC_SLOT_TYPE       BIT(28)
0055 #define ST_MMC_CCONFIG_64BIT            BIT(24)
0056 #define ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT  BIT(20)
0057 #define ST_MMC_CCONFIG_1P8_VOLT         BIT(16)
0058 #define ST_MMC_CCONFIG_3P0_VOLT         BIT(12)
0059 #define ST_MMC_CCONFIG_3P3_VOLT         BIT(8)
0060 #define ST_MMC_CCONFIG_SUSP_RES_SUPPORT     BIT(4)
0061 #define ST_MMC_CCONFIG_SDMA         BIT(0)
0062 #define ST_MMC_CCONFIG_3_DEFAULT    \
0063              (ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT    | \
0064               ST_MMC_CCONFIG_3P3_VOLT       | \
0065               ST_MMC_CCONFIG_SUSP_RES_SUPPORT   | \
0066               ST_MMC_CCONFIG_SDMA)
0067 
0068 #define ST_MMC_CCONFIG_REG_4    0x40c
0069 #define ST_MMC_CCONFIG_D_DRIVER BIT(20)
0070 #define ST_MMC_CCONFIG_C_DRIVER BIT(16)
0071 #define ST_MMC_CCONFIG_A_DRIVER BIT(12)
0072 #define ST_MMC_CCONFIG_DDR50    BIT(8)
0073 #define ST_MMC_CCONFIG_SDR104   BIT(4)
0074 #define ST_MMC_CCONFIG_SDR50    BIT(0)
0075 #define ST_MMC_CCONFIG_4_DEFAULT    0
0076 
0077 #define ST_MMC_CCONFIG_REG_5        0x410
0078 #define ST_MMC_CCONFIG_TUNING_FOR_SDR50 BIT(8)
0079 #define RETUNING_TIMER_CNT_MAX      0xf
0080 #define ST_MMC_CCONFIG_5_DEFAULT    0
0081 
0082 /* I/O configuration for Arasan IP */
0083 #define ST_MMC_GP_OUTPUT    0x450
0084 #define ST_MMC_GP_OUTPUT_CD BIT(12)
0085 
0086 #define ST_MMC_STATUS_R     0x460
0087 
0088 #define ST_TOP_MMC_DLY_FIX_OFF(x)   (x - 0x8)
0089 
0090 /* TOP config registers to manage static and dynamic delay */
0091 #define ST_TOP_MMC_TX_CLK_DLY           ST_TOP_MMC_DLY_FIX_OFF(0x8)
0092 #define ST_TOP_MMC_RX_CLK_DLY           ST_TOP_MMC_DLY_FIX_OFF(0xc)
0093 /* MMC delay control register */
0094 #define ST_TOP_MMC_DLY_CTRL         ST_TOP_MMC_DLY_FIX_OFF(0x18)
0095 #define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_CMD  BIT(0)
0096 #define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_PH_SEL   BIT(1)
0097 #define ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE   BIT(8)
0098 #define ST_TOP_MMC_DLY_CTRL_RX_DLL_ENABLE   BIT(9)
0099 #define ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY   BIT(10)
0100 #define ST_TOP_MMC_START_DLL_LOCK       BIT(11)
0101 
0102 /* register to provide the phase-shift value for DLL */
0103 #define ST_TOP_MMC_TX_DLL_STEP_DLY      ST_TOP_MMC_DLY_FIX_OFF(0x1c)
0104 #define ST_TOP_MMC_RX_DLL_STEP_DLY      ST_TOP_MMC_DLY_FIX_OFF(0x20)
0105 #define ST_TOP_MMC_RX_CMD_STEP_DLY      ST_TOP_MMC_DLY_FIX_OFF(0x24)
0106 
0107 /* phase shift delay on the tx clk 2.188ns */
0108 #define ST_TOP_MMC_TX_DLL_STEP_DLY_VALID    0x6
0109 
0110 #define ST_TOP_MMC_DLY_MAX          0xf
0111 
0112 #define ST_TOP_MMC_DYN_DLY_CONF \
0113         (ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE | \
0114          ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY | \
0115          ST_TOP_MMC_START_DLL_LOCK)
0116 
0117 /*
0118  * For clock speeds greater than 90MHz, we need to check that the
0119  * DLL procedure has finished before switching to ultra-speed modes.
0120  */
0121 #define CLK_TO_CHECK_DLL_LOCK   90000000
0122 
0123 static inline void st_mmcss_set_static_delay(void __iomem *ioaddr)
0124 {
0125     if (!ioaddr)
0126         return;
0127 
0128     writel_relaxed(0x0, ioaddr + ST_TOP_MMC_DLY_CTRL);
0129     writel_relaxed(ST_TOP_MMC_DLY_MAX,
0130             ioaddr + ST_TOP_MMC_TX_CLK_DLY);
0131 }
0132 
0133 /**
0134  * st_mmcss_cconfig: configure the Arasan HC inside the flashSS.
0135  * @np: dt device node.
0136  * @host: sdhci host
0137  * Description: this function is to configure the Arasan host controller.
0138  * On some ST SoCs, i.e. STiH407 family, the MMC devices inside a dedicated
0139  * flashSS sub-system which needs to be configured to be compliant to eMMC 4.5
0140  * or eMMC4.3.  This has to be done before registering the sdhci host.
0141  */
0142 static void st_mmcss_cconfig(struct device_node *np, struct sdhci_host *host)
0143 {
0144     struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
0145     struct mmc_host *mhost = host->mmc;
0146     u32 cconf2, cconf3, cconf4, cconf5;
0147 
0148     if (!of_device_is_compatible(np, "st,sdhci-stih407"))
0149         return;
0150 
0151     cconf2 = ST_MMC_CCONFIG_2_DEFAULT;
0152     cconf3 = ST_MMC_CCONFIG_3_DEFAULT;
0153     cconf4 = ST_MMC_CCONFIG_4_DEFAULT;
0154     cconf5 = ST_MMC_CCONFIG_5_DEFAULT;
0155 
0156     writel_relaxed(ST_MMC_CCONFIG_1_DEFAULT,
0157             host->ioaddr + ST_MMC_CCONFIG_REG_1);
0158 
0159     /* Set clock frequency, default to 50MHz if max-frequency is not
0160      * provided */
0161 
0162     switch (mhost->f_max) {
0163     case 200000000:
0164         clk_set_rate(pltfm_host->clk, mhost->f_max);
0165         cconf2 |= BASE_CLK_FREQ_200;
0166         break;
0167     case 100000000:
0168         clk_set_rate(pltfm_host->clk, mhost->f_max);
0169         cconf2 |= BASE_CLK_FREQ_100;
0170         break;
0171     default:
0172         clk_set_rate(pltfm_host->clk, 50000000);
0173         cconf2 |= BASE_CLK_FREQ_50;
0174     }
0175 
0176     writel_relaxed(cconf2, host->ioaddr + ST_MMC_CCONFIG_REG_2);
0177 
0178     if (!mmc_card_is_removable(mhost))
0179         cconf3 |= ST_MMC_CCONFIG_EMMC_SLOT_TYPE;
0180     else
0181         /* CARD _D ET_CTRL */
0182         writel_relaxed(ST_MMC_GP_OUTPUT_CD,
0183                 host->ioaddr + ST_MMC_GP_OUTPUT);
0184 
0185     if (mhost->caps & MMC_CAP_UHS_SDR50) {
0186         /* use 1.8V */
0187         cconf3 |= ST_MMC_CCONFIG_1P8_VOLT;
0188         cconf4 |= ST_MMC_CCONFIG_SDR50;
0189         /* Use tuning */
0190         cconf5 |= ST_MMC_CCONFIG_TUNING_FOR_SDR50;
0191         /* Max timeout for retuning */
0192         cconf5 |= RETUNING_TIMER_CNT_MAX;
0193     }
0194 
0195     if (mhost->caps & MMC_CAP_UHS_SDR104) {
0196         /*
0197          * SDR104 implies the HC can support HS200 mode, so
0198          * it's mandatory to use 1.8V
0199          */
0200         cconf3 |= ST_MMC_CCONFIG_1P8_VOLT;
0201         cconf4 |= ST_MMC_CCONFIG_SDR104;
0202         /* Max timeout for retuning */
0203         cconf5 |= RETUNING_TIMER_CNT_MAX;
0204     }
0205 
0206     if (mhost->caps & MMC_CAP_UHS_DDR50)
0207         cconf4 |= ST_MMC_CCONFIG_DDR50;
0208 
0209     writel_relaxed(cconf3, host->ioaddr + ST_MMC_CCONFIG_REG_3);
0210     writel_relaxed(cconf4, host->ioaddr + ST_MMC_CCONFIG_REG_4);
0211     writel_relaxed(cconf5, host->ioaddr + ST_MMC_CCONFIG_REG_5);
0212 }
0213 
0214 static inline void st_mmcss_set_dll(void __iomem *ioaddr)
0215 {
0216     if (!ioaddr)
0217         return;
0218 
0219     writel_relaxed(ST_TOP_MMC_DYN_DLY_CONF, ioaddr + ST_TOP_MMC_DLY_CTRL);
0220     writel_relaxed(ST_TOP_MMC_TX_DLL_STEP_DLY_VALID,
0221             ioaddr + ST_TOP_MMC_TX_DLL_STEP_DLY);
0222 }
0223 
0224 static int st_mmcss_lock_dll(void __iomem *ioaddr)
0225 {
0226     unsigned long curr, value;
0227     unsigned long finish = jiffies + HZ;
0228 
0229     /* Checks if the DLL procedure is finished */
0230     do {
0231         curr = jiffies;
0232         value = readl(ioaddr + ST_MMC_STATUS_R);
0233         if (value & 0x1)
0234             return 0;
0235 
0236         cpu_relax();
0237     } while (!time_after_eq(curr, finish));
0238 
0239     return -EBUSY;
0240 }
0241 
0242 static int sdhci_st_set_dll_for_clock(struct sdhci_host *host)
0243 {
0244     int ret = 0;
0245     struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
0246     struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);
0247 
0248     if (host->clock > CLK_TO_CHECK_DLL_LOCK) {
0249         st_mmcss_set_dll(pdata->top_ioaddr);
0250         ret = st_mmcss_lock_dll(host->ioaddr);
0251     }
0252 
0253     return ret;
0254 }
0255 
0256 static void sdhci_st_set_uhs_signaling(struct sdhci_host *host,
0257                     unsigned int uhs)
0258 {
0259     struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
0260     struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);
0261     u16 ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
0262     int ret = 0;
0263 
0264     /* Select Bus Speed Mode for host */
0265     ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
0266     switch (uhs) {
0267     /*
0268      * Set V18_EN -- UHS modes do not work without this.
0269      * does not change signaling voltage
0270      */
0271 
0272     case MMC_TIMING_UHS_SDR12:
0273         st_mmcss_set_static_delay(pdata->top_ioaddr);
0274         ctrl_2 |= SDHCI_CTRL_UHS_SDR12 | SDHCI_CTRL_VDD_180;
0275         break;
0276     case MMC_TIMING_UHS_SDR25:
0277         st_mmcss_set_static_delay(pdata->top_ioaddr);
0278         ctrl_2 |= SDHCI_CTRL_UHS_SDR25 | SDHCI_CTRL_VDD_180;
0279         break;
0280     case MMC_TIMING_UHS_SDR50:
0281         st_mmcss_set_static_delay(pdata->top_ioaddr);
0282         ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180;
0283         ret = sdhci_st_set_dll_for_clock(host);
0284         break;
0285     case MMC_TIMING_UHS_SDR104:
0286     case MMC_TIMING_MMC_HS200:
0287         st_mmcss_set_static_delay(pdata->top_ioaddr);
0288         ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180;
0289         ret =  sdhci_st_set_dll_for_clock(host);
0290         break;
0291     case MMC_TIMING_UHS_DDR50:
0292     case MMC_TIMING_MMC_DDR52:
0293         st_mmcss_set_static_delay(pdata->top_ioaddr);
0294         ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180;
0295         break;
0296     }
0297 
0298     if (ret)
0299         dev_warn(mmc_dev(host->mmc), "Error setting dll for clock "
0300                         "(uhs %d)\n", uhs);
0301 
0302     dev_dbg(mmc_dev(host->mmc), "uhs %d, ctrl_2 %04X\n", uhs, ctrl_2);
0303 
0304     sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
0305 }
0306 
0307 static u32 sdhci_st_readl(struct sdhci_host *host, int reg)
0308 {
0309     u32 ret;
0310 
0311     switch (reg) {
0312     case SDHCI_CAPABILITIES:
0313         ret = readl_relaxed(host->ioaddr + reg);
0314         /* Support 3.3V and 1.8V */
0315         ret &= ~SDHCI_CAN_VDD_300;
0316         break;
0317     default:
0318         ret = readl_relaxed(host->ioaddr + reg);
0319     }
0320     return ret;
0321 }
0322 
0323 static const struct sdhci_ops sdhci_st_ops = {
0324     .get_max_clock = sdhci_pltfm_clk_get_max_clock,
0325     .set_clock = sdhci_set_clock,
0326     .set_bus_width = sdhci_set_bus_width,
0327     .read_l = sdhci_st_readl,
0328     .reset = sdhci_reset,
0329     .set_uhs_signaling = sdhci_st_set_uhs_signaling,
0330 };
0331 
0332 static const struct sdhci_pltfm_data sdhci_st_pdata = {
0333     .ops = &sdhci_st_ops,
0334     .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
0335         SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
0336         SDHCI_QUIRK_NO_HISPD_BIT,
0337     .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
0338         SDHCI_QUIRK2_STOP_WITH_TC,
0339 };
0340 
0341 
0342 static int sdhci_st_probe(struct platform_device *pdev)
0343 {
0344     struct device_node *np = pdev->dev.of_node;
0345     struct sdhci_host *host;
0346     struct st_mmc_platform_data *pdata;
0347     struct sdhci_pltfm_host *pltfm_host;
0348     struct clk *clk, *icnclk;
0349     int ret = 0;
0350     u16 host_version;
0351     struct resource *res;
0352     struct reset_control *rstc;
0353 
0354     clk =  devm_clk_get(&pdev->dev, "mmc");
0355     if (IS_ERR(clk)) {
0356         dev_err(&pdev->dev, "Peripheral clk not found\n");
0357         return PTR_ERR(clk);
0358     }
0359 
0360     /* ICN clock isn't compulsory, but use it if it's provided. */
0361     icnclk = devm_clk_get(&pdev->dev, "icn");
0362     if (IS_ERR(icnclk))
0363         icnclk = NULL;
0364 
0365     rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
0366     if (IS_ERR(rstc))
0367         return PTR_ERR(rstc);
0368     reset_control_deassert(rstc);
0369 
0370     host = sdhci_pltfm_init(pdev, &sdhci_st_pdata, sizeof(*pdata));
0371     if (IS_ERR(host)) {
0372         dev_err(&pdev->dev, "Failed sdhci_pltfm_init\n");
0373         ret = PTR_ERR(host);
0374         goto err_pltfm_init;
0375     }
0376 
0377     pltfm_host = sdhci_priv(host);
0378     pdata = sdhci_pltfm_priv(pltfm_host);
0379     pdata->rstc = rstc;
0380 
0381     ret = mmc_of_parse(host->mmc);
0382     if (ret) {
0383         dev_err(&pdev->dev, "Failed mmc_of_parse\n");
0384         goto err_of;
0385     }
0386 
0387     ret = clk_prepare_enable(clk);
0388     if (ret) {
0389         dev_err(&pdev->dev, "Failed to prepare clock\n");
0390         goto err_of;
0391     }
0392 
0393     ret = clk_prepare_enable(icnclk);
0394     if (ret) {
0395         dev_err(&pdev->dev, "Failed to prepare icn clock\n");
0396         goto err_icnclk;
0397     }
0398 
0399     /* Configure the FlashSS Top registers for setting eMMC TX/RX delay */
0400     res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
0401                        "top-mmc-delay");
0402     pdata->top_ioaddr = devm_ioremap_resource(&pdev->dev, res);
0403     if (IS_ERR(pdata->top_ioaddr))
0404         pdata->top_ioaddr = NULL;
0405 
0406     pltfm_host->clk = clk;
0407     pdata->icnclk = icnclk;
0408 
0409     /* Configure the Arasan HC inside the flashSS */
0410     st_mmcss_cconfig(np, host);
0411 
0412     ret = sdhci_add_host(host);
0413     if (ret)
0414         goto err_out;
0415 
0416     host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
0417 
0418     dev_info(&pdev->dev, "SDHCI ST Initialised: Host Version: 0x%x Vendor Version 0x%x\n",
0419         ((host_version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT),
0420         ((host_version & SDHCI_VENDOR_VER_MASK) >>
0421         SDHCI_VENDOR_VER_SHIFT));
0422 
0423     return 0;
0424 
0425 err_out:
0426     clk_disable_unprepare(icnclk);
0427 err_icnclk:
0428     clk_disable_unprepare(clk);
0429 err_of:
0430     sdhci_pltfm_free(pdev);
0431 err_pltfm_init:
0432     reset_control_assert(rstc);
0433 
0434     return ret;
0435 }
0436 
0437 static int sdhci_st_remove(struct platform_device *pdev)
0438 {
0439     struct sdhci_host *host = platform_get_drvdata(pdev);
0440     struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
0441     struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);
0442     struct reset_control *rstc = pdata->rstc;
0443 
0444     sdhci_pltfm_unregister(pdev);
0445 
0446     clk_disable_unprepare(pdata->icnclk);
0447 
0448     reset_control_assert(rstc);
0449 
0450     return 0;
0451 }
0452 
0453 #ifdef CONFIG_PM_SLEEP
0454 static int sdhci_st_suspend(struct device *dev)
0455 {
0456     struct sdhci_host *host = dev_get_drvdata(dev);
0457     struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
0458     struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);
0459     int ret;
0460 
0461     if (host->tuning_mode != SDHCI_TUNING_MODE_3)
0462         mmc_retune_needed(host->mmc);
0463 
0464     ret = sdhci_suspend_host(host);
0465     if (ret)
0466         goto out;
0467 
0468     reset_control_assert(pdata->rstc);
0469 
0470     clk_disable_unprepare(pdata->icnclk);
0471     clk_disable_unprepare(pltfm_host->clk);
0472 out:
0473     return ret;
0474 }
0475 
0476 static int sdhci_st_resume(struct device *dev)
0477 {
0478     struct sdhci_host *host = dev_get_drvdata(dev);
0479     struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
0480     struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);
0481     struct device_node *np = dev->of_node;
0482     int ret;
0483 
0484     ret = clk_prepare_enable(pltfm_host->clk);
0485     if (ret)
0486         return ret;
0487 
0488     ret = clk_prepare_enable(pdata->icnclk);
0489     if (ret) {
0490         clk_disable_unprepare(pltfm_host->clk);
0491         return ret;
0492     }
0493 
0494     reset_control_deassert(pdata->rstc);
0495 
0496     st_mmcss_cconfig(np, host);
0497 
0498     return sdhci_resume_host(host);
0499 }
0500 #endif
0501 
0502 static SIMPLE_DEV_PM_OPS(sdhci_st_pmops, sdhci_st_suspend, sdhci_st_resume);
0503 
0504 static const struct of_device_id st_sdhci_match[] = {
0505     { .compatible = "st,sdhci" },
0506     {},
0507 };
0508 
0509 MODULE_DEVICE_TABLE(of, st_sdhci_match);
0510 
0511 static struct platform_driver sdhci_st_driver = {
0512     .probe = sdhci_st_probe,
0513     .remove = sdhci_st_remove,
0514     .driver = {
0515            .name = "sdhci-st",
0516            .probe_type = PROBE_PREFER_ASYNCHRONOUS,
0517            .pm = &sdhci_st_pmops,
0518            .of_match_table = st_sdhci_match,
0519           },
0520 };
0521 
0522 module_platform_driver(sdhci_st_driver);
0523 
0524 MODULE_DESCRIPTION("SDHCI driver for STMicroelectronics SoCs");
0525 MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
0526 MODULE_LICENSE("GPL v2");
0527 MODULE_ALIAS("platform:sdhci-st");