From dfc13e8402c75e7c2e0a52e123c0500a3259866b Mon Sep 17 00:00:00 2001 From: Hanumath Prasad Date: Thu, 30 Sep 2010 17:37:23 -0400 Subject: mmc: MMC 4.4 DDR support Add support for Dual Data Rate MMC cards as defined in the 4.4 specification. Signed-off-by: Hanumath Prasad Cc: linux-mmc@vger.kernel.org Acked-by: Linus Walleij Tested-by Zhangfei Gao Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 10 +++++++--- drivers/mmc/core/mmc.c | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 759a105cb216..aab593480975 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -373,7 +373,8 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req) readcmd = MMC_READ_SINGLE_BLOCK; writecmd = MMC_WRITE_BLOCK; } - + if (mmc_card_ddr_mode(card)) + brq.data.flags |= MMC_DDR_MODE; if (rq_data_dir(req) == READ) { brq.cmd.opcode = readcmd; brq.data.flags |= MMC_DATA_READ; @@ -655,8 +656,11 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) struct mmc_command cmd; int err; - /* Block-addressed cards ignore MMC_SET_BLOCKLEN. */ - if (mmc_card_blockaddr(card)) + /* + * Block-addressed and ddr mode supported cards + * ignore MMC_SET_BLOCKLEN. + */ + if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card)) return 0; mmc_claim_host(card->host); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 6570c03f9c76..66c4a59fee5f 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -258,6 +258,21 @@ static int mmc_read_ext_csd(struct mmc_card *card) } switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) { + case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52 | + EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 52000000; + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_52; + break; + case EXT_CSD_CARD_TYPE_DDR_1_2V | EXT_CSD_CARD_TYPE_52 | + EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 52000000; + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_2V; + break; + case EXT_CSD_CARD_TYPE_DDR_1_8V | EXT_CSD_CARD_TYPE_52 | + EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 52000000; + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_8V; + break; case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 52000000; break; @@ -502,6 +517,18 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, mmc_set_clock(host, max_dtr); + /* + * Activate DDR50 mode (if supported). + */ + if (mmc_card_highspeed(card)) { + if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) + && (host->caps & (MMC_CAP_1_8V_DDR))) + mmc_card_set_ddr_mode(card); + else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) + && (host->caps & (MMC_CAP_1_2V_DDR))) + mmc_card_set_ddr_mode(card); + } + /* * Activate wide bus (if supported). */ @@ -510,10 +537,16 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, unsigned ext_csd_bit, bus_width; if (host->caps & MMC_CAP_8_BIT_DATA) { - ext_csd_bit = EXT_CSD_BUS_WIDTH_8; + if (mmc_card_ddr_mode(card)) + ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_8; + else + ext_csd_bit = EXT_CSD_BUS_WIDTH_8; bus_width = MMC_BUS_WIDTH_8; } else { - ext_csd_bit = EXT_CSD_BUS_WIDTH_4; + if (mmc_card_ddr_mode(card)) + ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_4; + else + ext_csd_bit = EXT_CSD_BUS_WIDTH_4; bus_width = MMC_BUS_WIDTH_4; } -- cgit v1.2.3