aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorGirish K S <girish.shivananjappa@linaro.org>2012-01-05 23:26:39 -0500
committerChris Ball <cjb@laptop.org>2012-01-12 15:17:16 -0500
commit069c9f142822d552ec885572945d8bce9eff0519 (patch)
treef73eedfc7142af588d97cb4008127693f411f298 /drivers
parenta4924c71aa43d4f8a3f342b1f71788349472e684 (diff)
mmc: host: Adds support for eMMC 4.5 HS200 mode
This patch adds support for the HS200 mode on the host side. Also enables the tuning feature required when the HS200 mode is selected. Signed-off-by: Girish K S <girish.shivananjappa@linaro.org> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/host/sdhci.c57
-rw-r--r--drivers/mmc/host/sdhci.h1
2 files changed, 43 insertions, 15 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 0636e9a587b1..96f4e548ba22 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -49,7 +49,7 @@ static void sdhci_finish_data(struct sdhci_host *);
49 49
50static void sdhci_send_command(struct sdhci_host *, struct mmc_command *); 50static void sdhci_send_command(struct sdhci_host *, struct mmc_command *);
51static void sdhci_finish_command(struct sdhci_host *); 51static void sdhci_finish_command(struct sdhci_host *);
52static int sdhci_execute_tuning(struct mmc_host *mmc); 52static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
53static void sdhci_tuning_timer(unsigned long data); 53static void sdhci_tuning_timer(unsigned long data);
54 54
55#ifdef CONFIG_PM_RUNTIME 55#ifdef CONFIG_PM_RUNTIME
@@ -1014,7 +1014,8 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
1014 flags |= SDHCI_CMD_INDEX; 1014 flags |= SDHCI_CMD_INDEX;
1015 1015
1016 /* CMD19 is special in that the Data Present Select should be set */ 1016 /* CMD19 is special in that the Data Present Select should be set */
1017 if (cmd->data || (cmd->opcode == MMC_SEND_TUNING_BLOCK)) 1017 if (cmd->data || cmd->opcode == MMC_SEND_TUNING_BLOCK ||
1018 cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200)
1018 flags |= SDHCI_CMD_DATA; 1019 flags |= SDHCI_CMD_DATA;
1019 1020
1020 sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); 1021 sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
@@ -1287,7 +1288,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
1287 if ((host->flags & SDHCI_NEEDS_RETUNING) && 1288 if ((host->flags & SDHCI_NEEDS_RETUNING) &&
1288 !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) { 1289 !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) {
1289 spin_unlock_irqrestore(&host->lock, flags); 1290 spin_unlock_irqrestore(&host->lock, flags);
1290 sdhci_execute_tuning(mmc); 1291 sdhci_execute_tuning(mmc, mrq->cmd->opcode);
1291 spin_lock_irqsave(&host->lock, flags); 1292 spin_lock_irqsave(&host->lock, flags);
1292 1293
1293 /* Restore original mmc_request structure */ 1294 /* Restore original mmc_request structure */
@@ -1382,7 +1383,8 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
1382 unsigned int clock; 1383 unsigned int clock;
1383 1384
1384 /* In case of UHS-I modes, set High Speed Enable */ 1385 /* In case of UHS-I modes, set High Speed Enable */
1385 if ((ios->timing == MMC_TIMING_UHS_SDR50) || 1386 if ((ios->timing == MMC_TIMING_MMC_HS200) ||
1387 (ios->timing == MMC_TIMING_UHS_SDR50) ||
1386 (ios->timing == MMC_TIMING_UHS_SDR104) || 1388 (ios->timing == MMC_TIMING_UHS_SDR104) ||
1387 (ios->timing == MMC_TIMING_UHS_DDR50) || 1389 (ios->timing == MMC_TIMING_UHS_DDR50) ||
1388 (ios->timing == MMC_TIMING_UHS_SDR25)) 1390 (ios->timing == MMC_TIMING_UHS_SDR25))
@@ -1435,7 +1437,9 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
1435 ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 1437 ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
1436 /* Select Bus Speed Mode for host */ 1438 /* Select Bus Speed Mode for host */
1437 ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; 1439 ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
1438 if (ios->timing == MMC_TIMING_UHS_SDR12) 1440 if (ios->timing == MMC_TIMING_MMC_HS200)
1441 ctrl_2 |= SDHCI_CTRL_HS_SDR200;
1442 else if (ios->timing == MMC_TIMING_UHS_SDR12)
1439 ctrl_2 |= SDHCI_CTRL_UHS_SDR12; 1443 ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
1440 else if (ios->timing == MMC_TIMING_UHS_SDR25) 1444 else if (ios->timing == MMC_TIMING_UHS_SDR25)
1441 ctrl_2 |= SDHCI_CTRL_UHS_SDR25; 1445 ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
@@ -1682,7 +1686,7 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
1682 return err; 1686 return err;
1683} 1687}
1684 1688
1685static int sdhci_execute_tuning(struct mmc_host *mmc) 1689static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
1686{ 1690{
1687 struct sdhci_host *host; 1691 struct sdhci_host *host;
1688 u16 ctrl; 1692 u16 ctrl;
@@ -1690,6 +1694,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
1690 int tuning_loop_counter = MAX_TUNING_LOOP; 1694 int tuning_loop_counter = MAX_TUNING_LOOP;
1691 unsigned long timeout; 1695 unsigned long timeout;
1692 int err = 0; 1696 int err = 0;
1697 bool requires_tuning_nonuhs = false;
1693 1698
1694 host = mmc_priv(mmc); 1699 host = mmc_priv(mmc);
1695 1700
@@ -1700,13 +1705,19 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
1700 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 1705 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
1701 1706
1702 /* 1707 /*
1703 * Host Controller needs tuning only in case of SDR104 mode 1708 * The Host Controller needs tuning only in case of SDR104 mode
1704 * and for SDR50 mode when Use Tuning for SDR50 is set in 1709 * and for SDR50 mode when Use Tuning for SDR50 is set in the
1705 * Capabilities register. 1710 * Capabilities register.
1711 * If the Host Controller supports the HS200 mode then the
1712 * tuning function has to be executed.
1706 */ 1713 */
1714 if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) &&
1715 (host->flags & SDHCI_SDR50_NEEDS_TUNING ||
1716 host->flags & SDHCI_HS200_NEEDS_TUNING))
1717 requires_tuning_nonuhs = true;
1718
1707 if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) || 1719 if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) ||
1708 (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) && 1720 requires_tuning_nonuhs)
1709 (host->flags & SDHCI_SDR50_NEEDS_TUNING)))
1710 ctrl |= SDHCI_CTRL_EXEC_TUNING; 1721 ctrl |= SDHCI_CTRL_EXEC_TUNING;
1711 else { 1722 else {
1712 spin_unlock(&host->lock); 1723 spin_unlock(&host->lock);
@@ -1742,7 +1753,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
1742 if (!tuning_loop_counter && !timeout) 1753 if (!tuning_loop_counter && !timeout)
1743 break; 1754 break;
1744 1755
1745 cmd.opcode = MMC_SEND_TUNING_BLOCK; 1756 cmd.opcode = opcode;
1746 cmd.arg = 0; 1757 cmd.arg = 0;
1747 cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; 1758 cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
1748 cmd.retries = 0; 1759 cmd.retries = 0;
@@ -1757,7 +1768,17 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
1757 * block to the Host Controller. So we set the block size 1768 * block to the Host Controller. So we set the block size
1758 * to 64 here. 1769 * to 64 here.
1759 */ 1770 */
1760 sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), SDHCI_BLOCK_SIZE); 1771 if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200) {
1772 if (mmc->ios.bus_width == MMC_BUS_WIDTH_8)
1773 sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 128),
1774 SDHCI_BLOCK_SIZE);
1775 else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4)
1776 sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64),
1777 SDHCI_BLOCK_SIZE);
1778 } else {
1779 sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64),
1780 SDHCI_BLOCK_SIZE);
1781 }
1761 1782
1762 /* 1783 /*
1763 * The tuning block is sent by the card to the host controller. 1784 * The tuning block is sent by the card to the host controller.
@@ -2140,12 +2161,14 @@ static void sdhci_show_adma_error(struct sdhci_host *host) { }
2140 2161
2141static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) 2162static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
2142{ 2163{
2164 u32 command;
2143 BUG_ON(intmask == 0); 2165 BUG_ON(intmask == 0);
2144 2166
2145 /* CMD19 generates _only_ Buffer Read Ready interrupt */ 2167 /* CMD19 generates _only_ Buffer Read Ready interrupt */
2146 if (intmask & SDHCI_INT_DATA_AVAIL) { 2168 if (intmask & SDHCI_INT_DATA_AVAIL) {
2147 if (SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) == 2169 command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND));
2148 MMC_SEND_TUNING_BLOCK) { 2170 if (command == MMC_SEND_TUNING_BLOCK ||
2171 command == MMC_SEND_TUNING_BLOCK_HS200) {
2149 host->tuning_done = 1; 2172 host->tuning_done = 1;
2150 wake_up(&host->buf_ready_int); 2173 wake_up(&host->buf_ready_int);
2151 return; 2174 return;
@@ -2747,10 +2770,14 @@ int sdhci_add_host(struct sdhci_host *host)
2747 if (caps[1] & SDHCI_SUPPORT_DDR50) 2770 if (caps[1] & SDHCI_SUPPORT_DDR50)
2748 mmc->caps |= MMC_CAP_UHS_DDR50; 2771 mmc->caps |= MMC_CAP_UHS_DDR50;
2749 2772
2750 /* Does the host needs tuning for SDR50? */ 2773 /* Does the host need tuning for SDR50? */
2751 if (caps[1] & SDHCI_USE_SDR50_TUNING) 2774 if (caps[1] & SDHCI_USE_SDR50_TUNING)
2752 host->flags |= SDHCI_SDR50_NEEDS_TUNING; 2775 host->flags |= SDHCI_SDR50_NEEDS_TUNING;
2753 2776
2777 /* Does the host need tuning for HS200? */
2778 if (mmc->caps2 & MMC_CAP2_HS200)
2779 host->flags |= SDHCI_HS200_NEEDS_TUNING;
2780
2754 /* Driver Type(s) (A, C, D) supported by the host */ 2781 /* Driver Type(s) (A, C, D) supported by the host */
2755 if (caps[1] & SDHCI_DRIVER_TYPE_A) 2782 if (caps[1] & SDHCI_DRIVER_TYPE_A)
2756 mmc->caps |= MMC_CAP_DRIVER_TYPE_A; 2783 mmc->caps |= MMC_CAP_DRIVER_TYPE_A;
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index a04d4d0c6fd2..ad265b96b75b 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -158,6 +158,7 @@
158#define SDHCI_CTRL_UHS_SDR50 0x0002 158#define SDHCI_CTRL_UHS_SDR50 0x0002
159#define SDHCI_CTRL_UHS_SDR104 0x0003 159#define SDHCI_CTRL_UHS_SDR104 0x0003
160#define SDHCI_CTRL_UHS_DDR50 0x0004 160#define SDHCI_CTRL_UHS_DDR50 0x0004
161#define SDHCI_CTRL_HS_SDR200 0x0005 /* reserved value in SDIO spec */
161#define SDHCI_CTRL_VDD_180 0x0008 162#define SDHCI_CTRL_VDD_180 0x0008
162#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030 163#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030
163#define SDHCI_CTRL_DRV_TYPE_B 0x0000 164#define SDHCI_CTRL_DRV_TYPE_B 0x0000