diff options
author | Hanumath Prasad <hanumath.prasad@stericsson.com> | 2010-09-30 17:37:23 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2010-10-23 09:11:16 -0400 |
commit | dfc13e8402c75e7c2e0a52e123c0500a3259866b (patch) | |
tree | 29a0f5daeb300da027bb0ed9c042fffd214b078f | |
parent | 99fc5131018cbdc3cf42ce09fb394a4e8b053c74 (diff) |
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>
-rw-r--r-- | drivers/mmc/card/block.c | 10 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 37 | ||||
-rw-r--r-- | include/linux/mmc/card.h | 4 | ||||
-rw-r--r-- | include/linux/mmc/core.h | 1 | ||||
-rw-r--r-- | include/linux/mmc/host.h | 4 | ||||
-rw-r--r-- | include/linux/mmc/mmc.h | 10 |
6 files changed, 60 insertions, 6 deletions
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) | |||
373 | readcmd = MMC_READ_SINGLE_BLOCK; | 373 | readcmd = MMC_READ_SINGLE_BLOCK; |
374 | writecmd = MMC_WRITE_BLOCK; | 374 | writecmd = MMC_WRITE_BLOCK; |
375 | } | 375 | } |
376 | 376 | if (mmc_card_ddr_mode(card)) | |
377 | brq.data.flags |= MMC_DDR_MODE; | ||
377 | if (rq_data_dir(req) == READ) { | 378 | if (rq_data_dir(req) == READ) { |
378 | brq.cmd.opcode = readcmd; | 379 | brq.cmd.opcode = readcmd; |
379 | brq.data.flags |= MMC_DATA_READ; | 380 | brq.data.flags |= MMC_DATA_READ; |
@@ -655,8 +656,11 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) | |||
655 | struct mmc_command cmd; | 656 | struct mmc_command cmd; |
656 | int err; | 657 | int err; |
657 | 658 | ||
658 | /* Block-addressed cards ignore MMC_SET_BLOCKLEN. */ | 659 | /* |
659 | if (mmc_card_blockaddr(card)) | 660 | * Block-addressed and ddr mode supported cards |
661 | * ignore MMC_SET_BLOCKLEN. | ||
662 | */ | ||
663 | if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card)) | ||
660 | return 0; | 664 | return 0; |
661 | 665 | ||
662 | mmc_claim_host(card->host); | 666 | 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) | |||
258 | } | 258 | } |
259 | 259 | ||
260 | switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) { | 260 | switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) { |
261 | case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52 | | ||
262 | EXT_CSD_CARD_TYPE_26: | ||
263 | card->ext_csd.hs_max_dtr = 52000000; | ||
264 | card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_52; | ||
265 | break; | ||
266 | case EXT_CSD_CARD_TYPE_DDR_1_2V | EXT_CSD_CARD_TYPE_52 | | ||
267 | EXT_CSD_CARD_TYPE_26: | ||
268 | card->ext_csd.hs_max_dtr = 52000000; | ||
269 | card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_2V; | ||
270 | break; | ||
271 | case EXT_CSD_CARD_TYPE_DDR_1_8V | EXT_CSD_CARD_TYPE_52 | | ||
272 | EXT_CSD_CARD_TYPE_26: | ||
273 | card->ext_csd.hs_max_dtr = 52000000; | ||
274 | card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_8V; | ||
275 | break; | ||
261 | case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: | 276 | case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: |
262 | card->ext_csd.hs_max_dtr = 52000000; | 277 | card->ext_csd.hs_max_dtr = 52000000; |
263 | break; | 278 | break; |
@@ -503,6 +518,18 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
503 | mmc_set_clock(host, max_dtr); | 518 | mmc_set_clock(host, max_dtr); |
504 | 519 | ||
505 | /* | 520 | /* |
521 | * Activate DDR50 mode (if supported). | ||
522 | */ | ||
523 | if (mmc_card_highspeed(card)) { | ||
524 | if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) | ||
525 | && (host->caps & (MMC_CAP_1_8V_DDR))) | ||
526 | mmc_card_set_ddr_mode(card); | ||
527 | else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) | ||
528 | && (host->caps & (MMC_CAP_1_2V_DDR))) | ||
529 | mmc_card_set_ddr_mode(card); | ||
530 | } | ||
531 | |||
532 | /* | ||
506 | * Activate wide bus (if supported). | 533 | * Activate wide bus (if supported). |
507 | */ | 534 | */ |
508 | if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) && | 535 | if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) && |
@@ -510,10 +537,16 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
510 | unsigned ext_csd_bit, bus_width; | 537 | unsigned ext_csd_bit, bus_width; |
511 | 538 | ||
512 | if (host->caps & MMC_CAP_8_BIT_DATA) { | 539 | if (host->caps & MMC_CAP_8_BIT_DATA) { |
513 | ext_csd_bit = EXT_CSD_BUS_WIDTH_8; | 540 | if (mmc_card_ddr_mode(card)) |
541 | ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_8; | ||
542 | else | ||
543 | ext_csd_bit = EXT_CSD_BUS_WIDTH_8; | ||
514 | bus_width = MMC_BUS_WIDTH_8; | 544 | bus_width = MMC_BUS_WIDTH_8; |
515 | } else { | 545 | } else { |
516 | ext_csd_bit = EXT_CSD_BUS_WIDTH_4; | 546 | if (mmc_card_ddr_mode(card)) |
547 | ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_4; | ||
548 | else | ||
549 | ext_csd_bit = EXT_CSD_BUS_WIDTH_4; | ||
517 | bus_width = MMC_BUS_WIDTH_4; | 550 | bus_width = MMC_BUS_WIDTH_4; |
518 | } | 551 | } |
519 | 552 | ||
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 7bd49234cd88..8ce082781ccb 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h | |||
@@ -48,6 +48,7 @@ struct mmc_ext_csd { | |||
48 | unsigned int sa_timeout; /* Units: 100ns */ | 48 | unsigned int sa_timeout; /* Units: 100ns */ |
49 | unsigned int hs_max_dtr; | 49 | unsigned int hs_max_dtr; |
50 | unsigned int sectors; | 50 | unsigned int sectors; |
51 | unsigned int card_type; | ||
51 | unsigned int hc_erase_size; /* In sectors */ | 52 | unsigned int hc_erase_size; /* In sectors */ |
52 | unsigned int hc_erase_timeout; /* In milliseconds */ | 53 | unsigned int hc_erase_timeout; /* In milliseconds */ |
53 | unsigned int sec_trim_mult; /* Secure trim multiplier */ | 54 | unsigned int sec_trim_mult; /* Secure trim multiplier */ |
@@ -113,6 +114,7 @@ struct mmc_card { | |||
113 | #define MMC_STATE_READONLY (1<<1) /* card is read-only */ | 114 | #define MMC_STATE_READONLY (1<<1) /* card is read-only */ |
114 | #define MMC_STATE_HIGHSPEED (1<<2) /* card is in high speed mode */ | 115 | #define MMC_STATE_HIGHSPEED (1<<2) /* card is in high speed mode */ |
115 | #define MMC_STATE_BLOCKADDR (1<<3) /* card uses block-addressing */ | 116 | #define MMC_STATE_BLOCKADDR (1<<3) /* card uses block-addressing */ |
117 | #define MMC_STATE_HIGHSPEED_DDR (1<<4) /* card is in high speed mode */ | ||
116 | unsigned int quirks; /* card quirks */ | 118 | unsigned int quirks; /* card quirks */ |
117 | #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */ | 119 | #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */ |
118 | #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */ | 120 | #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */ |
@@ -154,11 +156,13 @@ struct mmc_card { | |||
154 | #define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY) | 156 | #define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY) |
155 | #define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED) | 157 | #define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED) |
156 | #define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR) | 158 | #define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR) |
159 | #define mmc_card_ddr_mode(c) ((c)->state & MMC_STATE_HIGHSPEED_DDR) | ||
157 | 160 | ||
158 | #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) | 161 | #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) |
159 | #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) | 162 | #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) |
160 | #define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED) | 163 | #define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED) |
161 | #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR) | 164 | #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR) |
165 | #define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR) | ||
162 | 166 | ||
163 | static inline int mmc_card_lenient_fn0(const struct mmc_card *c) | 167 | static inline int mmc_card_lenient_fn0(const struct mmc_card *c) |
164 | { | 168 | { |
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index 7429033acb66..d0fbcacab52c 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h | |||
@@ -109,6 +109,7 @@ struct mmc_data { | |||
109 | #define MMC_DATA_WRITE (1 << 8) | 109 | #define MMC_DATA_WRITE (1 << 8) |
110 | #define MMC_DATA_READ (1 << 9) | 110 | #define MMC_DATA_READ (1 << 9) |
111 | #define MMC_DATA_STREAM (1 << 10) | 111 | #define MMC_DATA_STREAM (1 << 10) |
112 | #define MMC_DDR_MODE (1 << 11) | ||
112 | 113 | ||
113 | unsigned int bytes_xfered; | 114 | unsigned int bytes_xfered; |
114 | 115 | ||
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index ccac56ae1286..6711eb8715ba 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h | |||
@@ -158,6 +158,10 @@ struct mmc_host { | |||
158 | #define MMC_CAP_NONREMOVABLE (1 << 8) /* Nonremovable e.g. eMMC */ | 158 | #define MMC_CAP_NONREMOVABLE (1 << 8) /* Nonremovable e.g. eMMC */ |
159 | #define MMC_CAP_WAIT_WHILE_BUSY (1 << 9) /* Waits while card is busy */ | 159 | #define MMC_CAP_WAIT_WHILE_BUSY (1 << 9) /* Waits while card is busy */ |
160 | #define MMC_CAP_ERASE (1 << 10) /* Allow erase/trim commands */ | 160 | #define MMC_CAP_ERASE (1 << 10) /* Allow erase/trim commands */ |
161 | #define MMC_CAP_1_8V_DDR (1 << 11) /* can support */ | ||
162 | /* DDR mode at 1.8V */ | ||
163 | #define MMC_CAP_1_2V_DDR (1 << 12) /* can support */ | ||
164 | /* DDR mode at 1.2V */ | ||
161 | 165 | ||
162 | mmc_pm_flag_t pm_caps; /* supported pm features */ | 166 | mmc_pm_flag_t pm_caps; /* supported pm features */ |
163 | 167 | ||
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index dd11ae51fb68..956fbd877692 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h | |||
@@ -277,11 +277,19 @@ struct _mmc_csd { | |||
277 | 277 | ||
278 | #define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */ | 278 | #define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */ |
279 | #define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */ | 279 | #define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */ |
280 | #define EXT_CSD_CARD_TYPE_MASK 0x3 /* Mask out reserved and DDR bits */ | 280 | #define EXT_CSD_CARD_TYPE_MASK 0xF /* Mask out reserved bits */ |
281 | #define EXT_CSD_CARD_TYPE_DDR_1_8V (1<<2) /* Card can run at 52MHz */ | ||
282 | /* DDR mode @1.8V or 3V I/O */ | ||
283 | #define EXT_CSD_CARD_TYPE_DDR_1_2V (1<<3) /* Card can run at 52MHz */ | ||
284 | /* DDR mode @1.2V I/O */ | ||
285 | #define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \ | ||
286 | | EXT_CSD_CARD_TYPE_DDR_1_2V) | ||
281 | 287 | ||
282 | #define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */ | 288 | #define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */ |
283 | #define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */ | 289 | #define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */ |
284 | #define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */ | 290 | #define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */ |
291 | #define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */ | ||
292 | #define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */ | ||
285 | 293 | ||
286 | #define EXT_CSD_SEC_ER_EN BIT(0) | 294 | #define EXT_CSD_SEC_ER_EN BIT(0) |
287 | #define EXT_CSD_SEC_BD_BLK_EN BIT(2) | 295 | #define EXT_CSD_SEC_BD_BLK_EN BIT(2) |