summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/host/sdhci-esdhc.h7
-rw-r--r--drivers/mmc/host/sdhci-of-esdhc.c44
-rw-r--r--drivers/mmc/host/sdhci.c8
-rw-r--r--drivers/mmc/host/sdhci.h3
4 files changed, 62 insertions, 0 deletions
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
index 6bb6c52..a4aa096 100644
--- a/drivers/mmc/host/sdhci-esdhc.h
+++ b/drivers/mmc/host/sdhci-esdhc.h
@@ -39,11 +39,18 @@
#define ESDHCI_PRESENT_STATE 0x24
#define ESDHC_CLK_STABLE 0x00000008
+#define ESDHC_PROCTL 0x28
+#define ESDHC_VOLT_SEL 0x00000400
+
#define ESDHC_CAPABILITIES_1 0x114
#define ESDHC_MODE_MASK 0x00000007
#define ESDHC_MODE_DDR50_SEL 0xfffffffc
+#define ESDHC_MODE_SDR104 0x00000002
#define ESDHC_MODE_DDR50 0x00000004
+#define ESDHC_TBCTL 0x120
+#define ESDHC_TB_EN 0x00000004
+
#define ESDHC_CLOCK_CONTROL 0x144
#define ESDHC_CLKLPBK_EXTPIN 0x80000000
#define ESDHC_CMDCLK_SHIFTED 0x00008000
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index d6799a8..afdf21a 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -43,6 +43,11 @@ static u32 esdhc_readl(struct sdhci_host *host, int reg)
if (reg == SDHCI_CAPABILITIES_1) {
ret = sdhci_32bs_readl(host, ESDHC_CAPABILITIES_1);
switch (adapter_type) {
+ case ESDHC_ADAPTER_TYPE_1:
+ if (ret & ESDHC_MODE_SDR104)
+ host->mmc->caps2 |= MMC_CAP2_HS200;
+ ret &= ~ESDHC_MODE_MASK;
+ break;
case ESDHC_ADAPTER_TYPE_3:
if (ret & ESDHC_MODE_DDR50) {
ret &= ESDHC_MODE_DDR50_SEL;
@@ -637,6 +642,43 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
return 0;
}
+void esdhc_set_tuning_block(struct sdhci_host *host)
+{
+ u32 value;
+
+ esdhc_clock_control(host, false);
+ value = sdhci_readl(host, ESDHC_DMA_SYSCTL);
+ value |= ESDHC_FLUSH_ASYNC_FIFO;
+ sdhci_writel(host, value, ESDHC_DMA_SYSCTL);
+
+ value = sdhci_readl(host, ESDHC_TBCTL);
+ value |= ESDHC_TB_EN;
+ sdhci_writel(host, value, ESDHC_TBCTL);
+ esdhc_clock_control(host, true);
+
+}
+
+void esdhc_signal_voltage_switch(struct sdhci_host *host,
+ unsigned char signal_voltage)
+{
+ u32 value;
+
+ value = sdhci_32bs_readl(host, ESDHC_PROCTL);
+
+ switch (signal_voltage) {
+ case MMC_SIGNAL_VOLTAGE_330:
+ value &= (~ESDHC_VOLT_SEL);
+ sdhci_32bs_writel(host, value, ESDHC_PROCTL);
+ break;
+ case MMC_SIGNAL_VOLTAGE_180:
+ value |= ESDHC_VOLT_SEL;
+ sdhci_32bs_writel(host, value, ESDHC_PROCTL);
+ break;
+ default:
+ return;
+ }
+}
+
static const struct sdhci_ops sdhci_esdhc_ops = {
.read_l = esdhc_readl,
.read_w = esdhc_readw,
@@ -661,6 +703,8 @@ static const struct sdhci_ops sdhci_esdhc_ops = {
.adma_workaround = esdhci_of_adma_workaround,
.platform_bus_width = esdhc_pltfm_bus_width,
.set_uhs_signaling = esdhc_set_uhs_signaling,
+ .set_tuning_block = esdhc_set_tuning_block,
+ .signal_voltage_switch = esdhc_signal_voltage_switch,
};
static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 8f0e396..1bc025d 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1750,6 +1750,11 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
if (host->version < SDHCI_SPEC_300)
return 0;
+ if (host->ops->signal_voltage_switch) {
+ host->ops->signal_voltage_switch(host, ios->signal_voltage);
+ return 0;
+ }
+
ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
switch (ios->signal_voltage) {
@@ -1890,6 +1895,9 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
return 0;
}
+ if (host->ops->set_tuning_block)
+ host->ops->set_tuning_block(host);
+
sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
/*
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 096b203..8de8936 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -299,6 +299,9 @@ struct sdhci_ops {
void (*adma_workaround)(struct sdhci_host *host, u32 intmask);
void (*platform_init)(struct sdhci_host *host);
void (*card_event)(struct sdhci_host *host);
+ void (*set_tuning_block)(struct sdhci_host *host);
+ void (*signal_voltage_switch)(struct sdhci_host *host,
+ unsigned char signal_voltage);
};
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS