diff options
author | Adrian Hunter <adrian.hunter@nokia.com> | 2010-08-24 06:20:26 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2010-10-23 09:11:16 -0400 |
commit | 0f8d8ea64ec7c77ca5beb59534d386fe0235961a (patch) | |
tree | 8d6aebd250897aa33cb166994720497f40a9aaa6 /drivers/mmc/core | |
parent | dfc13e8402c75e7c2e0a52e123c0500a3259866b (diff) |
mmc: Fixes for 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 <adrian.hunter@nokia.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r-- | drivers/mmc/core/bus.c | 6 | ||||
-rw-r--r-- | drivers/mmc/core/core.c | 28 | ||||
-rw-r--r-- | drivers/mmc/core/core.h | 1 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 21 |
4 files changed, 42 insertions, 14 deletions
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index e70bd6641cee..da3c01b214ec 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c | |||
@@ -253,14 +253,16 @@ int mmc_add_card(struct mmc_card *card) | |||
253 | } | 253 | } |
254 | 254 | ||
255 | if (mmc_host_is_spi(card->host)) { | 255 | if (mmc_host_is_spi(card->host)) { |
256 | printk(KERN_INFO "%s: new %s%s card on SPI\n", | 256 | printk(KERN_INFO "%s: new %s%s%s card on SPI\n", |
257 | mmc_hostname(card->host), | 257 | mmc_hostname(card->host), |
258 | mmc_card_highspeed(card) ? "high speed " : "", | 258 | mmc_card_highspeed(card) ? "high speed " : "", |
259 | mmc_card_ddr_mode(card) ? "DDR " : "", | ||
259 | type); | 260 | type); |
260 | } else { | 261 | } else { |
261 | printk(KERN_INFO "%s: new %s%s card at address %04x\n", | 262 | printk(KERN_INFO "%s: new %s%s%s card at address %04x\n", |
262 | mmc_hostname(card->host), | 263 | mmc_hostname(card->host), |
263 | mmc_card_highspeed(card) ? "high speed " : "", | 264 | mmc_card_highspeed(card) ? "high speed " : "", |
265 | mmc_card_ddr_mode(card) ? "DDR " : "", | ||
264 | type, card->rca); | 266 | type, card->rca); |
265 | } | 267 | } |
266 | 268 | ||
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 46029d5c0364..7cb352b3b247 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -651,14 +651,23 @@ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode) | |||
651 | } | 651 | } |
652 | 652 | ||
653 | /* | 653 | /* |
654 | * Change data bus width of a host. | 654 | * Change data bus width and DDR mode of a host. |
655 | */ | 655 | */ |
656 | void mmc_set_bus_width(struct mmc_host *host, unsigned int width) | 656 | void mmc_set_bus_width_ddr(struct mmc_host *host, unsigned int width, int ddr) |
657 | { | 657 | { |
658 | host->ios.bus_width = width; | 658 | host->ios.bus_width = width; |
659 | host->ios.ddr = ddr ? MMC_DDR_MODE : MMC_SDR_MODE; | ||
659 | mmc_set_ios(host); | 660 | mmc_set_ios(host); |
660 | } | 661 | } |
661 | 662 | ||
663 | /* | ||
664 | * Change data bus width of a host. | ||
665 | */ | ||
666 | void mmc_set_bus_width(struct mmc_host *host, unsigned int width) | ||
667 | { | ||
668 | mmc_set_bus_width_ddr(host, width, 0); | ||
669 | } | ||
670 | |||
662 | /** | 671 | /** |
663 | * mmc_vdd_to_ocrbitnum - Convert a voltage to the OCR bit number | 672 | * mmc_vdd_to_ocrbitnum - Convert a voltage to the OCR bit number |
664 | * @vdd: voltage (mV) | 673 | * @vdd: voltage (mV) |
@@ -1399,6 +1408,21 @@ int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from, | |||
1399 | } | 1408 | } |
1400 | EXPORT_SYMBOL(mmc_erase_group_aligned); | 1409 | EXPORT_SYMBOL(mmc_erase_group_aligned); |
1401 | 1410 | ||
1411 | int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen) | ||
1412 | { | ||
1413 | struct mmc_command cmd; | ||
1414 | |||
1415 | if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card)) | ||
1416 | return 0; | ||
1417 | |||
1418 | memset(&cmd, 0, sizeof(struct mmc_command)); | ||
1419 | cmd.opcode = MMC_SET_BLOCKLEN; | ||
1420 | cmd.arg = blocklen; | ||
1421 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; | ||
1422 | return mmc_wait_for_cmd(card->host, &cmd, 5); | ||
1423 | } | ||
1424 | EXPORT_SYMBOL(mmc_set_blocklen); | ||
1425 | |||
1402 | void mmc_rescan(struct work_struct *work) | 1426 | void mmc_rescan(struct work_struct *work) |
1403 | { | 1427 | { |
1404 | struct mmc_host *host = | 1428 | struct mmc_host *host = |
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index a2ca770ca89b..13240d128a69 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); | |||
35 | void mmc_set_clock(struct mmc_host *host, unsigned int hz); | 35 | void mmc_set_clock(struct mmc_host *host, unsigned int hz); |
36 | void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); | 36 | void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); |
37 | void mmc_set_bus_width(struct mmc_host *host, unsigned int width); | 37 | void mmc_set_bus_width(struct mmc_host *host, unsigned int width); |
38 | void mmc_set_bus_width_ddr(struct mmc_host *host, unsigned int width, int ddr); | ||
38 | u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); | 39 | u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); |
39 | void mmc_set_timing(struct mmc_host *host, unsigned int timing); | 40 | void mmc_set_timing(struct mmc_host *host, unsigned int timing); |
40 | 41 | ||
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 66c4a59fee5f..3ea58ce773ff 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, | |||
375 | struct mmc_card *oldcard) | 375 | struct mmc_card *oldcard) |
376 | { | 376 | { |
377 | struct mmc_card *card; | 377 | struct mmc_card *card; |
378 | int err; | 378 | int err, ddr = 0; |
379 | u32 cid[4]; | 379 | u32 cid[4]; |
380 | unsigned int max_dtr; | 380 | unsigned int max_dtr; |
381 | 381 | ||
@@ -518,32 +518,32 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
518 | mmc_set_clock(host, max_dtr); | 518 | mmc_set_clock(host, max_dtr); |
519 | 519 | ||
520 | /* | 520 | /* |
521 | * Activate DDR50 mode (if supported). | 521 | * Indicate DDR mode (if supported). |
522 | */ | 522 | */ |
523 | if (mmc_card_highspeed(card)) { | 523 | if (mmc_card_highspeed(card)) { |
524 | if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) | 524 | if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) |
525 | && (host->caps & (MMC_CAP_1_8V_DDR))) | 525 | && (host->caps & (MMC_CAP_1_8V_DDR))) |
526 | mmc_card_set_ddr_mode(card); | 526 | ddr = 1; |
527 | else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) | 527 | else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) |
528 | && (host->caps & (MMC_CAP_1_2V_DDR))) | 528 | && (host->caps & (MMC_CAP_1_2V_DDR))) |
529 | mmc_card_set_ddr_mode(card); | 529 | ddr = 1; |
530 | } | 530 | } |
531 | 531 | ||
532 | /* | 532 | /* |
533 | * Activate wide bus (if supported). | 533 | * Activate wide bus and DDR (if supported). |
534 | */ | 534 | */ |
535 | if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) && | 535 | if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) && |
536 | (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) { | 536 | (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) { |
537 | unsigned ext_csd_bit, bus_width; | 537 | unsigned ext_csd_bit, bus_width; |
538 | 538 | ||
539 | if (host->caps & MMC_CAP_8_BIT_DATA) { | 539 | if (host->caps & MMC_CAP_8_BIT_DATA) { |
540 | if (mmc_card_ddr_mode(card)) | 540 | if (ddr) |
541 | ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_8; | 541 | ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_8; |
542 | else | 542 | else |
543 | ext_csd_bit = EXT_CSD_BUS_WIDTH_8; | 543 | ext_csd_bit = EXT_CSD_BUS_WIDTH_8; |
544 | bus_width = MMC_BUS_WIDTH_8; | 544 | bus_width = MMC_BUS_WIDTH_8; |
545 | } else { | 545 | } else { |
546 | if (mmc_card_ddr_mode(card)) | 546 | if (ddr) |
547 | ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_4; | 547 | ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_4; |
548 | else | 548 | else |
549 | ext_csd_bit = EXT_CSD_BUS_WIDTH_4; | 549 | ext_csd_bit = EXT_CSD_BUS_WIDTH_4; |
@@ -557,12 +557,13 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
557 | goto free_card; | 557 | goto free_card; |
558 | 558 | ||
559 | if (err) { | 559 | if (err) { |
560 | printk(KERN_WARNING "%s: switch to bus width %d " | 560 | printk(KERN_WARNING "%s: switch to bus width %d ddr %d " |
561 | "failed\n", mmc_hostname(card->host), | 561 | "failed\n", mmc_hostname(card->host), |
562 | 1 << bus_width); | 562 | 1 << bus_width, ddr); |
563 | err = 0; | 563 | err = 0; |
564 | } else { | 564 | } else { |
565 | mmc_set_bus_width(card->host, bus_width); | 565 | mmc_card_set_ddr_mode(card); |
566 | mmc_set_bus_width_ddr(card->host, bus_width, ddr); | ||
566 | } | 567 | } |
567 | } | 568 | } |
568 | 569 | ||