On Mar 16, 2011, at 8:00 AM, Nath, Arindam wrote: > 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? Power to the sd slot is supplied via a regulator. This is turned on at power on. sometime in the future a reboot is done. power is NOT removed. The device does not reset into the default state. Have seen this on some boards. > > 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