@@ -77,8 +77,10 @@ static void sdhci_dumpregs(struct sdhci_host *host)
printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
sdhci_readw(host, SDHCI_ACMD12_ERR),
sdhci_readw(host, SDHCI_SLOT_INT_STATUS));
- printk(KERN_DEBUG DRIVER_NAME ": Caps: 0x%08x | Max curr: 0x%08x\n",
+ printk(KERN_DEBUG DRIVER_NAME ": Caps: 0x%08x | Caps1: 0x%08x\n",
sdhci_readl(host, SDHCI_CAPABILITIES),
+ sdhci_readl(host, SDHCI_CAPABILITIES_1));
+ printk(KERN_DEBUG DRIVER_NAME ": Max curr: 0x%08x\n",
sdhci_readl(host, SDHCI_MAX_CURRENT));
if (host->flags & SDHCI_USE_ADMA)
@@ -1217,6 +1219,14 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
/*
+ * Higher speed data rates may need tuning - board specific.
+ * punt handling these speeds to the adoption layer
+ */
+ if ((host->flags & SDHCI_DATA_RATES_300) &&
+ host->ops->program_v3_rate)
+ host->ops->program_v3_rate(host, ios);
+
+ /*
* Some (ENE) controllers go apeshit on some ios operation,
* signalling timeout and CRC errors even on CMD0. Resetting
* it on each ios seems to solve the problem.
@@ -1720,6 +1730,7 @@ int sdhci_add_host(struct sdhci_host *host)
{
struct mmc_host *mmc;
unsigned int caps;
+ unsigned int caps_1;
int ret;
WARN_ON(host == NULL);
@@ -1745,6 +1756,13 @@ int sdhci_add_host(struct sdhci_host *host)
caps = (host->quirks & SDHCI_QUIRK_MISSING_CAPS) ? host->caps :
sdhci_readl(host, SDHCI_CAPABILITIES);
+ if (host->version >= SDHCI_SPEC_300) {
+ caps_1 = (host->quirks & SDHCI_QUIRK_MISSING_CAPS_1) ?
+ host->caps_1 : sdhci_readl(host, SDHCI_CAPABILITIES_1);
+ }
+ else
+ caps_1 = 0;
+
if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
host->flags |= SDHCI_USE_SDMA;
else if (!(caps & SDHCI_CAN_DO_SDMA))
@@ -1873,6 +1891,25 @@ int sdhci_add_host(struct sdhci_host *host)
mmc_card_is_removable(mmc))
mmc->caps |= MMC_CAP_NEEDS_POLL;
+ /* require platform code to handle v3 speeds */
+ if (host->version >= SDHCI_SPEC_300 && host->ops->program_v3_rate) {
+ if (host->ops->support_v3_data_rates &&
+ host->ops->support_v3_data_rates(host, caps_1)) {
+ mmc->caps |= MMC_CAP_1_8V_DDR;
+ mmc->caps |= MMC_CAP_1_2V_DDR;
+ host->flags |= SDHCI_DATA_RATES_300;
+ }
+ else if (caps_1 & ( SDHCI_CAN_DO_SDR50 |
+ SDHCI_CAN_DO_SDR104 |
+ SDHCI_CAN_DO_DDR50)) {
+ host->flags |= SDHCI_DATA_RATES_300;
+ if (caps_1 & SDHCI_CAN_DO_DDR50) {
+ mmc->caps |= MMC_CAP_1_8V_DDR;
+ mmc->caps |= MMC_CAP_1_2V_DDR;
+ }
+ }
+ }
+
mmc->ocr_avail = 0;
if (caps & SDHCI_CAN_VDD_330)
mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34;
@@ -137,7 +137,25 @@
#define SDHCI_ACMD12_ERR 0x3C
-/* 3E-3F reserved */
+#define HOST_CONTROL_2 0x3E
+#define SDHCI_CTL2_UHS_MODE_SEL_SDR12 0
+#define SDHCI_CTL2_UHS_MODE_SEL_SDR25 1
+#define SDHCI_CTL2_UHS_MODE_SEL_SDR50 2
+#define SDHCI_CTL2_UHS_MODE_SEL_SDR104 3
+#define SDHCI_CTL2_UHS_MODE_SEL_DDR50 4
+#define SDHCI_CTL2_UHS_MODE_MASK 0x7
+#define SDHCI_CTL2_UHS_MODE_SHIFT 0
+#define SDHCI_CTL2_SDH_V18_EN 0x00000008
+#define SDHCI_CTL2_DRV_STRENGTH_SEL_B 0
+#define SDHCI_CTL2_DRV_STRENGTH_SEL_A 1
+#define SDHCI_CTL2_DRV_STRENGTH_SEL_C 2
+#define SDHCI_CTL2_DRV_STRENGTH_SEL_D 3
+#define SDHCI_CTL2_DRV_STRENGTH_MASK 0x3
+#define SDHCI_CTL2_DRV_STRENGTH_SHIFT 4
+#define SDHCI_CTL2_EXE_TUNING 0x00000040
+#define SDHCI_CTL2_SAMPLING_CLK_SEL 0x00000080
+#define SDHCI_CTL2_ASYNC_INT_EN 0x00004000
+#define SDHCI_CTL2_PRE_VAL_EN 0x00008000
#define SDHCI_CAPABILITIES 0x40
#define SDHCI_TIMEOUT_CLK_MASK 0x0000003F
@@ -158,7 +176,20 @@
#define SDHCI_CAN_VDD_180 0x04000000
#define SDHCI_CAN_64BIT 0x10000000
-/* 44-47 reserved for more caps */
+#define SDHCI_CAPABILITIES_1 0x44
+#define SDHCI_CAN_DO_SDR50 0x00000001
+#define SDHCI_CAN_DO_SDR104 0x00000002
+#define SDHCI_CAN_DO_DDR50 0x00000004
+#define SDHCI_DRIVER_TYPE_A 0x00000010
+#define SDHCI_DRIVER_TYPE_C 0x00000020
+#define SDHCI_DRIVER_TYPE_D 0x00000040
+#define SDHCI_RETUNING_TIME_COUNT_MASK 0x00000F00
+#define SDHCI_RETUNING_TIME_COUNT_SHIFT 8
+#define SDHCI_USE_TUNING_DDR50 0x00002000
+#define SDHCI_RETUNING_MODE_MASK 0x0000C000
+#define SDHCI_RETUNING_MODE_SHIFT 14
+#define SDHCI_CLOCK_MULTIPLIER_MASK 0x00FF0000
+#define SDHCI_CLOCK_MULTIPLIER_SHIFT 16
#define SDHCI_MAX_CURRENT 0x48
@@ -263,6 +294,8 @@ struct sdhci_host {
#define SDHCI_QUIRK_NO_HISPD_BIT (1<<29)
/* slot has 8 data pins going to eMMC/mmc card */
#define SDHCI_QUIRK_SLOT_CAN_DO_8_BITS (1<<30)
+/* Controller is missing capability register 1 (sd 3.0) */
+#define SDHCI_QUIRK_MISSING_CAPS_1 (1<<31)
int irq; /* Device IRQ */
void __iomem * ioaddr; /* Mapped address */
@@ -287,6 +320,7 @@ struct sdhci_host {
#define SDHCI_USE_ADMA (1<<1) /* Host is ADMA capable */
#define SDHCI_REQ_USE_DMA (1<<2) /* Use DMA for this req. */
#define SDHCI_DEVICE_DEAD (1<<3) /* Device unresponsive */
+#define SDHCI_DATA_RATES_300 (1<<4) /* Host can do V3 data rates */
unsigned int version; /* SDHCI spec. version */
@@ -318,6 +352,7 @@ struct sdhci_host {
struct timer_list timer; /* Timer for timeouts */
unsigned int caps; /* Alternative capabilities */
+ unsigned int caps_1; /* Alternative capabilities */
unsigned long private[0] ____cacheline_aligned;
};
@@ -341,6 +376,10 @@ struct sdhci_ops {
unsigned int (*get_timeout_clock)(struct sdhci_host *host);
int (*platform_8bit_width)(struct sdhci_host *host,
int width);
+ int (*support_v3_data_rates)(struct sdhci_host *host,
+ unsigned int caps_1);
+ int (*program_v3_rate)(struct sdhci_host *host,
+ struct mmc_ios *ios);
};
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS