@@ -76,8 +76,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)
@@ -1001,9 +1003,19 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
if (clock == 0)
goto out;
- for (div = 1;div < 256;div *= 2) {
- if ((host->max_clk / div) <= clock)
- break;
+ if (host->version >= SDHCI_SPEC_300) {
+ if (host->max_clk <= clock)
+ div = 1;
+ else {
+ div = host->max_clk/clock;
+ if (host->max_clk % clock)
+ div++;
+ }
+ } else {
+ for (div = 1;div < 256;div *= 2) {
+ if ((host->max_clk / div) <= clock)
+ break;
+ }
}
div >>= 1;
@@ -1025,6 +1037,9 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
mdelay(1);
}
+ clk = (div & SDHCI_CLOCK_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
+ clk |= ((div & SDHCI_CLOCK_DIV_HI_MASK) >> SDHCI_CLOCK_DIV_MASK_LEN)
+ << SDHCI_CLOCK_DIVIDER_HI_SHIFT;
clk |= SDHCI_CLOCK_CARD_EN;
sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
@@ -1169,11 +1184,13 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
sdhci_set_power(host, ios->vdd);
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
-
- if (ios->bus_width == MMC_BUS_WIDTH_8)
- ctrl |= SDHCI_CTRL_8BITBUS;
- else
- ctrl &= ~SDHCI_CTRL_8BITBUS;
+ if (host->version >= SDHCI_SPEC_300) {
+ if (ios->bus_width == MMC_BUS_WIDTH_8) {
+ ctrl |= SDHCI_CTRL_8BITBUS;
+ ctrl &= ~SDHCI_CTRL_4BITBUS;
+ } else
+ ctrl &= ~SDHCI_CTRL_8BITBUS;
+ }
if (ios->bus_width == MMC_BUS_WIDTH_4)
ctrl |= SDHCI_CTRL_4BITBUS;
@@ -1189,6 +1206,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 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.
@@ -1692,6 +1717,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);
@@ -1708,7 +1734,7 @@ int sdhci_add_host(struct sdhci_host *host)
host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
host->version = (host->version & SDHCI_SPEC_VER_MASK)
>> SDHCI_SPEC_VER_SHIFT;
- if (host->version > SDHCI_SPEC_200) {
+ if (host->version > SDHCI_SPEC_300) {
printk(KERN_ERR "%s: Unknown controller version (%d). "
"You may experience problems.\n", mmc_hostname(mmc),
host->version);
@@ -1717,6 +1743,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))
@@ -1779,8 +1812,14 @@ int sdhci_add_host(struct sdhci_host *host)
mmc_dev(host->mmc)->dma_mask = &host->dma_mask;
}
- host->max_clk =
- (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
+ if (host->version >= SDHCI_SPEC_300)
+ host->max_clk =
+ (caps & SDHCI_CLOCK_BASE_MASK_300) >>
+ SDHCI_CLOCK_BASE_SHIFT;
+ else
+ host->max_clk =
+ (caps & SDHCI_CLOCK_BASE_MASK) >>
+ SDHCI_CLOCK_BASE_SHIFT;
host->max_clk *= 1000000;
if (host->max_clk == 0 || host->quirks &
SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) {
@@ -1815,6 +1854,8 @@ int sdhci_add_host(struct sdhci_host *host)
mmc->ops = &sdhci_ops;
if (host->ops->get_min_clock)
mmc->f_min = host->ops->get_min_clock(host);
+ else if (host->version >= SDHCI_SPEC_300)
+ mmc->f_min = host->max_clk / 2046;
else
mmc->f_min = host->max_clk / 256;
mmc->f_max = host->max_clk;
@@ -1829,6 +1870,22 @@ int sdhci_add_host(struct sdhci_host *host)
if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
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_DUAL_DATA_RATE;
+ 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_DUAL_DATA_RATE;
+ }
+ }
+
mmc->ocr_avail = 0;
if (caps & SDHCI_CAN_VDD_330)
mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34;
@@ -72,7 +72,7 @@
#define SDHCI_CTRL_ADMA1 0x08
#define SDHCI_CTRL_ADMA32 0x10
#define SDHCI_CTRL_ADMA64 0x18
-#define SDHCI_CTRL_8BITBUS 0x20
+#define SDHCI_CTRL_8BITBUS 0x20
#define SDHCI_POWER_CONTROL 0x29
#define SDHCI_POWER_ON 0x01
@@ -86,6 +86,10 @@
#define SDHCI_CLOCK_CONTROL 0x2C
#define SDHCI_DIVIDER_SHIFT 8
+#define SDHCI_CLOCK_DIV_MASK 0xFF
+#define SDHCI_CLOCK_DIVIDER_HI_SHIFT 6
+#define SDHCI_CLOCK_DIV_MASK_LEN 8
+#define SDHCI_CLOCK_DIV_HI_MASK 0x300
#define SDHCI_CLOCK_CARD_EN 0x0004
#define SDHCI_CLOCK_INT_STABLE 0x0002
#define SDHCI_CLOCK_INT_EN 0x0001
@@ -133,13 +137,32 @@
#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
#define SDHCI_TIMEOUT_CLK_SHIFT 0
#define SDHCI_TIMEOUT_CLK_UNIT 0x00000080
#define SDHCI_CLOCK_BASE_MASK 0x00003F00
+#define SDHCI_CLOCK_BASE_MASK_300 0x0000FF00
#define SDHCI_CLOCK_BASE_SHIFT 8
#define SDHCI_MAX_BLOCK_MASK 0x00030000
#define SDHCI_MAX_BLOCK_SHIFT 16
@@ -152,7 +175,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
@@ -178,6 +214,7 @@
#define SDHCI_SPEC_VER_SHIFT 0
#define SDHCI_SPEC_100 0
#define SDHCI_SPEC_200 1
+#define SDHCI_SPEC_300 2
struct sdhci_ops;
@@ -247,6 +284,8 @@ struct sdhci_host {
#define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 (1<<28)
/* Controller doesn't have HISPD bit field in HI-SPEED SD card */
#define SDHCI_QUIRK_NO_HISPD_BIT (1<<29)
+/* Controller is missing capability register 1 (sd 3.0) */
+#define SDHCI_QUIRK_MISSING_CAPS_1 (1<<30)
int irq; /* Device IRQ */
void __iomem * ioaddr; /* Mapped address */
@@ -271,6 +310,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 */
@@ -302,6 +342,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;
};
@@ -323,6 +364,10 @@ struct sdhci_ops {
unsigned int (*get_max_clock)(struct sdhci_host *host);
unsigned int (*get_min_clock)(struct sdhci_host *host);
unsigned int (*get_timeout_clock)(struct sdhci_host *host);
+ 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
@@ -157,6 +157,7 @@ struct mmc_host {
#define MMC_CAP_NONREMOVABLE (1 << 8) /* Nonremovable e.g. eMMC */
#define MMC_CAP_WAIT_WHILE_BUSY (1 << 9) /* Waits while card is busy */
#define MMC_CAP_ERASE (1 << 10) /* Allow erase/trim commands */
+#define MMC_CAP_DUAL_DATA_RATE (1 << 11) /* MMC can do dual data rate */
mmc_pm_flag_t pm_caps; /* supported pm features */