@@ -84,6 +84,8 @@ static void sdhci_dumpregs(struct sdhci_host *host)
printk(KERN_DEBUG DRIVER_NAME ": Cmd: 0x%08x | Max curr: 0x%08x\n",
sdhci_readw(host, SDHCI_COMMAND),
sdhci_readl(host, SDHCI_MAX_CURRENT));
+ printk(KERN_DEBUG DRIVER_NAME ": HostCtrl2:0x%08x\n",
+ sdhci_readw(host, SDHCI_HOST_CONTROL_2));
if (host->flags & SDHCI_USE_ADMA)
printk(KERN_DEBUG DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n",
@@ -986,6 +988,38 @@ static void sdhci_finish_command(struct sdhci_host *host)
host->cmd = NULL;
}
+/*
+ * Handle 1.8V signaling for DDR. No need to check for other
+ * DDR values since driver supports ONLY 1_8V DDR. This is
+ * set by the MMC_CAP_1_8V_DDR. 1_2V DDR is not supported.
+ */
+static void sdhci_set_ddr(struct sdhci_host *host, unsigned int ddr)
+{
+ u16 con;
+
+ if (ddr == MMC_SDR_MODE)
+ return;
+
+ con = sdhci_readw(host, SDHCI_HOST_CONTROL_2);
+ con |= SDCTRL_2_SDH_V18_EN;
+ sdhci_writew(host, con, SDHCI_HOST_CONTROL_2);
+
+ /* Change sigalling voltage and wait for it to be stable */
+ if (host->ops->set_signaling_voltage)
+ host->ops->set_signaling_voltage(host, 18);
+ else
+ mdelay(5);
+
+ /*
+ * We can fail here but there is no higher level recovery
+ * since the card is already past the switch to ddr
+ */
+ con = sdhci_readw(host, SDHCI_HOST_CONTROL_2);
+ con &= ~SDCTRL_2_UHS_MODE_MASK;
+ con |= SDCTRL_2_UHS_MODE_SEL_DDR50;
+ sdhci_writew(host, con, SDHCI_HOST_CONTROL_2);
+}
+
static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
{
int div;
@@ -1180,6 +1214,7 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
}
sdhci_set_clock(host, ios->clock);
+ sdhci_set_ddr(host, ios->ddr);
if (ios->power_mode == MMC_POWER_OFF)
sdhci_set_power(host, -1);
@@ -1744,7 +1779,7 @@ EXPORT_SYMBOL_GPL(sdhci_alloc_host);
int sdhci_add_host(struct sdhci_host *host)
{
struct mmc_host *mmc;
- unsigned int caps, ocr_avail;
+ unsigned int caps, caps_h, ocr_avail;
int ret;
WARN_ON(host == NULL);
@@ -1767,8 +1802,19 @@ int sdhci_add_host(struct sdhci_host *host)
host->version);
}
- caps = (host->quirks & SDHCI_QUIRK_MISSING_CAPS) ? host->caps :
- sdhci_readl(host, SDHCI_CAPABILITIES);
+ if (host->quirks & SDHCI_QUIRK_MISSING_CAPS) {
+ caps = host->caps;
+ caps_h = 0;
+ } else {
+ caps = sdhci_readl(host, SDHCI_CAPABILITIES);
+ if (host->version >= SDHCI_SPEC_300)
+ caps_h = sdhci_readl(host, SDHCI_CAPABILITIES_1);
+ else
+ caps_h = 0;
+ }
+
+ if (caps_h & SDHCI_CAN_DDR50)
+ mmc->caps |= MMC_CAP_1_8V_DDR;
if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
host->flags |= SDHCI_USE_SDMA;
@@ -1905,7 +1951,6 @@ int sdhci_add_host(struct sdhci_host *host)
ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31;
if (caps & SDHCI_CAN_VDD_180)
ocr_avail |= MMC_VDD_165_195;
-
mmc->ocr_avail = ocr_avail;
mmc->ocr_avail_sdio = ocr_avail;
if (host->ocr_avail_sdio)
@@ -182,6 +182,9 @@
#define SDHCI_CAN_64BIT 0x10000000
#define SDHCI_CAPABILITIES_1 0x44
+#define SDHCI_CAN_SDR50 0x00000001
+#define SDHCI_CAN_SDR104 0x00000002
+#define SDHCI_CAN_DDR50 0x00000004
#define SDHCI_MAX_CURRENT 0x48
@@ -237,6 +240,8 @@ struct sdhci_ops {
void (*platform_send_init_74_clocks)(struct sdhci_host *host,
u8 power_mode);
unsigned int (*get_ro)(struct sdhci_host *host);
+ unsigned int (*set_signaling_voltage)(struct sdhci_host *host,
+ unsigned short voltage);
};
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS