aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArindam Nath <arindam.nath@amd.com>2011-05-05 02:49:02 -0400
committerChris Ball <cjb@laptop.org>2011-05-24 23:53:45 -0400
commit5371c927bcd06a5c9dd6785bab2d452b87d9abc6 (patch)
tree71add97be08e93fcb5ac2bfcc44fc66d8f2b92df
parent49c468fcf878d2c86e31920cf54aa90c88418a66 (diff)
mmc: sd: set current limit for uhs cards
We decide on the current limit to be set for the card based on the Capability of Host Controller to provide current at 1.8V signalling, and the maximum current limit of the card as indicated by CMD6 mode 0. We then set the current limit for the card using CMD6 mode 1. As per the Physical Layer Spec v3.01, the current limit switch is only applicable for SDR50, SDR104, and DDR50 bus speed modes. For other UHS-I modes, we set the default current limit of 200mA. Tested by Zhangfei Gao with a Toshiba uhs card and general hs card, on mmp2 in SDMA mode. Signed-off-by: Arindam Nath <arindam.nath@amd.com> Reviewed-by: Philip Rakity <prakity@marvell.com> Tested-by: Philip Rakity <prakity@marvell.com> Acked-by: Zhangfei Gao <zhangfei.gao@marvell.com> Signed-off-by: Chris Ball <cjb@laptop.org>
-rw-r--r--drivers/mmc/core/sd.c63
-rw-r--r--drivers/mmc/host/sdhci.c10
-rw-r--r--include/linux/mmc/card.h9
-rw-r--r--include/linux/mmc/host.h4
4 files changed, 86 insertions, 0 deletions
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 6970b82171f7..8e2d8012e4cb 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -512,6 +512,64 @@ static int sd_set_bus_speed_mode(struct mmc_card *card, u8 *status)
512 return 0; 512 return 0;
513} 513}
514 514
515static int sd_set_current_limit(struct mmc_card *card, u8 *status)
516{
517 int current_limit = 0;
518 int err;
519
520 /*
521 * Current limit switch is only defined for SDR50, SDR104, and DDR50
522 * bus speed modes. For other bus speed modes, we set the default
523 * current limit of 200mA.
524 */
525 if ((card->sd_bus_speed == UHS_SDR50_BUS_SPEED) ||
526 (card->sd_bus_speed == UHS_SDR104_BUS_SPEED) ||
527 (card->sd_bus_speed == UHS_DDR50_BUS_SPEED)) {
528 if (card->host->caps & MMC_CAP_MAX_CURRENT_800) {
529 if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_800)
530 current_limit = SD_SET_CURRENT_LIMIT_800;
531 else if (card->sw_caps.sd3_curr_limit &
532 SD_MAX_CURRENT_600)
533 current_limit = SD_SET_CURRENT_LIMIT_600;
534 else if (card->sw_caps.sd3_curr_limit &
535 SD_MAX_CURRENT_400)
536 current_limit = SD_SET_CURRENT_LIMIT_400;
537 else if (card->sw_caps.sd3_curr_limit &
538 SD_MAX_CURRENT_200)
539 current_limit = SD_SET_CURRENT_LIMIT_200;
540 } else if (card->host->caps & MMC_CAP_MAX_CURRENT_600) {
541 if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_600)
542 current_limit = SD_SET_CURRENT_LIMIT_600;
543 else if (card->sw_caps.sd3_curr_limit &
544 SD_MAX_CURRENT_400)
545 current_limit = SD_SET_CURRENT_LIMIT_400;
546 else if (card->sw_caps.sd3_curr_limit &
547 SD_MAX_CURRENT_200)
548 current_limit = SD_SET_CURRENT_LIMIT_200;
549 } else if (card->host->caps & MMC_CAP_MAX_CURRENT_400) {
550 if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_400)
551 current_limit = SD_SET_CURRENT_LIMIT_400;
552 else if (card->sw_caps.sd3_curr_limit &
553 SD_MAX_CURRENT_200)
554 current_limit = SD_SET_CURRENT_LIMIT_200;
555 } else if (card->host->caps & MMC_CAP_MAX_CURRENT_200) {
556 if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_200)
557 current_limit = SD_SET_CURRENT_LIMIT_200;
558 }
559 } else
560 current_limit = SD_SET_CURRENT_LIMIT_200;
561
562 err = mmc_sd_switch(card, 1, 3, current_limit, status);
563 if (err)
564 return err;
565
566 if (((status[15] >> 4) & 0x0F) != current_limit)
567 printk(KERN_WARNING "%s: Problem setting current limit!\n",
568 mmc_hostname(card->host));
569
570 return 0;
571}
572
515/* 573/*
516 * UHS-I specific initialization procedure 574 * UHS-I specific initialization procedure
517 */ 575 */
@@ -550,6 +608,11 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card)
550 608
551 /* Set bus speed mode of the card */ 609 /* Set bus speed mode of the card */
552 err = sd_set_bus_speed_mode(card, status); 610 err = sd_set_bus_speed_mode(card, status);
611 if (err)
612 goto out;
613
614 /* Set current limit for the card */
615 err = sd_set_current_limit(card, status);
553 616
554out: 617out:
555 kfree(status); 618 kfree(status);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 8994493dd940..2a15aad2eba5 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2216,6 +2216,16 @@ int sdhci_add_host(struct sdhci_host *host)
2216 2216
2217 if (max_current_180 > 150) 2217 if (max_current_180 > 150)
2218 mmc->caps |= MMC_CAP_SET_XPC_180; 2218 mmc->caps |= MMC_CAP_SET_XPC_180;
2219
2220 /* Maximum current capabilities of the host at 1.8V */
2221 if (max_current_180 >= 800)
2222 mmc->caps |= MMC_CAP_MAX_CURRENT_800;
2223 else if (max_current_180 >= 600)
2224 mmc->caps |= MMC_CAP_MAX_CURRENT_600;
2225 else if (max_current_180 >= 400)
2226 mmc->caps |= MMC_CAP_MAX_CURRENT_400;
2227 else
2228 mmc->caps |= MMC_CAP_MAX_CURRENT_200;
2219 } 2229 }
2220 2230
2221 mmc->ocr_avail = ocr_avail; 2231 mmc->ocr_avail = ocr_avail;
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 4ef6ded6347d..47b5ad3960b7 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -105,6 +105,15 @@ struct sd_switch_caps {
105#define SD_DRIVER_TYPE_C 0x04 105#define SD_DRIVER_TYPE_C 0x04
106#define SD_DRIVER_TYPE_D 0x08 106#define SD_DRIVER_TYPE_D 0x08
107 unsigned int sd3_curr_limit; 107 unsigned int sd3_curr_limit;
108#define SD_SET_CURRENT_LIMIT_200 0
109#define SD_SET_CURRENT_LIMIT_400 1
110#define SD_SET_CURRENT_LIMIT_600 2
111#define SD_SET_CURRENT_LIMIT_800 3
112
113#define SD_MAX_CURRENT_200 (1 << SD_SET_CURRENT_LIMIT_200)
114#define SD_MAX_CURRENT_400 (1 << SD_SET_CURRENT_LIMIT_400)
115#define SD_MAX_CURRENT_600 (1 << SD_SET_CURRENT_LIMIT_600)
116#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800)
108}; 117};
109 118
110struct sdio_cccr { 119struct sdio_cccr {
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 62375992bdd6..52b5dc914a8c 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -203,6 +203,10 @@ struct mmc_host {
203#define MMC_CAP_DRIVER_TYPE_A (1 << 23) /* Host supports Driver Type A */ 203#define MMC_CAP_DRIVER_TYPE_A (1 << 23) /* Host supports Driver Type A */
204#define MMC_CAP_DRIVER_TYPE_C (1 << 24) /* Host supports Driver Type C */ 204#define MMC_CAP_DRIVER_TYPE_C (1 << 24) /* Host supports Driver Type C */
205#define MMC_CAP_DRIVER_TYPE_D (1 << 25) /* Host supports Driver Type D */ 205#define MMC_CAP_DRIVER_TYPE_D (1 << 25) /* Host supports Driver Type D */
206#define MMC_CAP_MAX_CURRENT_200 (1 << 26) /* Host max current limit is 200mA */
207#define MMC_CAP_MAX_CURRENT_400 (1 << 27) /* Host max current limit is 400mA */
208#define MMC_CAP_MAX_CURRENT_600 (1 << 28) /* Host max current limit is 600mA */
209#define MMC_CAP_MAX_CURRENT_800 (1 << 29) /* Host max current limit is 800mA */
206 210
207 mmc_pm_flag_t pm_caps; /* supported pm features */ 211 mmc_pm_flag_t pm_caps; /* supported pm features */
208 212