Hi Arron, One minor comment -- okay without the change but clearer IMHO with the change. Reviewed-by: Philip Rakity <prakity@xxxxxxxxxxx> Philip On Jul 2, 2012, at 11:16 PM, Aaron Lu wrote: > Host has different current capabilities at different voltages, we need > to record these settings seperately. Before set current limit for the sd > card, find out the current voltage first and then find out the current > capabilities of the host to set the limit. > > Signed-off-by: Aaron Lu <aaron.lu@xxxxxxx> > --- > drivers/mmc/core/sd.c | 58 ++++++++++++++++++++++++++++++++++++++++++------ > drivers/mmc/host/sdhci.c | 28 +++++++++++++++++++---- > include/linux/mmc/host.h | 16 +++++++++---- > 3 files changed, 87 insertions(+), 15 deletions(-) > > diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c > index ae72d6e..4b4cf4d 100644 > --- a/drivers/mmc/core/sd.c > +++ b/drivers/mmc/core/sd.c > @@ -521,11 +521,39 @@ static int sd_set_current_limit(struct mmc_card *card, u8 *status) > { > int current_limit = SD_SET_CURRENT_NO_CHANGE; > int err; > + u8 voltage; u32 voltage; > > /* > * 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 the current voltage first. > + */ > + switch (1 << card->host->ios.vdd) { > + case MMC_VDD_165_195: > + voltage = 0; /* host's voltage is 1.8V */ It is a little clearly if you do this or make voltage 0, 1, 2 an enum for the routine. otherwise reviewed-by: Philip Rakity <prakity@xxxxxxxxxxx> voltage = MMC_VDD_165_195; > > + break; > + case MMC_VDD_29_30: > + case MMC_VDD_30_31: > + voltage = 1; /* host's voltage is 3.0V */ voltage = MMC_VDD_29_30 | MMC_VDD_30_31; > > + break; > + case MMC_VDD_32_33: > + case MMC_VDD_33_34: > + voltage = 2; /* host's voltage is 3.3V */ voltage = MMC_VDD_32_33 | MMC_VDD_33_34; > > + break; > + default: > + BUG(); /* host's voltage is invalid */ > + } > + > + /* > * 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 > @@ -533,16 +561,32 @@ static int sd_set_current_limit(struct mmc_card *card, u8 *status) > * 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) > + if (voltage == 0) { if (voltage == MMC_VDD_165_195) { > + if (card->host->caps & MMC_CAP_MAX_CURRENT_800_180) > + current_limit = SD_SET_CURRENT_LIMIT_800; > + else if (card->host->caps & MMC_CAP_MAX_CURRENT_600_180) > + current_limit = SD_SET_CURRENT_LIMIT_600; > + else if (card->host->caps & MMC_CAP_MAX_CURRENT_400_180) > + current_limit = SD_SET_CURRENT_LIMIT_400; > + else if (card->host->caps & MMC_CAP_MAX_CURRENT_200_180) > + current_limit = SD_SET_CURRENT_LIMIT_200; > + } else if (voltage == 1) } else if (voltage == ( MMC_VDD_29_30 | MMC_VDD_30_31) etc ? > { > + if (card->host->caps & MMC_CAP_MAX_CURRENT_800_300) > + current_limit = SD_SET_CURRENT_LIMIT_800; > + else if (card->host->caps & MMC_CAP_MAX_CURRENT_600_300) > + current_limit = SD_SET_CURRENT_LIMIT_600; > + else if (card->host->caps & MMC_CAP_MAX_CURRENT_400_300) > + current_limit = SD_SET_CURRENT_LIMIT_400; > + else if (card->host->caps & MMC_CAP_MAX_CURRENT_200_300) > + current_limit = SD_SET_CURRENT_LIMIT_200; > + } else if (voltage == 2) { > + if (card->host->caps & MMC_CAP_MAX_CURRENT_800_330) > current_limit = SD_SET_CURRENT_LIMIT_800; > - else if (card->host->caps & MMC_CAP_MAX_CURRENT_600) > + else if (card->host->caps & MMC_CAP_MAX_CURRENT_600_330) > current_limit = SD_SET_CURRENT_LIMIT_600; > - else if (card->host->caps & MMC_CAP_MAX_CURRENT_400) > + else if (card->host->caps & MMC_CAP_MAX_CURRENT_400_330) > current_limit = SD_SET_CURRENT_LIMIT_400; > - else if (card->host->caps & MMC_CAP_MAX_CURRENT_200) > + else if (card->host->caps & MMC_CAP_MAX_CURRENT_200_330) > current_limit = SD_SET_CURRENT_LIMIT_200; > } > > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c > index caba999..00c2cbb 100644 > --- a/drivers/mmc/host/sdhci.c > +++ b/drivers/mmc/host/sdhci.c > @@ -2897,6 +2897,16 @@ int sdhci_add_host(struct sdhci_host *host) > > if (max_current_330 > 150) > mmc->caps |= MMC_CAP_SET_XPC_330; > + > + /* Maximum current capabilities of the host at 3.3V */ > + if (max_current_330 >= 800) > + mmc->caps |= MMC_CAP_MAX_CURRENT_800_330; > + else if (max_current_330 >= 600) > + mmc->caps |= MMC_CAP_MAX_CURRENT_600_330; > + else if (max_current_330 >= 400) > + mmc->caps |= MMC_CAP_MAX_CURRENT_400_330; > + else if (max_current_330 >= 200) > + mmc->caps |= MMC_CAP_MAX_CURRENT_200_330; > } > if (caps[0] & SDHCI_CAN_VDD_300) { > int max_current_300; > @@ -2910,6 +2920,16 @@ int sdhci_add_host(struct sdhci_host *host) > > if (max_current_300 > 150) > mmc->caps |= MMC_CAP_SET_XPC_300; > + > + /* Maximum current capabilities of the host at 3.0V */ > + if (max_current_300 >= 800) > + mmc->caps |= MMC_CAP_MAX_CURRENT_800_300; > + else if (max_current_300 >= 600) > + mmc->caps |= MMC_CAP_MAX_CURRENT_600_300; > + else if (max_current_300 >= 400) > + mmc->caps |= MMC_CAP_MAX_CURRENT_400_300; > + else if (max_current_300 >= 200) > + mmc->caps |= MMC_CAP_MAX_CURRENT_200_300; > } > if (caps[0] & SDHCI_CAN_VDD_180) { > int max_current_180; > @@ -2926,13 +2946,13 @@ int sdhci_add_host(struct sdhci_host *host) > > /* Maximum current capabilities of the host at 1.8V */ > if (max_current_180 >= 800) > - mmc->caps |= MMC_CAP_MAX_CURRENT_800; > + mmc->caps |= MMC_CAP_MAX_CURRENT_800_180; > else if (max_current_180 >= 600) > - mmc->caps |= MMC_CAP_MAX_CURRENT_600; > + mmc->caps |= MMC_CAP_MAX_CURRENT_600_180; > else if (max_current_180 >= 400) > - mmc->caps |= MMC_CAP_MAX_CURRENT_400; > + mmc->caps |= MMC_CAP_MAX_CURRENT_400_180; > else if (max_current_180 >= 200) > - mmc->caps |= MMC_CAP_MAX_CURRENT_200; > + mmc->caps |= MMC_CAP_MAX_CURRENT_200_180; > } > > mmc->ocr_avail = ocr_avail; > diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h > index 65c64ee..ca84ffb 100644 > --- a/include/linux/mmc/host.h > +++ b/include/linux/mmc/host.h > @@ -238,10 +238,10 @@ struct mmc_host { > #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_MAX_CURRENT_200_180 (1 << 26) /* Host max current limit is 200mA at 1.8V */ > +#define MMC_CAP_MAX_CURRENT_400_180 (1 << 27) /* Host max current limit is 400mA at 1.8V */ > +#define MMC_CAP_MAX_CURRENT_600_180 (1 << 28) /* Host max current limit is 600mA at 1.8V */ > +#define MMC_CAP_MAX_CURRENT_800_180 (1 << 29) /* Host max current limit is 800mA at 1.8V */ > #define MMC_CAP_CMD23 (1 << 30) /* CMD23 supported. */ > #define MMC_CAP_HW_RESET (1 << 31) /* Hardware reset */ > > @@ -261,6 +261,14 @@ struct mmc_host { > #define MMC_CAP2_HC_ERASE_SZ (1 << 9) /* High-capacity erase size */ > #define MMC_CAP2_CD_ACTIVE_HIGH (1 << 10) /* Card-detect signal active high */ > #define MMC_CAP2_RO_ACTIVE_HIGH (1 << 11) /* Write-protect signal active high */ > +#define MMC_CAP_MAX_CURRENT_200_300 (1 << 12) /* Host max current limit is 200mA at 3.0V */ > +#define MMC_CAP_MAX_CURRENT_400_300 (1 << 13) /* Host max current limit is 400mA at 3.0V */ > +#define MMC_CAP_MAX_CURRENT_600_300 (1 << 14) /* Host max current limit is 600mA at 3.0V */ > +#define MMC_CAP_MAX_CURRENT_800_300 (1 << 15) /* Host max current limit is 800mA at 3.0V */ > +#define MMC_CAP_MAX_CURRENT_200_330 (1 << 16) /* Host max current limit is 200mA at 3.3V */ > +#define MMC_CAP_MAX_CURRENT_400_330 (1 << 17) /* Host max current limit is 400mA at 3.3V */ > +#define MMC_CAP_MAX_CURRENT_600_330 (1 << 18) /* Host max current limit is 600mA at 3.3V */ > +#define MMC_CAP_MAX_CURRENT_800_330 (1 << 19) /* Host max current limit is 800mA at 3.3V */ > > mmc_pm_flag_t pm_caps; /* supported pm features */ > unsigned int power_notify_type; > -- > 1.7.11.1.3.g4c8a9db > > -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html