Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Driver for Marvell Xenon SDHC as a platform device
0004  *
0005  * Copyright (C) 2016 Marvell, All Rights Reserved.
0006  *
0007  * Author:  Hu Ziji <huziji@marvell.com>
0008  * Date:    2016-8-24
0009  *
0010  * Inspired by Jisheng Zhang <jszhang@marvell.com>
0011  * Special thanks to Video BG4 project team.
0012  */
0013 
0014 #include <linux/acpi.h>
0015 #include <linux/delay.h>
0016 #include <linux/ktime.h>
0017 #include <linux/module.h>
0018 #include <linux/of.h>
0019 #include <linux/pm.h>
0020 #include <linux/pm_runtime.h>
0021 
0022 #include "sdhci-pltfm.h"
0023 #include "sdhci-xenon.h"
0024 
0025 static int xenon_enable_internal_clk(struct sdhci_host *host)
0026 {
0027     u32 reg;
0028     ktime_t timeout;
0029 
0030     reg = sdhci_readl(host, SDHCI_CLOCK_CONTROL);
0031     reg |= SDHCI_CLOCK_INT_EN;
0032     sdhci_writel(host, reg, SDHCI_CLOCK_CONTROL);
0033     /* Wait max 20 ms */
0034     timeout = ktime_add_ms(ktime_get(), 20);
0035     while (1) {
0036         bool timedout = ktime_after(ktime_get(), timeout);
0037 
0038         reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
0039         if (reg & SDHCI_CLOCK_INT_STABLE)
0040             break;
0041         if (timedout) {
0042             dev_err(mmc_dev(host->mmc), "Internal clock never stabilised.\n");
0043             return -ETIMEDOUT;
0044         }
0045         usleep_range(900, 1100);
0046     }
0047 
0048     return 0;
0049 }
0050 
0051 /* Set SDCLK-off-while-idle */
0052 static void xenon_set_sdclk_off_idle(struct sdhci_host *host,
0053                      unsigned char sdhc_id, bool enable)
0054 {
0055     u32 reg;
0056     u32 mask;
0057 
0058     reg = sdhci_readl(host, XENON_SYS_OP_CTRL);
0059     /* Get the bit shift basing on the SDHC index */
0060     mask = (0x1 << (XENON_SDCLK_IDLEOFF_ENABLE_SHIFT + sdhc_id));
0061     if (enable)
0062         reg |= mask;
0063     else
0064         reg &= ~mask;
0065 
0066     sdhci_writel(host, reg, XENON_SYS_OP_CTRL);
0067 }
0068 
0069 /* Enable/Disable the Auto Clock Gating function */
0070 static void xenon_set_acg(struct sdhci_host *host, bool enable)
0071 {
0072     u32 reg;
0073 
0074     reg = sdhci_readl(host, XENON_SYS_OP_CTRL);
0075     if (enable)
0076         reg &= ~XENON_AUTO_CLKGATE_DISABLE_MASK;
0077     else
0078         reg |= XENON_AUTO_CLKGATE_DISABLE_MASK;
0079     sdhci_writel(host, reg, XENON_SYS_OP_CTRL);
0080 }
0081 
0082 /* Enable this SDHC */
0083 static void xenon_enable_sdhc(struct sdhci_host *host,
0084                   unsigned char sdhc_id)
0085 {
0086     u32 reg;
0087 
0088     reg = sdhci_readl(host, XENON_SYS_OP_CTRL);
0089     reg |= (BIT(sdhc_id) << XENON_SLOT_ENABLE_SHIFT);
0090     sdhci_writel(host, reg, XENON_SYS_OP_CTRL);
0091 
0092     host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
0093     /*
0094      * Force to clear BUS_TEST to
0095      * skip bus_test_pre and bus_test_post
0096      */
0097     host->mmc->caps &= ~MMC_CAP_BUS_WIDTH_TEST;
0098 }
0099 
0100 /* Disable this SDHC */
0101 static void xenon_disable_sdhc(struct sdhci_host *host,
0102                    unsigned char sdhc_id)
0103 {
0104     u32 reg;
0105 
0106     reg = sdhci_readl(host, XENON_SYS_OP_CTRL);
0107     reg &= ~(BIT(sdhc_id) << XENON_SLOT_ENABLE_SHIFT);
0108     sdhci_writel(host, reg, XENON_SYS_OP_CTRL);
0109 }
0110 
0111 /* Enable Parallel Transfer Mode */
0112 static void xenon_enable_sdhc_parallel_tran(struct sdhci_host *host,
0113                         unsigned char sdhc_id)
0114 {
0115     u32 reg;
0116 
0117     reg = sdhci_readl(host, XENON_SYS_EXT_OP_CTRL);
0118     reg |= BIT(sdhc_id);
0119     sdhci_writel(host, reg, XENON_SYS_EXT_OP_CTRL);
0120 }
0121 
0122 /* Mask command conflict error */
0123 static void xenon_mask_cmd_conflict_err(struct sdhci_host *host)
0124 {
0125     u32  reg;
0126 
0127     reg = sdhci_readl(host, XENON_SYS_EXT_OP_CTRL);
0128     reg |= XENON_MASK_CMD_CONFLICT_ERR;
0129     sdhci_writel(host, reg, XENON_SYS_EXT_OP_CTRL);
0130 }
0131 
0132 static void xenon_retune_setup(struct sdhci_host *host)
0133 {
0134     struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
0135     struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
0136     u32 reg;
0137 
0138     /* Disable the Re-Tuning Request functionality */
0139     reg = sdhci_readl(host, XENON_SLOT_RETUNING_REQ_CTRL);
0140     reg &= ~XENON_RETUNING_COMPATIBLE;
0141     sdhci_writel(host, reg, XENON_SLOT_RETUNING_REQ_CTRL);
0142 
0143     /* Disable the Re-tuning Interrupt */
0144     reg = sdhci_readl(host, SDHCI_SIGNAL_ENABLE);
0145     reg &= ~SDHCI_INT_RETUNE;
0146     sdhci_writel(host, reg, SDHCI_SIGNAL_ENABLE);
0147     reg = sdhci_readl(host, SDHCI_INT_ENABLE);
0148     reg &= ~SDHCI_INT_RETUNE;
0149     sdhci_writel(host, reg, SDHCI_INT_ENABLE);
0150 
0151     /* Force to use Tuning Mode 1 */
0152     host->tuning_mode = SDHCI_TUNING_MODE_1;
0153     /* Set re-tuning period */
0154     host->tuning_count = 1 << (priv->tuning_count - 1);
0155 }
0156 
0157 /*
0158  * Operations inside struct sdhci_ops
0159  */
0160 /* Recover the Register Setting cleared during SOFTWARE_RESET_ALL */
0161 static void xenon_reset_exit(struct sdhci_host *host,
0162                  unsigned char sdhc_id, u8 mask)
0163 {
0164     /* Only SOFTWARE RESET ALL will clear the register setting */
0165     if (!(mask & SDHCI_RESET_ALL))
0166         return;
0167 
0168     /* Disable tuning request and auto-retuning again */
0169     xenon_retune_setup(host);
0170 
0171     /*
0172      * The ACG should be turned off at the early init time, in order
0173      * to solve a possible issues with the 1.8V regulator stabilization.
0174      * The feature is enabled in later stage.
0175      */
0176     xenon_set_acg(host, false);
0177 
0178     xenon_set_sdclk_off_idle(host, sdhc_id, false);
0179 
0180     xenon_mask_cmd_conflict_err(host);
0181 }
0182 
0183 static void xenon_reset(struct sdhci_host *host, u8 mask)
0184 {
0185     struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
0186     struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
0187 
0188     sdhci_reset(host, mask);
0189     xenon_reset_exit(host, priv->sdhc_id, mask);
0190 }
0191 
0192 /*
0193  * Xenon defines different values for HS200 and HS400
0194  * in Host_Control_2
0195  */
0196 static void xenon_set_uhs_signaling(struct sdhci_host *host,
0197                     unsigned int timing)
0198 {
0199     u16 ctrl_2;
0200 
0201     ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
0202     /* Select Bus Speed Mode for host */
0203     ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
0204     if (timing == MMC_TIMING_MMC_HS200)
0205         ctrl_2 |= XENON_CTRL_HS200;
0206     else if (timing == MMC_TIMING_UHS_SDR104)
0207         ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
0208     else if (timing == MMC_TIMING_UHS_SDR12)
0209         ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
0210     else if (timing == MMC_TIMING_UHS_SDR25)
0211         ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
0212     else if (timing == MMC_TIMING_UHS_SDR50)
0213         ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
0214     else if ((timing == MMC_TIMING_UHS_DDR50) ||
0215          (timing == MMC_TIMING_MMC_DDR52))
0216         ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
0217     else if (timing == MMC_TIMING_MMC_HS400)
0218         ctrl_2 |= XENON_CTRL_HS400;
0219     sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
0220 }
0221 
0222 static void xenon_set_power(struct sdhci_host *host, unsigned char mode,
0223         unsigned short vdd)
0224 {
0225     struct mmc_host *mmc = host->mmc;
0226     u8 pwr = host->pwr;
0227 
0228     sdhci_set_power_noreg(host, mode, vdd);
0229 
0230     if (host->pwr == pwr)
0231         return;
0232 
0233     if (host->pwr == 0)
0234         vdd = 0;
0235 
0236     if (!IS_ERR(mmc->supply.vmmc))
0237         mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
0238 }
0239 
0240 static void xenon_voltage_switch(struct sdhci_host *host)
0241 {
0242     /* Wait for 5ms after set 1.8V signal enable bit */
0243     usleep_range(5000, 5500);
0244 }
0245 
0246 static unsigned int xenon_get_max_clock(struct sdhci_host *host)
0247 {
0248     struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
0249 
0250     if (pltfm_host->clk)
0251         return sdhci_pltfm_clk_get_max_clock(host);
0252     else
0253         return pltfm_host->clock;
0254 }
0255 
0256 static const struct sdhci_ops sdhci_xenon_ops = {
0257     .voltage_switch     = xenon_voltage_switch,
0258     .set_clock      = sdhci_set_clock,
0259     .set_power      = xenon_set_power,
0260     .set_bus_width      = sdhci_set_bus_width,
0261     .reset          = xenon_reset,
0262     .set_uhs_signaling  = xenon_set_uhs_signaling,
0263     .get_max_clock      = xenon_get_max_clock,
0264 };
0265 
0266 static const struct sdhci_pltfm_data sdhci_xenon_pdata = {
0267     .ops = &sdhci_xenon_ops,
0268     .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
0269           SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
0270           SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
0271 };
0272 
0273 /*
0274  * Xenon Specific Operations in mmc_host_ops
0275  */
0276 static void xenon_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
0277 {
0278     struct sdhci_host *host = mmc_priv(mmc);
0279     struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
0280     struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
0281     u32 reg;
0282 
0283     /*
0284      * HS400/HS200/eMMC HS doesn't have Preset Value register.
0285      * However, sdhci_set_ios will read HS400/HS200 Preset register.
0286      * Disable Preset Value register for HS400/HS200.
0287      * eMMC HS with preset_enabled set will trigger a bug in
0288      * get_preset_value().
0289      */
0290     if ((ios->timing == MMC_TIMING_MMC_HS400) ||
0291         (ios->timing == MMC_TIMING_MMC_HS200) ||
0292         (ios->timing == MMC_TIMING_MMC_HS)) {
0293         host->preset_enabled = false;
0294         host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
0295         host->flags &= ~SDHCI_PV_ENABLED;
0296 
0297         reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
0298         reg &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
0299         sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
0300     } else {
0301         host->quirks2 &= ~SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
0302     }
0303 
0304     sdhci_set_ios(mmc, ios);
0305     xenon_phy_adj(host, ios);
0306 
0307     if (host->clock > XENON_DEFAULT_SDCLK_FREQ)
0308         xenon_set_sdclk_off_idle(host, priv->sdhc_id, true);
0309 }
0310 
0311 static int xenon_start_signal_voltage_switch(struct mmc_host *mmc,
0312                          struct mmc_ios *ios)
0313 {
0314     struct sdhci_host *host = mmc_priv(mmc);
0315 
0316     /*
0317      * Before SD/SDIO set signal voltage, SD bus clock should be
0318      * disabled. However, sdhci_set_clock will also disable the Internal
0319      * clock in mmc_set_signal_voltage().
0320      * If Internal clock is disabled, the 3.3V/1.8V bit can not be updated.
0321      * Thus here manually enable internal clock.
0322      *
0323      * After switch completes, it is unnecessary to disable internal clock,
0324      * since keeping internal clock active obeys SD spec.
0325      */
0326     xenon_enable_internal_clk(host);
0327 
0328     xenon_soc_pad_ctrl(host, ios->signal_voltage);
0329 
0330     /*
0331      * If Vqmmc is fixed on platform, vqmmc regulator should be unavailable.
0332      * Thus SDHCI_CTRL_VDD_180 bit might not work then.
0333      * Skip the standard voltage switch to avoid any issue.
0334      */
0335     if (PTR_ERR(mmc->supply.vqmmc) == -ENODEV)
0336         return 0;
0337 
0338     return sdhci_start_signal_voltage_switch(mmc, ios);
0339 }
0340 
0341 /*
0342  * Update card type.
0343  * priv->init_card_type will be used in PHY timing adjustment.
0344  */
0345 static void xenon_init_card(struct mmc_host *mmc, struct mmc_card *card)
0346 {
0347     struct sdhci_host *host = mmc_priv(mmc);
0348     struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
0349     struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
0350 
0351     /* Update card type*/
0352     priv->init_card_type = card->type;
0353 }
0354 
0355 static int xenon_execute_tuning(struct mmc_host *mmc, u32 opcode)
0356 {
0357     struct sdhci_host *host = mmc_priv(mmc);
0358 
0359     if (host->timing == MMC_TIMING_UHS_DDR50 ||
0360         host->timing == MMC_TIMING_MMC_DDR52)
0361         return 0;
0362 
0363     /*
0364      * Currently force Xenon driver back to support mode 1 only,
0365      * even though Xenon might claim to support mode 2 or mode 3.
0366      * It requires more time to test mode 2/mode 3 on more platforms.
0367      */
0368     if (host->tuning_mode != SDHCI_TUNING_MODE_1)
0369         xenon_retune_setup(host);
0370 
0371     return sdhci_execute_tuning(mmc, opcode);
0372 }
0373 
0374 static void xenon_enable_sdio_irq(struct mmc_host *mmc, int enable)
0375 {
0376     struct sdhci_host *host = mmc_priv(mmc);
0377     struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
0378     struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
0379     u32 reg;
0380     u8 sdhc_id = priv->sdhc_id;
0381 
0382     sdhci_enable_sdio_irq(mmc, enable);
0383 
0384     if (enable) {
0385         /*
0386          * Set SDIO Card Inserted indication
0387          * to enable detecting SDIO async irq.
0388          */
0389         reg = sdhci_readl(host, XENON_SYS_CFG_INFO);
0390         reg |= (1 << (sdhc_id + XENON_SLOT_TYPE_SDIO_SHIFT));
0391         sdhci_writel(host, reg, XENON_SYS_CFG_INFO);
0392     } else {
0393         /* Clear SDIO Card Inserted indication */
0394         reg = sdhci_readl(host, XENON_SYS_CFG_INFO);
0395         reg &= ~(1 << (sdhc_id + XENON_SLOT_TYPE_SDIO_SHIFT));
0396         sdhci_writel(host, reg, XENON_SYS_CFG_INFO);
0397     }
0398 }
0399 
0400 static void xenon_replace_mmc_host_ops(struct sdhci_host *host)
0401 {
0402     host->mmc_host_ops.set_ios = xenon_set_ios;
0403     host->mmc_host_ops.start_signal_voltage_switch =
0404             xenon_start_signal_voltage_switch;
0405     host->mmc_host_ops.init_card = xenon_init_card;
0406     host->mmc_host_ops.execute_tuning = xenon_execute_tuning;
0407     host->mmc_host_ops.enable_sdio_irq = xenon_enable_sdio_irq;
0408 }
0409 
0410 /*
0411  * Parse Xenon specific DT properties:
0412  * sdhc-id: the index of current SDHC.
0413  *      Refer to XENON_SYS_CFG_INFO register
0414  * tun-count: the interval between re-tuning
0415  */
0416 static int xenon_probe_params(struct platform_device *pdev)
0417 {
0418     struct device *dev = &pdev->dev;
0419     struct sdhci_host *host = platform_get_drvdata(pdev);
0420     struct mmc_host *mmc = host->mmc;
0421     struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
0422     struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
0423     u32 sdhc_id, nr_sdhc;
0424     u32 tuning_count;
0425 
0426     /* Disable HS200 on Armada AP806 */
0427     if (priv->hw_version == XENON_AP806)
0428         host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200;
0429 
0430     sdhc_id = 0x0;
0431     if (!device_property_read_u32(dev, "marvell,xenon-sdhc-id", &sdhc_id)) {
0432         nr_sdhc = sdhci_readl(host, XENON_SYS_CFG_INFO);
0433         nr_sdhc &= XENON_NR_SUPPORTED_SLOT_MASK;
0434         if (unlikely(sdhc_id > nr_sdhc)) {
0435             dev_err(mmc_dev(mmc), "SDHC Index %d exceeds Number of SDHCs %d\n",
0436                 sdhc_id, nr_sdhc);
0437             return -EINVAL;
0438         }
0439     }
0440     priv->sdhc_id = sdhc_id;
0441 
0442     tuning_count = XENON_DEF_TUNING_COUNT;
0443     if (!device_property_read_u32(dev, "marvell,xenon-tun-count",
0444                       &tuning_count)) {
0445         if (unlikely(tuning_count >= XENON_TMR_RETUN_NO_PRESENT)) {
0446             dev_err(mmc_dev(mmc), "Wrong Re-tuning Count. Set default value %d\n",
0447                 XENON_DEF_TUNING_COUNT);
0448             tuning_count = XENON_DEF_TUNING_COUNT;
0449         }
0450     }
0451     priv->tuning_count = tuning_count;
0452 
0453     return xenon_phy_parse_params(dev, host);
0454 }
0455 
0456 static int xenon_sdhc_prepare(struct sdhci_host *host)
0457 {
0458     struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
0459     struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
0460     u8 sdhc_id = priv->sdhc_id;
0461 
0462     /* Enable SDHC */
0463     xenon_enable_sdhc(host, sdhc_id);
0464 
0465     /* Enable ACG */
0466     xenon_set_acg(host, true);
0467 
0468     /* Enable Parallel Transfer Mode */
0469     xenon_enable_sdhc_parallel_tran(host, sdhc_id);
0470 
0471     /* Disable SDCLK-Off-While-Idle before card init */
0472     xenon_set_sdclk_off_idle(host, sdhc_id, false);
0473 
0474     xenon_mask_cmd_conflict_err(host);
0475 
0476     return 0;
0477 }
0478 
0479 static void xenon_sdhc_unprepare(struct sdhci_host *host)
0480 {
0481     struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
0482     struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
0483     u8 sdhc_id = priv->sdhc_id;
0484 
0485     /* disable SDHC */
0486     xenon_disable_sdhc(host, sdhc_id);
0487 }
0488 
0489 static int xenon_probe(struct platform_device *pdev)
0490 {
0491     struct sdhci_pltfm_host *pltfm_host;
0492     struct device *dev = &pdev->dev;
0493     struct sdhci_host *host;
0494     struct xenon_priv *priv;
0495     int err;
0496 
0497     host = sdhci_pltfm_init(pdev, &sdhci_xenon_pdata,
0498                 sizeof(struct xenon_priv));
0499     if (IS_ERR(host))
0500         return PTR_ERR(host);
0501 
0502     pltfm_host = sdhci_priv(host);
0503     priv = sdhci_pltfm_priv(pltfm_host);
0504 
0505     priv->hw_version = (unsigned long)device_get_match_data(&pdev->dev);
0506 
0507     /*
0508      * Link Xenon specific mmc_host_ops function,
0509      * to replace standard ones in sdhci_ops.
0510      */
0511     xenon_replace_mmc_host_ops(host);
0512 
0513     if (dev->of_node) {
0514         pltfm_host->clk = devm_clk_get(&pdev->dev, "core");
0515         if (IS_ERR(pltfm_host->clk)) {
0516             err = PTR_ERR(pltfm_host->clk);
0517             dev_err(&pdev->dev, "Failed to setup input clk: %d\n", err);
0518             goto free_pltfm;
0519         }
0520         err = clk_prepare_enable(pltfm_host->clk);
0521         if (err)
0522             goto free_pltfm;
0523 
0524         priv->axi_clk = devm_clk_get(&pdev->dev, "axi");
0525         if (IS_ERR(priv->axi_clk)) {
0526             err = PTR_ERR(priv->axi_clk);
0527             if (err == -EPROBE_DEFER)
0528                 goto err_clk;
0529         } else {
0530             err = clk_prepare_enable(priv->axi_clk);
0531             if (err)
0532                 goto err_clk;
0533         }
0534     }
0535 
0536     err = mmc_of_parse(host->mmc);
0537     if (err)
0538         goto err_clk_axi;
0539 
0540     sdhci_get_property(pdev);
0541 
0542     xenon_set_acg(host, false);
0543 
0544     /* Xenon specific parameters parse */
0545     err = xenon_probe_params(pdev);
0546     if (err)
0547         goto err_clk_axi;
0548 
0549     err = xenon_sdhc_prepare(host);
0550     if (err)
0551         goto err_clk_axi;
0552 
0553     pm_runtime_get_noresume(&pdev->dev);
0554     pm_runtime_set_active(&pdev->dev);
0555     pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
0556     pm_runtime_use_autosuspend(&pdev->dev);
0557     pm_runtime_enable(&pdev->dev);
0558     pm_suspend_ignore_children(&pdev->dev, 1);
0559 
0560     err = sdhci_add_host(host);
0561     if (err)
0562         goto remove_sdhc;
0563 
0564     pm_runtime_put_autosuspend(&pdev->dev);
0565 
0566     return 0;
0567 
0568 remove_sdhc:
0569     pm_runtime_disable(&pdev->dev);
0570     pm_runtime_put_noidle(&pdev->dev);
0571     xenon_sdhc_unprepare(host);
0572 err_clk_axi:
0573     clk_disable_unprepare(priv->axi_clk);
0574 err_clk:
0575     clk_disable_unprepare(pltfm_host->clk);
0576 free_pltfm:
0577     sdhci_pltfm_free(pdev);
0578     return err;
0579 }
0580 
0581 static int xenon_remove(struct platform_device *pdev)
0582 {
0583     struct sdhci_host *host = platform_get_drvdata(pdev);
0584     struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
0585     struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
0586 
0587     pm_runtime_get_sync(&pdev->dev);
0588     pm_runtime_disable(&pdev->dev);
0589     pm_runtime_put_noidle(&pdev->dev);
0590 
0591     sdhci_remove_host(host, 0);
0592 
0593     xenon_sdhc_unprepare(host);
0594     clk_disable_unprepare(priv->axi_clk);
0595     clk_disable_unprepare(pltfm_host->clk);
0596 
0597     sdhci_pltfm_free(pdev);
0598 
0599     return 0;
0600 }
0601 
0602 #ifdef CONFIG_PM_SLEEP
0603 static int xenon_suspend(struct device *dev)
0604 {
0605     struct sdhci_host *host = dev_get_drvdata(dev);
0606     struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
0607     struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
0608     int ret;
0609 
0610     ret = pm_runtime_force_suspend(dev);
0611 
0612     priv->restore_needed = true;
0613     return ret;
0614 }
0615 #endif
0616 
0617 #ifdef CONFIG_PM
0618 static int xenon_runtime_suspend(struct device *dev)
0619 {
0620     struct sdhci_host *host = dev_get_drvdata(dev);
0621     struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
0622     struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
0623     int ret;
0624 
0625     ret = sdhci_runtime_suspend_host(host);
0626     if (ret)
0627         return ret;
0628 
0629     if (host->tuning_mode != SDHCI_TUNING_MODE_3)
0630         mmc_retune_needed(host->mmc);
0631 
0632     clk_disable_unprepare(pltfm_host->clk);
0633     /*
0634      * Need to update the priv->clock here, or when runtime resume
0635      * back, phy don't aware the clock change and won't adjust phy
0636      * which will cause cmd err
0637      */
0638     priv->clock = 0;
0639     return 0;
0640 }
0641 
0642 static int xenon_runtime_resume(struct device *dev)
0643 {
0644     struct sdhci_host *host = dev_get_drvdata(dev);
0645     struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
0646     struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
0647     int ret;
0648 
0649     ret = clk_prepare_enable(pltfm_host->clk);
0650     if (ret) {
0651         dev_err(dev, "can't enable mainck\n");
0652         return ret;
0653     }
0654 
0655     if (priv->restore_needed) {
0656         ret = xenon_sdhc_prepare(host);
0657         if (ret)
0658             goto out;
0659         priv->restore_needed = false;
0660     }
0661 
0662     ret = sdhci_runtime_resume_host(host, 0);
0663     if (ret)
0664         goto out;
0665     return 0;
0666 out:
0667     clk_disable_unprepare(pltfm_host->clk);
0668     return ret;
0669 }
0670 #endif /* CONFIG_PM */
0671 
0672 static const struct dev_pm_ops sdhci_xenon_dev_pm_ops = {
0673     SET_SYSTEM_SLEEP_PM_OPS(xenon_suspend,
0674                 pm_runtime_force_resume)
0675     SET_RUNTIME_PM_OPS(xenon_runtime_suspend,
0676                xenon_runtime_resume,
0677                NULL)
0678 };
0679 
0680 static const struct of_device_id sdhci_xenon_dt_ids[] = {
0681     { .compatible = "marvell,armada-ap806-sdhci", .data = (void *)XENON_AP806},
0682     { .compatible = "marvell,armada-ap807-sdhci", .data = (void *)XENON_AP807},
0683     { .compatible = "marvell,armada-cp110-sdhci", .data =  (void *)XENON_CP110},
0684     { .compatible = "marvell,armada-3700-sdhci", .data =  (void *)XENON_A3700},
0685     {}
0686 };
0687 MODULE_DEVICE_TABLE(of, sdhci_xenon_dt_ids);
0688 
0689 #ifdef CONFIG_ACPI
0690 static const struct acpi_device_id sdhci_xenon_acpi_ids[] = {
0691     { .id = "MRVL0002", XENON_AP806},
0692     { .id = "MRVL0003", XENON_AP807},
0693     { .id = "MRVL0004", XENON_CP110},
0694     {}
0695 };
0696 MODULE_DEVICE_TABLE(acpi, sdhci_xenon_acpi_ids);
0697 #endif
0698 
0699 static struct platform_driver sdhci_xenon_driver = {
0700     .driver = {
0701         .name   = "xenon-sdhci",
0702         .probe_type = PROBE_PREFER_ASYNCHRONOUS,
0703         .of_match_table = sdhci_xenon_dt_ids,
0704         .acpi_match_table = ACPI_PTR(sdhci_xenon_acpi_ids),
0705         .pm = &sdhci_xenon_dev_pm_ops,
0706     },
0707     .probe  = xenon_probe,
0708     .remove = xenon_remove,
0709 };
0710 
0711 module_platform_driver(sdhci_xenon_driver);
0712 
0713 MODULE_DESCRIPTION("SDHCI platform driver for Marvell Xenon SDHC");
0714 MODULE_AUTHOR("Hu Ziji <huziji@marvell.com>");
0715 MODULE_LICENSE("GPL v2");