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 <hanumath.prasad@stericsson.com> Cc: linux-mmc@vger.kernel.org Acked-by: Linus Walleij <linus.walleij@stericsson.com> Tested-by Zhangfei Gao <zhangfei.gao@marvell.com> Signed-off-by: Chris Ball <cjb@laptop.org>
This commit is contained in:
parent
99fc513101
commit
dfc13e8402
6 changed files with 60 additions and 6 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ struct mmc_ext_csd {
|
|||
unsigned int sa_timeout; /* Units: 100ns */
|
||||
unsigned int hs_max_dtr;
|
||||
unsigned int sectors;
|
||||
unsigned int card_type;
|
||||
unsigned int hc_erase_size; /* In sectors */
|
||||
unsigned int hc_erase_timeout; /* In milliseconds */
|
||||
unsigned int sec_trim_mult; /* Secure trim multiplier */
|
||||
|
@ -113,6 +114,7 @@ struct mmc_card {
|
|||
#define MMC_STATE_READONLY (1<<1) /* card is read-only */
|
||||
#define MMC_STATE_HIGHSPEED (1<<2) /* card is in high speed mode */
|
||||
#define MMC_STATE_BLOCKADDR (1<<3) /* card uses block-addressing */
|
||||
#define MMC_STATE_HIGHSPEED_DDR (1<<4) /* card is in high speed mode */
|
||||
unsigned int quirks; /* card quirks */
|
||||
#define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */
|
||||
#define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */
|
||||
|
@ -154,11 +156,13 @@ struct mmc_card {
|
|||
#define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY)
|
||||
#define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED)
|
||||
#define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR)
|
||||
#define mmc_card_ddr_mode(c) ((c)->state & MMC_STATE_HIGHSPEED_DDR)
|
||||
|
||||
#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
|
||||
#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
|
||||
#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
|
||||
#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
|
||||
#define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)
|
||||
|
||||
static inline int mmc_card_lenient_fn0(const struct mmc_card *c)
|
||||
{
|
||||
|
|
|
@ -109,6 +109,7 @@ struct mmc_data {
|
|||
#define MMC_DATA_WRITE (1 << 8)
|
||||
#define MMC_DATA_READ (1 << 9)
|
||||
#define MMC_DATA_STREAM (1 << 10)
|
||||
#define MMC_DDR_MODE (1 << 11)
|
||||
|
||||
unsigned int bytes_xfered;
|
||||
|
||||
|
|
|
@ -158,6 +158,10 @@ 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_1_8V_DDR (1 << 11) /* can support */
|
||||
/* DDR mode at 1.8V */
|
||||
#define MMC_CAP_1_2V_DDR (1 << 12) /* can support */
|
||||
/* DDR mode at 1.2V */
|
||||
|
||||
mmc_pm_flag_t pm_caps; /* supported pm features */
|
||||
|
||||
|
|
|
@ -277,11 +277,19 @@ struct _mmc_csd {
|
|||
|
||||
#define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */
|
||||
#define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */
|
||||
#define EXT_CSD_CARD_TYPE_MASK 0x3 /* Mask out reserved and DDR bits */
|
||||
#define EXT_CSD_CARD_TYPE_MASK 0xF /* Mask out reserved bits */
|
||||
#define EXT_CSD_CARD_TYPE_DDR_1_8V (1<<2) /* Card can run at 52MHz */
|
||||
/* DDR mode @1.8V or 3V I/O */
|
||||
#define EXT_CSD_CARD_TYPE_DDR_1_2V (1<<3) /* Card can run at 52MHz */
|
||||
/* DDR mode @1.2V I/O */
|
||||
#define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \
|
||||
| EXT_CSD_CARD_TYPE_DDR_1_2V)
|
||||
|
||||
#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
|
||||
#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
|
||||
#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
|
||||
#define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */
|
||||
#define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */
|
||||
|
||||
#define EXT_CSD_SEC_ER_EN BIT(0)
|
||||
#define EXT_CSD_SEC_BD_BLK_EN BIT(2)
|
||||
|
|
Reference in a new issue