@@ -25,13 +25,11 @@
#include <linux/io.h>
#include <linux/err.h>
#include <plat/sdhci.h>
+#include <mach/cputype.h>
#include "sdhci.h"
#define DRIVER_NAME "sdhci-pxa"
-#define SD_FIFO_PARAM 0x104
-#define DIS_PAD_SD_CLK_GATE 0x400
-
struct sdhci_pxa {
struct sdhci_host *host;
struct sdhci_pxa_platdata *pdata;
@@ -46,10 +44,33 @@ struct sdhci_pxa {
* SDHCI core callbacks *
* *
\*****************************************************************************/
+#ifdef CONFIG_MMC_CLKGATE
+static void hardware_clk_gating(struct sdhci_host *host)
+{
+ unsigned short tmp;
+ int enable;
+
+ /*
+ * MMP2 controller allows clock gating for SD/eMMC/SDIO cards
+ * by extending the definition for SDCTRL_2_ASYNC_INT_EN in the
+ * host control register 2. The SD Host Controller spec
+ * defines this bit for use with SDIO.
+ */
+ enable = host->mmc->clk_gated;
+ tmp = readw(host->ioaddr + HOST_CTRL_2);
+
+ if (enable)
+ tmp |= SDCTRL_2_ASYNC_INT_EN;
+ else
+ tmp &= ~SDCTRL_2_ASYNC_INT_EN;
+
+ writew(tmp, host->ioaddr + HOST_CTRL_2);
+}
+#endif
+
static void set_clock(struct sdhci_host *host, unsigned int clock)
{
struct sdhci_pxa *pxa = sdhci_priv(host);
- u32 tmp = 0;
if (clock == 0) {
if (pxa->clk_enable) {
@@ -58,11 +79,6 @@ static void set_clock(struct sdhci_host *host, unsigned int clock)
}
} else {
if (0 == pxa->clk_enable) {
- if (pxa->pdata->flags & PXA_FLAG_DISABLE_CLOCK_GATING) {
- tmp = readl(host->ioaddr + SD_FIFO_PARAM);
- tmp |= DIS_PAD_SD_CLK_GATE;
- writel(tmp, host->ioaddr + SD_FIFO_PARAM);
- }
clk_enable(pxa->clk);
pxa->clk_enable = 1;
}
@@ -71,6 +87,9 @@ static void set_clock(struct sdhci_host *host, unsigned int clock)
static struct sdhci_ops sdhci_pxa_ops = {
.set_clock = set_clock,
+#ifdef CONFIG_MMC_CLKGATE
+ .platform_hw_clk_gate = hardware_clk_gating,
+#endif
};
/*****************************************************************************\
@@ -145,6 +164,11 @@ static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT)
host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+#ifdef CONFIG_MMC_CLKGATE
+ if (cpu_is_mmp2())
+ host->mmc->caps |= MMC_CAP_HW_CLOCK_GATING;
+#endif
+
ret = sdhci_add_host(host);
if (ret) {
dev_err(&pdev->dev, "failed to add host\n");