Hi Philip, > -----Original Message----- > From: Philip Rakity [mailto:prakity@xxxxxxxxxxx] > Sent: Wednesday, March 16, 2011 8:22 PM > To: Nath, Arindam > Cc: cjb@xxxxxxxxxx; zhangfei.gao@xxxxxxxxx; subhashj@xxxxxxxxxxxxxx; > linux-mmc@xxxxxxxxxxxxxxx; Su, Henry; Lu, Aaron; anath.amd@xxxxxxxxx > Subject: Re: [PATCH v2 07/12] mmc: sd: set current limit for uhs cards > > > On Mar 16, 2011, at 7:32 AM, Nath, Arindam wrote: > > > Hi Philip, > > > > > >> -----Original Message----- > >> From: Philip Rakity [mailto:prakity@xxxxxxxxxxx] > >> Sent: Wednesday, March 16, 2011 7:56 PM > >> To: Nath, Arindam > >> Cc: cjb@xxxxxxxxxx; zhangfei.gao@xxxxxxxxx; subhashj@xxxxxxxxxxxxxx; > >> linux-mmc@xxxxxxxxxxxxxxx; Su, Henry; Lu, Aaron; anath.amd@xxxxxxxxx > >> Subject: Re: [PATCH v2 07/12] mmc: sd: set current limit for uhs > cards > >> > >> > >> On Mar 4, 2011, at 3:32 AM, Arindam Nath wrote: > >> > >>> 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. > >>> > >>> Signed-off-by: Arindam Nath <arindam.nath@xxxxxxx> > >>> --- > >>> drivers/mmc/core/sd.c | 45 > >> +++++++++++++++++++++++++++++++++++++++++++++ > >>> drivers/mmc/host/sdhci.c | 24 ++++++++++++++++++++++++ > >>> include/linux/mmc/card.h | 9 +++++++++ > >>> include/linux/mmc/host.h | 1 + > >>> 4 files changed, 79 insertions(+), 0 deletions(-) > >>> > >>> diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c > >>> index ec0d8e6..df98a2c 100644 > >>> --- a/drivers/mmc/core/sd.c > >>> +++ b/drivers/mmc/core/sd.c > >>> @@ -550,6 +550,46 @@ static int sd_set_bus_speed_mode(struct > mmc_card > >> *card, u8 *status) > >>> return 0; > >>> } > >>> > >>> +static int sd_set_current_limit(struct mmc_card *card, u8 *status) > >>> +{ > >>> + struct mmc_host *host = card->host; > >>> + int mmc_host_max_current_180, current_limit; > >>> + int err; > >>> + > >>> + /* sanity check */ > >>> + if (!host->ops->get_max_current_180) > >>> + return 0; > >> > >> a better name would be get_max_current rather than > get_max_current_180 > > > > The Max Current Capabilities register reports maximum currents for > 1.8V, 3.0V and 3.3V. Since we are only interested in the maximum > current at 1.8V, so I have added *_180 to the variable names to make it > explicit. > > understand but that is the usage now and if we need to extend the code > the name becomes misleading. Okay. I will remove *_180 in next version. > > > >> > >> do you want a test for get_max_current_180 < 400 ? and return 0 > have > >> it do the switch > >> by setting the value ? > > > > As mentioned in the Physical Layer spec v3.01, <400mA falls under the > default current limit, so we don't need to set it in case any or all of > the above conditions fail. > > if future cards have memory or power is not removed they will they > retain the old setting ? if so better to explicitly initialize. Can you please elaborate this a little further? Thanks, Arindam > > > > > Thanks, > > Arindam > > > >>> + > >>> + /* Maximum current supported by host at 1.8V */ > >>> + mmc_host_max_current_180 = host->ops->get_max_current_180(host); > >>> + > >>> + if (mmc_host_max_current_180 >= 800) { > >>> + if (card->sw_caps.uhs_curr_limit & SD_MAX_CURRENT_800) > >>> + current_limit = SD_SET_CURRENT_LIMIT_800; > >>> + else if (card->sw_caps.uhs_curr_limit & SD_MAX_CURRENT_600) > >>> + current_limit = SD_SET_CURRENT_LIMIT_600; > >>> + else if (card->sw_caps.uhs_curr_limit & SD_MAX_CURRENT_400) > >>> + current_limit = SD_SET_CURRENT_LIMIT_400; > >>> + } else if (mmc_host_max_current_180 >= 600) { > >>> + if (card->sw_caps.uhs_curr_limit & SD_MAX_CURRENT_600) > >>> + current_limit = SD_SET_CURRENT_LIMIT_600; > >>> + else if (card->sw_caps.uhs_curr_limit & SD_MAX_CURRENT_400) > >>> + current_limit = SD_SET_CURRENT_LIMIT_400; > >>> + } else if (mmc_host_max_current_180 >= 400) > >>> + if (card->sw_caps.uhs_curr_limit & SD_MAX_CURRENT_400) > >>> + current_limit = SD_SET_CURRENT_LIMIT_400; > >> > >> or > >> else > >> current_limit = SD_SET_CURRENT_LIMIT_200; > >>> + > >>> + err = mmc_sd_switch(card, 1, 3, current_limit, status); > >>> + if (err) > >>> + return err; > >>> + > >>> + if (((status[15] >> 4) & 0x0F) != current_limit) > >>> + printk(KERN_WARNING "%s: Problem setting current limit!\n", > >>> + mmc_hostname(card->host)); > >>> + > >>> + return 0; > >>> +} > >>> + > >>> /* > >>> * UHS-I specific initialization procedure > >>> */ > >>> @@ -590,6 +630,11 @@ static int mmc_sd_init_uhs_card(struct > mmc_card > >> *card) > >>> > >>> /* Set bus speed mode of the card */ > >>> err = sd_set_bus_speed_mode(card, status); > >>> + if (err) > >>> + goto out; > >>> + > >>> + /* Set current limit for the card */ > >>> + err = sd_set_current_limit(card, status); > >>> > >>> out: > >>> kfree(status); > >>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c > >>> index f127fa2..245cc39 100644 > >>> --- a/drivers/mmc/host/sdhci.c > >>> +++ b/drivers/mmc/host/sdhci.c > >>> @@ -1462,12 +1462,36 @@ static int > >> sdhci_start_signal_voltage_switch(struct mmc_host *mmc) > >>> return -EAGAIN; > >>> } > >>> > >> > >> better name is sdhci_get_max_current > >> > >>> +static int sdhci_get_max_current_180(struct mmc_host *mmc) > >>> +{ > >>> + struct sdhci_host *host; > >>> + u32 max_current_caps; > >>> + unsigned long flags; > >>> + int max_current_180; > >>> + > >>> + host = mmc_priv(mmc); > >>> + > >>> + spin_lock_irqsave(&host->lock, flags); > >>> + > >>> + max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT); > >>> + > >>> + spin_unlock_irqrestore(&host->lock, flags); > >>> + > >>> + /* Maximum current is 4 times the register value for 1.8V */ > >>> + max_current_180 = ((max_current_caps & > >> SDHCI_MAX_CURRENT_180_MASK) >> > >>> + SDHCI_MAX_CURRENT_180_SHIFT) * > >>> + SDHCI_MAX_CURRENT_MULTIPLIER; > >> > >> SDHCI_MAX_CURRENT_SHIFT is better name. > >> > >>> + > >>> + return max_current_180; > >>> +} > >>> + > >>> static const struct mmc_host_ops sdhci_ops = { > >>> .request = sdhci_request, > >>> .set_ios = sdhci_set_ios, > >>> .get_ro = sdhci_get_ro, > >>> .enable_sdio_irq = sdhci_enable_sdio_irq, > >>> .start_signal_voltage_switch = > >> sdhci_start_signal_voltage_switch, > >>> + .get_max_current_180 = sdhci_get_max_current_180, > >> > >> .get_max_current = sdhci_get_max_current; > >>> }; > >>> > >>> > >> > /********************************************************************** > >> *******\ > >>> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h > >>> index 0b24c41..a6811ae 100644 > >>> --- a/include/linux/mmc/card.h > >>> +++ b/include/linux/mmc/card.h > >>> @@ -98,6 +98,15 @@ struct sd_switch_caps { > >>> #define SD_DRIVER_TYPE_C 0x04 > >>> #define SD_DRIVER_TYPE_D 0x08 > >>> unsigned int uhs_curr_limit; > >>> +#define SD_SET_CURRENT_LIMIT_200 0 > >>> +#define SD_SET_CURRENT_LIMIT_400 1 > >>> +#define SD_SET_CURRENT_LIMIT_600 2 > >>> +#define SD_SET_CURRENT_LIMIT_800 3 > >>> + > >>> +#define SD_MAX_CURRENT_200 (1 << SD_SET_CURRENT_LIMIT_200) > >>> +#define SD_MAX_CURRENT_400 (1 << SD_SET_CURRENT_LIMIT_400) > >>> +#define SD_MAX_CURRENT_600 (1 << SD_SET_CURRENT_LIMIT_600) > >>> +#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800) > >>> }; > >>> > >>> struct sdio_cccr { > >>> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h > >>> index 4dfff6d..e84cd05 100644 > >>> --- a/include/linux/mmc/host.h > >>> +++ b/include/linux/mmc/host.h > >>> @@ -128,6 +128,7 @@ struct mmc_host_ops { > >>> void (*init_card)(struct mmc_host *host, struct mmc_card *card); > >>> > >>> int (*start_signal_voltage_switch)(struct mmc_host *host); > >>> + int (*get_max_current_180)(struct mmc_host *mmc); > >>> }; > >>> > >>> struct mmc_card; > >>> -- > >>> 1.7.1 > >>> > >> > > > > > -- 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