aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilip Rakity <prakity@marvell.com>2011-05-13 01:47:18 -0400
committerChris Ball <cjb@laptop.org>2011-05-24 23:53:58 -0400
commit4c4cb171054230c2e58ed6574d7faa1871c75bbe (patch)
tree8ba336234def08a99ae98d29047da69de41cdcb0
parent261bbd463a091b939770255d559bbc89b1bad568 (diff)
mmc: core: add support for eMMC Dual Data Rate
eMMC voltage change not required for 1.8V. 3.3V and 1.8V vcc are capable of doing DDR. vccq of 1.8v is not required. Signed-off-by: Philip Rakity <prakity@marvell.com> Reviewed-by: Arindam Nath <arindam.nath@amd.com> Signed-off-by: Chris Ball <cjb@laptop.org>
-rw-r--r--drivers/mmc/core/core.c14
-rw-r--r--drivers/mmc/core/core.h2
-rw-r--r--drivers/mmc/core/mmc.c35
-rw-r--r--include/linux/mmc/host.h1
4 files changed, 33 insertions, 19 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 94c8d5a9eca..7863eedf3d9 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -718,22 +718,12 @@ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode)
718} 718}
719 719
720/* 720/*
721 * Change data bus width and DDR mode of a host.
722 */
723void mmc_set_bus_width_ddr(struct mmc_host *host, unsigned int width,
724 unsigned int ddr)
725{
726 host->ios.bus_width = width;
727 host->ios.ddr = ddr;
728 mmc_set_ios(host);
729}
730
731/*
732 * Change data bus width of a host. 721 * Change data bus width of a host.
733 */ 722 */
734void mmc_set_bus_width(struct mmc_host *host, unsigned int width) 723void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
735{ 724{
736 mmc_set_bus_width_ddr(host, width, MMC_SDR_MODE); 725 host->ios.bus_width = width;
726 mmc_set_ios(host);
737} 727}
738 728
739/** 729/**
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 53d23c24032..d9411ed2a39 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -38,8 +38,6 @@ void mmc_ungate_clock(struct mmc_host *host);
38void mmc_set_ungated(struct mmc_host *host); 38void mmc_set_ungated(struct mmc_host *host);
39void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); 39void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode);
40void mmc_set_bus_width(struct mmc_host *host, unsigned int width); 40void mmc_set_bus_width(struct mmc_host *host, unsigned int width);
41void mmc_set_bus_width_ddr(struct mmc_host *host, unsigned int width,
42 unsigned int ddr);
43u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); 41u32 mmc_select_voltage(struct mmc_host *host, u32 ocr);
44int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, 42int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage,
45 bool cmd11); 43 bool cmd11);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index a2c795e8f9d..0433fe66cba 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -20,6 +20,7 @@
20#include "core.h" 20#include "core.h"
21#include "bus.h" 21#include "bus.h"
22#include "mmc_ops.h" 22#include "mmc_ops.h"
23#include "sd_ops.h"
23 24
24static const unsigned int tran_exp[] = { 25static const unsigned int tran_exp[] = {
25 10000, 100000, 1000000, 10000000, 26 10000, 100000, 1000000, 10000000,
@@ -633,10 +634,14 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
633 */ 634 */
634 if (mmc_card_highspeed(card)) { 635 if (mmc_card_highspeed(card)) {
635 if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) 636 if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
636 && (host->caps & (MMC_CAP_1_8V_DDR))) 637 && ((host->caps & (MMC_CAP_1_8V_DDR |
638 MMC_CAP_UHS_DDR50))
639 == (MMC_CAP_1_8V_DDR | MMC_CAP_UHS_DDR50)))
637 ddr = MMC_1_8V_DDR_MODE; 640 ddr = MMC_1_8V_DDR_MODE;
638 else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) 641 else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
639 && (host->caps & (MMC_CAP_1_2V_DDR))) 642 && ((host->caps & (MMC_CAP_1_2V_DDR |
643 MMC_CAP_UHS_DDR50))
644 == (MMC_CAP_1_2V_DDR | MMC_CAP_UHS_DDR50)))
640 ddr = MMC_1_2V_DDR_MODE; 645 ddr = MMC_1_2V_DDR_MODE;
641 } 646 }
642 647
@@ -670,8 +675,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
670 ext_csd_bits[idx][0], 675 ext_csd_bits[idx][0],
671 0); 676 0);
672 if (!err) { 677 if (!err) {
673 mmc_set_bus_width_ddr(card->host, 678 mmc_set_bus_width(card->host, bus_width);
674 bus_width, MMC_SDR_MODE);
675 /* 679 /*
676 * If controller can't handle bus width test, 680 * If controller can't handle bus width test,
677 * use the highest bus width to maintain 681 * use the highest bus width to maintain
@@ -697,8 +701,29 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
697 1 << bus_width, ddr); 701 1 << bus_width, ddr);
698 goto free_card; 702 goto free_card;
699 } else if (ddr) { 703 } else if (ddr) {
704 /*
705 * eMMC cards can support 3.3V to 1.2V i/o (vccq)
706 * signaling.
707 *
708 * EXT_CSD_CARD_TYPE_DDR_1_8V means 3.3V or 1.8V vccq.
709 *
710 * 1.8V vccq at 3.3V core voltage (vcc) is not required
711 * in the JEDEC spec for DDR.
712 *
713 * Do not force change in vccq since we are obviously
714 * working and no change to vccq is needed.
715 *
716 * WARNING: eMMC rules are NOT the same as SD DDR
717 */
718 if (ddr == EXT_CSD_CARD_TYPE_DDR_1_2V) {
719 err = mmc_set_signal_voltage(host,
720 MMC_SIGNAL_VOLTAGE_120, 0);
721 if (err)
722 goto err;
723 }
700 mmc_card_set_ddr_mode(card); 724 mmc_card_set_ddr_mode(card);
701 mmc_set_bus_width_ddr(card->host, bus_width, ddr); 725 mmc_set_timing(card->host, MMC_TIMING_UHS_DDR50);
726 mmc_set_bus_width(card->host, bus_width);
702 } 727 }
703 } 728 }
704 729
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 6716bd12ecc..de32e6aa018 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -66,6 +66,7 @@ struct mmc_ios {
66 66
67#define MMC_SIGNAL_VOLTAGE_330 0 67#define MMC_SIGNAL_VOLTAGE_330 0
68#define MMC_SIGNAL_VOLTAGE_180 1 68#define MMC_SIGNAL_VOLTAGE_180 1
69#define MMC_SIGNAL_VOLTAGE_120 2
69 70
70 unsigned char drv_type; /* driver type (A, B, C, D) */ 71 unsigned char drv_type; /* driver type (A, B, C, D) */
71 72