2010-07-09 07:25:33

by Hanumath Prasad

[permalink] [raw]
Subject: [PATCH] mmc: MMC 4.4 DDR support

Add support for Dual Data Rate MMC cards as defined in the 4.4
specification.

Cc: [email protected]
Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Hanumath Prasad <[email protected]>
---
drivers/mmc/card/block.c | 10 +++++++---
drivers/mmc/core/mmc.c | 37 +++++++++++++++++++++++++++++++++++--
include/linux/mmc/card.h | 5 +++++
include/linux/mmc/core.h | 1 +
include/linux/mmc/host.h | 4 ++++
include/linux/mmc/mmc.h | 11 +++++++++--
6 files changed, 61 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index cb9fbc8..4eb84eb 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -299,7 +299,8 @@ static int mmc_blk_issue_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;
@@ -569,8 +570,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 89f7a25..1d33503 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -227,6 +227,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;
@@ -444,6 +459,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).
*/
if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
@@ -451,10 +478,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;
}

diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index d02d2c6..7d0aca8 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -44,6 +44,7 @@ struct mmc_ext_csd {
unsigned int sa_timeout; /* Units: 100ns */
unsigned int hs_max_dtr;
unsigned int sectors;
+ unsigned int card_type;
};

struct sd_scr {
@@ -97,6 +98,8 @@ 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 */
+ /* dual data rate 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 */
@@ -129,11 +132,13 @@ struct mmc_card {
#define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT)
#define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY)
#define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED)
+#define mmc_card_ddr_mode(c) ((c)->state & MMC_STATE_HIGHSPEED_DDR)
#define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR)

#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_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)
#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)

static inline int mmc_card_lenient_fn0(const struct mmc_card *c)
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index e4898e9..b31e47a 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -107,6 +107,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;

diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index f65913c..c775290 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -155,6 +155,10 @@ struct mmc_host {
#define MMC_CAP_DISABLE (1 << 7) /* Can the host be disabled */
#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_1_8V_DDR (1 << 10) /* can support */
+ /* DDR mode at 1.8V */
+#define MMC_CAP_1_2V_DDR (1 << 11) /* can support */
+ /* DDR mode at 1.2V */

mmc_pm_flag_t pm_caps; /* supported pm features */

diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 8a49cbf..fc446de 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -268,11 +268,18 @@ 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 */

/*
* MMC_SWITCH access modes
--
1.6.3.3


2010-07-10 05:28:12

by Kyungmin Park

[permalink] [raw]
Subject: Re: [PATCH] mmc: MMC 4.4 DDR support

Hi,

Looks good to me except where's use the MMC_DDR_MODE. why do you set
brq.data.flags |= MMC_DDR_MODE?

Now my SDHCI host don't support eMMC 4.4 but the end of july I can test it.

Thank you,
Kyungmin Park

On Fri, Jul 9, 2010 at 3:59 PM, Hanumath Prasad
<[email protected]> wrote:
> Add support for Dual Data Rate MMC cards as defined in the 4.4
> specification.
>
> Cc: [email protected]
> Acked-by: Linus Walleij <[email protected]>
> Signed-off-by: Hanumath Prasad <[email protected]>
> ---
> ?drivers/mmc/card/block.c | ? 10 +++++++---
> ?drivers/mmc/core/mmc.c ? | ? 37 +++++++++++++++++++++++++++++++++++--
> ?include/linux/mmc/card.h | ? ?5 +++++
> ?include/linux/mmc/core.h | ? ?1 +
> ?include/linux/mmc/host.h | ? ?4 ++++
> ?include/linux/mmc/mmc.h ?| ? 11 +++++++++--
> ?6 files changed, 61 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
> index cb9fbc8..4eb84eb 100644
> --- a/drivers/mmc/card/block.c
> +++ b/drivers/mmc/card/block.c
> @@ -299,7 +299,8 @@ static int mmc_blk_issue_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;
> @@ -569,8 +570,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 89f7a25..1d33503 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -227,6 +227,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;
> @@ -444,6 +459,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).
> ? ? ? ? */
> ? ? ? ?if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
> @@ -451,10 +478,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;
> ? ? ? ? ? ? ? ?}
>
> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
> index d02d2c6..7d0aca8 100644
> --- a/include/linux/mmc/card.h
> +++ b/include/linux/mmc/card.h
> @@ -44,6 +44,7 @@ struct mmc_ext_csd {
> ? ? ? ?unsigned int ? ? ? ? ? ?sa_timeout; ? ? ? ? ? ? /* Units: 100ns */
> ? ? ? ?unsigned int ? ? ? ? ? ?hs_max_dtr;
> ? ? ? ?unsigned int ? ? ? ? ? ?sectors;
> + ? ? ? unsigned int ? ? ? ? ? ?card_type;
> ?};
>
> ?struct sd_scr {
> @@ -97,6 +98,8 @@ 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 */
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* dual data rate 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 */
> @@ -129,11 +132,13 @@ struct mmc_card {
> ?#define mmc_card_present(c) ? ?((c)->state & MMC_STATE_PRESENT)
> ?#define mmc_card_readonly(c) ? ((c)->state & MMC_STATE_READONLY)
> ?#define mmc_card_highspeed(c) ?((c)->state & MMC_STATE_HIGHSPEED)
> +#define mmc_card_ddr_mode(c) ? ((c)->state & MMC_STATE_HIGHSPEED_DDR)
> ?#define mmc_card_blockaddr(c) ?((c)->state & MMC_STATE_BLOCKADDR)
>
> ?#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_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)
> ?#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
>
> ?static inline int mmc_card_lenient_fn0(const struct mmc_card *c)
> diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
> index e4898e9..b31e47a 100644
> --- a/include/linux/mmc/core.h
> +++ b/include/linux/mmc/core.h
> @@ -107,6 +107,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;
>
> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> index f65913c..c775290 100644
> --- a/include/linux/mmc/host.h
> +++ b/include/linux/mmc/host.h
> @@ -155,6 +155,10 @@ struct mmc_host {
> ?#define MMC_CAP_DISABLE ? ? ? ? ? ? ? ?(1 << 7) ? ? ? ?/* Can the host be disabled */
> ?#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_1_8V_DDR ? ? ? ?(1 << 10) ? ? ? /* can support */
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* DDR mode at 1.8V */
> +#define MMC_CAP_1_2V_DDR ? ? ? ?(1 << 11) ? ? ? /* can support */
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* DDR mode at 1.2V */
>
> ? ? ? ?mmc_pm_flag_t ? ? ? ? ? pm_caps; ? ? ? ?/* supported pm features */
>
> diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
> index 8a49cbf..fc446de 100644
> --- a/include/linux/mmc/mmc.h
> +++ b/include/linux/mmc/mmc.h
> @@ -268,11 +268,18 @@ 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 */
>
> ?/*
> ?* MMC_SWITCH access modes
> --
> 1.6.3.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to [email protected]
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>

2010-07-10 05:29:53

by Kyungmin Park

[permalink] [raw]
Subject: Re: [PATCH] mmc: MMC 4.4 DDR support

On Sat, Jul 10, 2010 at 2:28 PM, Kyungmin Park <[email protected]> wrote:
> Hi,
>
> Looks good to me except where's use the MMC_DDR_MODE. why do you set
> brq.data.flags |= MMC_DDR_MODE?
>
> Now my SDHCI host don't support eMMC 4.4 but the end of july I can test it.
Fixing eMMC 4.4 means DDR features at host.
>
> Thank you,
> Kyungmin Park
>
> On Fri, Jul 9, 2010 at 3:59 PM, Hanumath Prasad
> <[email protected]> wrote:
>> Add support for Dual Data Rate MMC cards as defined in the 4.4
>> specification.
>>
>> Cc: [email protected]
>> Acked-by: Linus Walleij <[email protected]>
>> Signed-off-by: Hanumath Prasad <[email protected]>
>> ---
>> ?drivers/mmc/card/block.c | ? 10 +++++++---
>> ?drivers/mmc/core/mmc.c ? | ? 37 +++++++++++++++++++++++++++++++++++--
>> ?include/linux/mmc/card.h | ? ?5 +++++
>> ?include/linux/mmc/core.h | ? ?1 +
>> ?include/linux/mmc/host.h | ? ?4 ++++
>> ?include/linux/mmc/mmc.h ?| ? 11 +++++++++--
>> ?6 files changed, 61 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
>> index cb9fbc8..4eb84eb 100644
>> --- a/drivers/mmc/card/block.c
>> +++ b/drivers/mmc/card/block.c
>> @@ -299,7 +299,8 @@ static int mmc_blk_issue_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;
>> @@ -569,8 +570,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 89f7a25..1d33503 100644
>> --- a/drivers/mmc/core/mmc.c
>> +++ b/drivers/mmc/core/mmc.c
>> @@ -227,6 +227,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;
>> @@ -444,6 +459,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).
>> ? ? ? ? */
>> ? ? ? ?if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
>> @@ -451,10 +478,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;
>> ? ? ? ? ? ? ? ?}
>>
>> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
>> index d02d2c6..7d0aca8 100644
>> --- a/include/linux/mmc/card.h
>> +++ b/include/linux/mmc/card.h
>> @@ -44,6 +44,7 @@ struct mmc_ext_csd {
>> ? ? ? ?unsigned int ? ? ? ? ? ?sa_timeout; ? ? ? ? ? ? /* Units: 100ns */
>> ? ? ? ?unsigned int ? ? ? ? ? ?hs_max_dtr;
>> ? ? ? ?unsigned int ? ? ? ? ? ?sectors;
>> + ? ? ? unsigned int ? ? ? ? ? ?card_type;
>> ?};
>>
>> ?struct sd_scr {
>> @@ -97,6 +98,8 @@ 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 */
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* dual data rate 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 */
>> @@ -129,11 +132,13 @@ struct mmc_card {
>> ?#define mmc_card_present(c) ? ?((c)->state & MMC_STATE_PRESENT)
>> ?#define mmc_card_readonly(c) ? ((c)->state & MMC_STATE_READONLY)
>> ?#define mmc_card_highspeed(c) ?((c)->state & MMC_STATE_HIGHSPEED)
>> +#define mmc_card_ddr_mode(c) ? ((c)->state & MMC_STATE_HIGHSPEED_DDR)
>> ?#define mmc_card_blockaddr(c) ?((c)->state & MMC_STATE_BLOCKADDR)
>>
>> ?#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_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)
>> ?#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
>>
>> ?static inline int mmc_card_lenient_fn0(const struct mmc_card *c)
>> diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
>> index e4898e9..b31e47a 100644
>> --- a/include/linux/mmc/core.h
>> +++ b/include/linux/mmc/core.h
>> @@ -107,6 +107,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;
>>
>> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
>> index f65913c..c775290 100644
>> --- a/include/linux/mmc/host.h
>> +++ b/include/linux/mmc/host.h
>> @@ -155,6 +155,10 @@ struct mmc_host {
>> ?#define MMC_CAP_DISABLE ? ? ? ? ? ? ? ?(1 << 7) ? ? ? ?/* Can the host be disabled */
>> ?#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_1_8V_DDR ? ? ? ?(1 << 10) ? ? ? /* can support */
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* DDR mode at 1.8V */
>> +#define MMC_CAP_1_2V_DDR ? ? ? ?(1 << 11) ? ? ? /* can support */
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* DDR mode at 1.2V */
>>
>> ? ? ? ?mmc_pm_flag_t ? ? ? ? ? pm_caps; ? ? ? ?/* supported pm features */
>>
>> diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
>> index 8a49cbf..fc446de 100644
>> --- a/include/linux/mmc/mmc.h
>> +++ b/include/linux/mmc/mmc.h
>> @@ -268,11 +268,18 @@ 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 */
>>
>> ?/*
>> ?* MMC_SWITCH access modes
>> --
>> 1.6.3.3
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>> the body of a message to [email protected]
>> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>>
>

2010-07-13 01:14:53

by Kyungmin Park

[permalink] [raw]
Subject: Re: [PATCH] mmc: MMC 4.4 DDR support

On Sat, Jul 10, 2010 at 2:40 PM, P.Hanumath PRASAD
<[email protected]> wrote:
> Hi,
>
> The MMC_DDR_MODE is the flag set in case if the device is set to DDR mode. And this flag is for the host to enable the DDR

Then where can I see your host drivers? I hope to see also.

I wonder if we use the DDR mode, then I first set the DDR mode at both
MMC and host. then no need to send DDR_MODE support for each request.
doesn't it?

Thank you,
Kyungmin Park

>
> Mode for the controller before doing any data transfers in DDR mode.
>
> Thanks & Regards,
> Hanumath
>
> -----Original Message-----
> From: [email protected] [mailto:[email protected]] On Behalf Of Kyungmin Park
> Sent: Saturday, July 10, 2010 10:58 AM
> To: P.Hanumath PRASAD
> Cc: [email protected]; STEricsson_nomadik_linux; Linus WALLEIJ; [email protected]
> Subject: Re: [PATCH] mmc: MMC 4.4 DDR support
>
> Hi,
>
> Looks good to me except where's use the MMC_DDR_MODE. why do you set
> brq.data.flags |= MMC_DDR_MODE?
>
> Now my SDHCI host don't support eMMC 4.4 but the end of july I can test it.
>
> Thank you,
> Kyungmin Park
>
> On Fri, Jul 9, 2010 at 3:59 PM, Hanumath Prasad
> <[email protected]> wrote:
>> Add support for Dual Data Rate MMC cards as defined in the 4.4
>> specification.
>>
>> Cc: [email protected]
>> Acked-by: Linus Walleij <[email protected]>
>> Signed-off-by: Hanumath Prasad <[email protected]>
>> ---
>> ?drivers/mmc/card/block.c | ? 10 +++++++---
>> ?drivers/mmc/core/mmc.c ? | ? 37 +++++++++++++++++++++++++++++++++++--
>> ?include/linux/mmc/card.h | ? ?5 +++++
>> ?include/linux/mmc/core.h | ? ?1 +
>> ?include/linux/mmc/host.h | ? ?4 ++++
>> ?include/linux/mmc/mmc.h ?| ? 11 +++++++++--
>> ?6 files changed, 61 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
>> index cb9fbc8..4eb84eb 100644
>> --- a/drivers/mmc/card/block.c
>> +++ b/drivers/mmc/card/block.c
>> @@ -299,7 +299,8 @@ static int mmc_blk_issue_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;
>> @@ -569,8 +570,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 89f7a25..1d33503 100644
>> --- a/drivers/mmc/core/mmc.c
>> +++ b/drivers/mmc/core/mmc.c
>> @@ -227,6 +227,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;
>> @@ -444,6 +459,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).
>> ? ? ? ? */
>> ? ? ? ?if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
>> @@ -451,10 +478,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;
>> ? ? ? ? ? ? ? ?}
>>
>> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
>> index d02d2c6..7d0aca8 100644
>> --- a/include/linux/mmc/card.h
>> +++ b/include/linux/mmc/card.h
>> @@ -44,6 +44,7 @@ struct mmc_ext_csd {
>> ? ? ? ?unsigned int ? ? ? ? ? ?sa_timeout; ? ? ? ? ? ? /* Units: 100ns */
>> ? ? ? ?unsigned int ? ? ? ? ? ?hs_max_dtr;
>> ? ? ? ?unsigned int ? ? ? ? ? ?sectors;
>> + ? ? ? unsigned int ? ? ? ? ? ?card_type;
>> ?};
>>
>> ?struct sd_scr {
>> @@ -97,6 +98,8 @@ 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 */
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* dual data rate 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 */
>> @@ -129,11 +132,13 @@ struct mmc_card {
>> ?#define mmc_card_present(c) ? ?((c)->state & MMC_STATE_PRESENT)
>> ?#define mmc_card_readonly(c) ? ((c)->state & MMC_STATE_READONLY)
>> ?#define mmc_card_highspeed(c) ?((c)->state & MMC_STATE_HIGHSPEED)
>> +#define mmc_card_ddr_mode(c) ? ((c)->state & MMC_STATE_HIGHSPEED_DDR)
>> ?#define mmc_card_blockaddr(c) ?((c)->state & MMC_STATE_BLOCKADDR)
>>
>> ?#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_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)
>> ?#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
>>
>> ?static inline int mmc_card_lenient_fn0(const struct mmc_card *c)
>> diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
>> index e4898e9..b31e47a 100644
>> --- a/include/linux/mmc/core.h
>> +++ b/include/linux/mmc/core.h
>> @@ -107,6 +107,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;
>>
>> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
>> index f65913c..c775290 100644
>> --- a/include/linux/mmc/host.h
>> +++ b/include/linux/mmc/host.h
>> @@ -155,6 +155,10 @@ struct mmc_host {
>> ?#define MMC_CAP_DISABLE ? ? ? ? ? ? ? ?(1 << 7) ? ? ? ?/* Can the host be disabled */
>> ?#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_1_8V_DDR ? ? ? ?(1 << 10) ? ? ? /* can support */
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* DDR mode at 1.8V */
>> +#define MMC_CAP_1_2V_DDR ? ? ? ?(1 << 11) ? ? ? /* can support */
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* DDR mode at 1.2V */
>>
>> ? ? ? ?mmc_pm_flag_t ? ? ? ? ? pm_caps; ? ? ? ?/* supported pm features */
>>
>> diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
>> index 8a49cbf..fc446de 100644
>> --- a/include/linux/mmc/mmc.h
>> +++ b/include/linux/mmc/mmc.h
>> @@ -268,11 +268,18 @@ 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 */
>>
>> ?/*
>> ?* MMC_SWITCH access modes
>> --
>> 1.6.3.3
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>> the body of a message to [email protected]
>> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>>
>

2010-08-21 22:30:37

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH] mmc: MMC 4.4 DDR support

2010/7/9 Hanumath Prasad <[email protected]>:

> Add support for Dual Data Rate MMC cards as defined in the 4.4
> specification.

Hm is there some problem with this patch or has the processing
of it simply stalled? When I read the thread I cannot see Hanumaths
answers on the list but it looks mainly like the patch is OK and
there is some chit-chat.

Can it be picked up? Everyone is going to need DDR MMC
for their eMMCs soon-ish.

Hanumath can you resend your comments to the list since they
seem to be lost.

Yours,
Linus Walleij

2010-08-21 22:46:17

by Chris Ball

[permalink] [raw]
Subject: Re: [PATCH] mmc: MMC 4.4 DDR support

Hi,

> Hm is there some problem with this patch or has the processing of
> it simply stalled? When I read the thread I cannot see Hanumaths
> answers on the list but it looks mainly like the patch is OK and
> there is some chit-chat.
>
> Can it be picked up? Everyone is going to need DDR MMC for their
> eMMCs soon-ish.

I'd like to dedicate more time to mmc/. Do you think it'd be useful
for me to catch all the patches sent to linux-mmc@ into a public Git
tree, and periodically report on what went upstream via akpm and
what's still waiting?

Of course, the tree could also be used for testing. Maybe even
automated testing, which I'm also interested in.

Thanks,

- Chris.
--
Chris Ball <[email protected]>
One Laptop Per Child

2010-08-23 07:21:51

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH] mmc: MMC 4.4 DDR support

2010/8/22 Chris Ball <[email protected]>:

> I'd like to dedicate more time to mmc/. ?Do you think it'd be useful
> for me to catch all the patches sent to linux-mmc@ into a public Git
> tree, and periodically report on what went upstream via akpm and
> what's still waiting?

That sounds very close to getting it participate in linux-next.

Which in turn would make it convenient for you to issue pull
requests to Linus (Torvalds) directly.

Which would make you the MMC subsystem maintainer...

So why not :-)

Yours,
Linus Walleij

2010-08-23 20:48:34

by Matt Fleming

[permalink] [raw]
Subject: Re: [PATCH] mmc: MMC 4.4 DDR support

On Sat, Aug 21, 2010 at 06:37:45PM -0400, Chris Ball wrote:
> Hi,
>
> > Hm is there some problem with this patch or has the processing of
> > it simply stalled? When I read the thread I cannot see Hanumaths
> > answers on the list but it looks mainly like the patch is OK and
> > there is some chit-chat.
> >
> > Can it be picked up? Everyone is going to need DDR MMC for their
> > eMMCs soon-ish.
>
> I'd like to dedicate more time to mmc/. Do you think it'd be useful
> for me to catch all the patches sent to linux-mmc@ into a public Git
> tree, and periodically report on what went upstream via akpm and
> what's still waiting?

It's possible Andrew has a reason that hasn't been picked up yet.

Maybe what we really need is to get patchwork setup for the linux-mmc
list? Other subsystem maintainers swear by it. That way, it'd be much
harder for patches to go unnoticed.

2010-08-23 21:28:41

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH] mmc: MMC 4.4 DDR support

On Mon, 23 Aug 2010 21:48:29 +0100
Matt Fleming <[email protected]> wrote:

> On Sat, Aug 21, 2010 at 06:37:45PM -0400, Chris Ball wrote:
> > Hi,
> >
> > > Hm is there some problem with this patch or has the processing of
> > > it simply stalled? When I read the thread I cannot see Hanumaths
> > > answers on the list but it looks mainly like the patch is OK and
> > > there is some chit-chat.
> > >
> > > Can it be picked up? Everyone is going to need DDR MMC for their
> > > eMMCs soon-ish.
> >
> > I'd like to dedicate more time to mmc/. Do you think it'd be useful
> > for me to catch all the patches sent to linux-mmc@ into a public Git
> > tree, and periodically report on what went upstream via akpm and
> > what's still waiting?
>
> It's possible Andrew has a reason that hasn't been picked up yet.
>

Kyungmin Park's questions didn't seem adequately answered and the
discussion kind of died.

I updated the patch and merged it, but I'd like the outstanding
question(s) resolved. ie: why do we add MMC_DDR_MODE, set it in
brq.data.flags and then never use it?

2010-08-24 10:31:11

by Adrian Hunter

[permalink] [raw]
Subject: Re: [PATCH] mmc: MMC 4.4 DDR support

Andrew Morton wrote:
> On Mon, 23 Aug 2010 21:48:29 +0100
> Matt Fleming <[email protected]> wrote:
>
>> On Sat, Aug 21, 2010 at 06:37:45PM -0400, Chris Ball wrote:
>>> Hi,
>>>
>>> > Hm is there some problem with this patch or has the processing of
>>> > it simply stalled? When I read the thread I cannot see Hanumaths
>>> > answers on the list but it looks mainly like the patch is OK and
>>> > there is some chit-chat.
>>> >
>>> > Can it be picked up? Everyone is going to need DDR MMC for their
>>> > eMMCs soon-ish.
>>>
>>> I'd like to dedicate more time to mmc/. Do you think it'd be useful
>>> for me to catch all the patches sent to linux-mmc@ into a public Git
>>> tree, and periodically report on what went upstream via akpm and
>>> what's still waiting?
>> It's possible Andrew has a reason that hasn't been picked up yet.
>>
>
> Kyungmin Park's questions didn't seem adequately answered and the
> discussion kind of died.
>
> I updated the patch and merged it, but I'd like the outstanding
> question(s) resolved. ie: why do we add MMC_DDR_MODE, set it in
> brq.data.flags and then never use it?

I am not able to test DDR mode but it look to me that the patch
should be changed. Here is a fix:

>From 8253aa16b1ab15974a3ba8f33566fe8e2cca29e6 Mon Sep 17 00:00:00 2001
From: Adrian Hunter <[email protected]>
Date: Tue, 24 Aug 2010 13:20:26 +0300
Subject: [PATCH] mmc: Fix Dual Data Rate (DDR) support

The DDR support patch needs the following fixes:

- The block driver does not need to know about DDR, any more
than it needs to know about bus width.
- Not only the card must be switched to DDR mode. The host
controller must also be configured, which is done through
the 'set_ios()' function.
- Do not set the DDR mode state until after the switch command
is successful.
- Setting block length is not supported in DDR mode. Make that
a core function and change the other place it is used (mmc_test)
also.

Signed-off-by: Adrian Hunter <[email protected]>
---
drivers/mmc/card/block.c | 19 +++----------------
drivers/mmc/card/mmc_test.c | 12 +-----------
drivers/mmc/core/bus.c | 6 ++++--
drivers/mmc/core/core.c | 28 ++++++++++++++++++++++++++--
drivers/mmc/core/core.h | 1 +
drivers/mmc/core/mmc.c | 21 +++++++++++----------
include/linux/mmc/core.h | 3 ++-
include/linux/mmc/host.h | 5 +++++
8 files changed, 53 insertions(+), 42 deletions(-)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 24f39d7..1ec93bb 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -373,8 +373,6 @@ 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;
@@ -652,26 +650,15 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
static int
mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
{
- struct mmc_command cmd;
int err;

- /*
- * 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);
- cmd.opcode = MMC_SET_BLOCKLEN;
- cmd.arg = 512;
- cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
- err = mmc_wait_for_cmd(card->host, &cmd, 5);
+ err = mmc_set_blocklen(card, 512);
mmc_release_host(card->host);

if (err) {
- printk(KERN_ERR "%s: unable to set block size to %d: %d\n",
- md->disk->disk_name, cmd.arg, err);
+ printk(KERN_ERR "%s: unable to set block size to 512: %d\n",
+ md->disk->disk_name, err);
return -EINVAL;
}

diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index 5dd8576..f80b759 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -100,17 +100,7 @@ struct mmc_test_card {
*/
static int mmc_test_set_blksize(struct mmc_test_card *test, unsigned size)
{
- struct mmc_command cmd;
- int ret;
-
- cmd.opcode = MMC_SET_BLOCKLEN;
- cmd.arg = size;
- cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
- ret = mmc_wait_for_cmd(test->card->host, &cmd, 0);
- if (ret)
- return ret;
-
- return 0;
+ return mmc_set_blocklen(test->card, size);
}

/*
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 7cd9749..dc36f39 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -254,14 +254,16 @@ int mmc_add_card(struct mmc_card *card)
}

if (mmc_host_is_spi(card->host)) {
- printk(KERN_INFO "%s: new %s%s card on SPI\n",
+ printk(KERN_INFO "%s: new %s%s%s card on SPI\n",
mmc_hostname(card->host),
mmc_card_highspeed(card) ? "high speed " : "",
+ mmc_card_ddr_mode(card) ? "DDR " : "",
type);
} else {
- printk(KERN_INFO "%s: new %s%s card at address %04x\n",
+ printk(KERN_INFO "%s: new %s%s%s card at address %04x\n",
mmc_hostname(card->host),
mmc_card_highspeed(card) ? "high speed " : "",
+ mmc_card_ddr_mode(card) ? "DDR " : "",
type, card->rca);
}

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 5db49b1..8519480 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -650,14 +650,23 @@ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode)
}

/*
- * Change data bus width of a host.
+ * Change data bus width and DDR mode of a host.
*/
-void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
+void mmc_set_bus_width_ddr(struct mmc_host *host, unsigned int width, int ddr)
{
host->ios.bus_width = width;
+ host->ios.ddr = ddr ? MMC_DDR_MODE : MMC_SDR_MODE;
mmc_set_ios(host);
}

+/*
+ * Change data bus width of a host.
+ */
+void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
+{
+ mmc_set_bus_width_ddr(host, width, 0);
+}
+
/**
* mmc_vdd_to_ocrbitnum - Convert a voltage to the OCR bit number
* @vdd: voltage (mV)
@@ -1397,6 +1406,21 @@ int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from,
}
EXPORT_SYMBOL(mmc_erase_group_aligned);

+int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
+{
+ struct mmc_command cmd;
+
+ if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card))
+ return 0;
+
+ memset(&cmd, 0, sizeof(struct mmc_command));
+ cmd.opcode = MMC_SET_BLOCKLEN;
+ cmd.arg = blocklen;
+ cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
+ return mmc_wait_for_cmd(card->host, &cmd, 5);
+}
+EXPORT_SYMBOL(mmc_set_blocklen);
+
void mmc_rescan(struct work_struct *work)
{
struct mmc_host *host =
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 9d9eef5..68150c9 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -35,6 +35,7 @@ void mmc_set_chip_select(struct mmc_host *host, int mode);
void mmc_set_clock(struct mmc_host *host, unsigned int hz);
void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode);
void mmc_set_bus_width(struct mmc_host *host, unsigned int width);
+void mmc_set_bus_width_ddr(struct mmc_host *host, unsigned int width, int ddr);
u32 mmc_select_voltage(struct mmc_host *host, u32 ocr);
void mmc_set_timing(struct mmc_host *host, unsigned int timing);

diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index dcfc921..998c0d3 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -375,7 +375,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
struct mmc_card *oldcard)
{
struct mmc_card *card;
- int err;
+ int err, ddr = 0;
u32 cid[4];
unsigned int max_dtr;

@@ -518,32 +518,32 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
mmc_set_clock(host, max_dtr);

/*
- * Activate DDR50 mode (if supported).
+ * Indicate DDR 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);
+ ddr = 1;
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);
+ ddr = 1;
}

/*
- * Activate wide bus (if supported).
+ * Activate wide bus and DDR (if supported).
*/
if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
(host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
unsigned ext_csd_bit, bus_width;

if (host->caps & MMC_CAP_8_BIT_DATA) {
- if (mmc_card_ddr_mode(card))
+ if (ddr)
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 {
- if (mmc_card_ddr_mode(card))
+ if (ddr)
ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_4;
else
ext_csd_bit = EXT_CSD_BUS_WIDTH_4;
@@ -557,12 +557,13 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
goto free_card;

if (err) {
- printk(KERN_WARNING "%s: switch to bus width %d "
+ printk(KERN_WARNING "%s: switch to bus width %d ddr %d "
"failed\n", mmc_hostname(card->host),
- 1 << bus_width);
+ 1 << bus_width, ddr);
err = 0;
} else {
- mmc_set_bus_width(card->host, bus_width);
+ mmc_card_set_ddr_mode(card);
+ mmc_set_bus_width_ddr(card->host, bus_width, ddr);
}
}

diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 17bb4c2..64e013f 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -109,7 +109,6 @@ 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;

@@ -154,6 +153,8 @@ extern int mmc_can_secure_erase_trim(struct mmc_card *card);
extern int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from,
unsigned int nr);

+extern int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen);
+
extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *);
extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int);

diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 09dbb90..aa1a747 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -50,6 +50,11 @@ struct mmc_ios {
#define MMC_TIMING_LEGACY 0
#define MMC_TIMING_MMC_HS 1
#define MMC_TIMING_SD_HS 2
+
+ unsigned char ddr; /* dual data rate used */
+
+#define MMC_SDR_MODE 0
+#define MMC_DDR_MODE 1
};

struct mmc_host_ops {
--
1.6.3.3