Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 312854
b: refs/heads/master
c: 55c4665
h: refs/heads/master
v: v3
  • Loading branch information
Aaron Lu authored and Chris Ball committed Jul 22, 2012
1 parent afc82b9 commit 5df10aa
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 51 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 94c18149451e9ae91a669bc33370273327d7da81
refs/heads/master: 55c4665ea0a42fd6427826bfce96eb4b0389262a
69 changes: 54 additions & 15 deletions trunk/drivers/mmc/core/sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,34 +517,69 @@ static int sd_set_bus_speed_mode(struct mmc_card *card, u8 *status)
return 0;
}

/* Get host's max current setting at its current voltage */
static u32 sd_get_host_max_current(struct mmc_host *host)
{
u32 voltage, max_current;

voltage = 1 << host->ios.vdd;
switch (voltage) {
case MMC_VDD_165_195:
max_current = host->max_current_180;
break;
case MMC_VDD_29_30:
case MMC_VDD_30_31:
max_current = host->max_current_300;
break;
case MMC_VDD_32_33:
case MMC_VDD_33_34:
max_current = host->max_current_330;
break;
default:
max_current = 0;
}

return max_current;
}

static int sd_set_current_limit(struct mmc_card *card, u8 *status)
{
int current_limit = SD_SET_CURRENT_NO_CHANGE;
int err;
u32 max_current;

/*
* Current limit switch is only defined for SDR50, SDR104, and DDR50
* bus speed modes. For other bus speed modes, we do not change the
* current limit.
*/
if ((card->sd_bus_speed != UHS_SDR50_BUS_SPEED) &&
(card->sd_bus_speed != UHS_SDR104_BUS_SPEED) &&
(card->sd_bus_speed != UHS_DDR50_BUS_SPEED))
return 0;

/*
* Host has different current capabilities when operating at
* different voltages, so find out its max current first.
*/
max_current = sd_get_host_max_current(card->host);

/*
* We only check host's capability here, if we set a limit that is
* higher than the card's maximum current, the card will be using its
* maximum current, e.g. if the card's maximum current is 300ma, and
* when we set current limit to 200ma, the card will draw 200ma, and
* when we set current limit to 400/600/800ma, the card will draw its
* maximum 300ma from the host.
*/
if ((card->sd_bus_speed == UHS_SDR50_BUS_SPEED) ||
(card->sd_bus_speed == UHS_SDR104_BUS_SPEED) ||
(card->sd_bus_speed == UHS_DDR50_BUS_SPEED)) {
if (card->host->caps & MMC_CAP_MAX_CURRENT_800)
current_limit = SD_SET_CURRENT_LIMIT_800;
else if (card->host->caps & MMC_CAP_MAX_CURRENT_600)
current_limit = SD_SET_CURRENT_LIMIT_600;
else if (card->host->caps & MMC_CAP_MAX_CURRENT_400)
current_limit = SD_SET_CURRENT_LIMIT_400;
else if (card->host->caps & MMC_CAP_MAX_CURRENT_200)
current_limit = SD_SET_CURRENT_LIMIT_200;
}
if (max_current >= 800)
current_limit = SD_SET_CURRENT_LIMIT_800;
else if (max_current >= 600)
current_limit = SD_SET_CURRENT_LIMIT_600;
else if (max_current >= 400)
current_limit = SD_SET_CURRENT_LIMIT_400;
else if (max_current >= 200)
current_limit = SD_SET_CURRENT_LIMIT_200;

if (current_limit != SD_SET_CURRENT_NO_CHANGE) {
err = mmc_sd_switch(card, 1, 3, current_limit, status);
Expand Down Expand Up @@ -677,6 +712,7 @@ struct device_type sd_type = {
int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
{
int err;
u32 max_current;

/*
* Since we're changing the OCR value, we seem to
Expand Down Expand Up @@ -704,9 +740,12 @@ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50))
ocr |= SD_OCR_S18R;

/* If the host can supply more than 150mA, XPC should be set to 1. */
if (host->caps & (MMC_CAP_SET_XPC_330 | MMC_CAP_SET_XPC_300 |
MMC_CAP_SET_XPC_180))
/*
* If the host can supply more than 150mA at current voltage,
* XPC should be set to 1.
*/
max_current = sd_get_host_max_current(host);
if (max_current > 150)
ocr |= SD_OCR_XPC;

try_again:
Expand Down
31 changes: 3 additions & 28 deletions trunk/drivers/mmc/host/sdhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -2906,53 +2906,28 @@ int sdhci_add_host(struct sdhci_host *host)
}

if (caps[0] & SDHCI_CAN_VDD_330) {
int max_current_330;

ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34;

max_current_330 = ((max_current_caps &
mmc->max_current_330 = ((max_current_caps &
SDHCI_MAX_CURRENT_330_MASK) >>
SDHCI_MAX_CURRENT_330_SHIFT) *
SDHCI_MAX_CURRENT_MULTIPLIER;

if (max_current_330 > 150)
mmc->caps |= MMC_CAP_SET_XPC_330;
}
if (caps[0] & SDHCI_CAN_VDD_300) {
int max_current_300;

ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31;

max_current_300 = ((max_current_caps &
mmc->max_current_300 = ((max_current_caps &
SDHCI_MAX_CURRENT_300_MASK) >>
SDHCI_MAX_CURRENT_300_SHIFT) *
SDHCI_MAX_CURRENT_MULTIPLIER;

if (max_current_300 > 150)
mmc->caps |= MMC_CAP_SET_XPC_300;
}
if (caps[0] & SDHCI_CAN_VDD_180) {
int max_current_180;

ocr_avail |= MMC_VDD_165_195;

max_current_180 = ((max_current_caps &
mmc->max_current_180 = ((max_current_caps &
SDHCI_MAX_CURRENT_180_MASK) >>
SDHCI_MAX_CURRENT_180_SHIFT) *
SDHCI_MAX_CURRENT_MULTIPLIER;

if (max_current_180 > 150)
mmc->caps |= MMC_CAP_SET_XPC_180;

/* Maximum current capabilities of the host at 1.8V */
if (max_current_180 >= 800)
mmc->caps |= MMC_CAP_MAX_CURRENT_800;
else if (max_current_180 >= 600)
mmc->caps |= MMC_CAP_MAX_CURRENT_600;
else if (max_current_180 >= 400)
mmc->caps |= MMC_CAP_MAX_CURRENT_400;
else if (max_current_180 >= 200)
mmc->caps |= MMC_CAP_MAX_CURRENT_200;
}

mmc->ocr_avail = ocr_avail;
Expand Down
10 changes: 3 additions & 7 deletions trunk/include/linux/mmc/host.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ struct mmc_host {
u32 ocr_avail_sd; /* SD-specific OCR */
u32 ocr_avail_mmc; /* MMC-specific OCR */
struct notifier_block pm_notify;
u32 max_current_330;
u32 max_current_300;
u32 max_current_180;

#define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */
#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */
Expand Down Expand Up @@ -232,16 +235,9 @@ struct mmc_host {
#define MMC_CAP_UHS_SDR50 (1 << 17) /* Host supports UHS SDR50 mode */
#define MMC_CAP_UHS_SDR104 (1 << 18) /* Host supports UHS SDR104 mode */
#define MMC_CAP_UHS_DDR50 (1 << 19) /* Host supports UHS DDR50 mode */
#define MMC_CAP_SET_XPC_330 (1 << 20) /* Host supports >150mA current at 3.3V */
#define MMC_CAP_SET_XPC_300 (1 << 21) /* Host supports >150mA current at 3.0V */
#define MMC_CAP_SET_XPC_180 (1 << 22) /* Host supports >150mA current at 1.8V */
#define MMC_CAP_DRIVER_TYPE_A (1 << 23) /* Host supports Driver Type A */
#define MMC_CAP_DRIVER_TYPE_C (1 << 24) /* Host supports Driver Type C */
#define MMC_CAP_DRIVER_TYPE_D (1 << 25) /* Host supports Driver Type D */
#define MMC_CAP_MAX_CURRENT_200 (1 << 26) /* Host max current limit is 200mA */
#define MMC_CAP_MAX_CURRENT_400 (1 << 27) /* Host max current limit is 400mA */
#define MMC_CAP_MAX_CURRENT_600 (1 << 28) /* Host max current limit is 600mA */
#define MMC_CAP_MAX_CURRENT_800 (1 << 29) /* Host max current limit is 800mA */
#define MMC_CAP_CMD23 (1 << 30) /* CMD23 supported. */
#define MMC_CAP_HW_RESET (1 << 31) /* Hardware reset */

Expand Down

0 comments on commit 5df10aa

Please sign in to comment.