diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/sdhci-esdhc.h | 7 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-of-esdhc.c | 44 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.c | 8 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.h | 3 |
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 |