From: Aaron Lu <aaron.lu@amd.com>
To: Chris Ball <cjb@laptop.org>
Cc: Girish K S <girish.shivananjappa@linaro.org>,
Philip Rakity <prakity@marvell.com>,
linux-mmc@vger.kernel.org, Aaron Lu <aaron.lwe@gmail.com>
Subject: Re: [PATCH 2/2] mmc: sd: Fix sd current limit setting
Date: Wed, 18 Jul 2012 14:22:23 +0800 [thread overview]
Message-ID: <20120718062223.GA2711@aarontestpc.amd.com> (raw)
In-Reply-To: <87liihocxj.fsf@octavius.laptop.org>
Hi Chris,
On Wed, Jul 18, 2012 at 01:28:40AM -0400, Chris Ball wrote:
> Hi Aaron,
>
> On Wed, Jul 18 2012, Aaron Lu wrote:
> > Is the following patch OK? This is based on top of current mmc-next with
> > the previous one in tree. Not sure if this is what you want though.
>
> Yes, that's perfect; squashed into the original patch and pushed out
> to mmc-next. Thanks!
>
> Having there be so many MAX_CURRENT defines -- and having them be
> split in the middle between CAP_ and CAP2_ -- is starting to feel
> a bit awkward.
I agree.
> Does anyone have ideas on how that might be tidied up,
> since we have an opportunity to come up with a better plan
> before this gets merged soon?
What about we add three fields in mmc_host to store the max current
value for 3.3v/3.0v/1.8v and use that when needed instead of the cap
setting of the host?
I've prepared the following code, please check if this is better than
the current one:
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 312b78d..2232004 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -517,11 +517,36 @@ 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 voltage;
+ u32 max_current;
/*
* Current limit switch is only defined for SDR50, SDR104, and DDR50
@@ -535,9 +560,9 @@ static int sd_set_current_limit(struct mmc_card *card, u8 *status)
/*
* Host has different current capabilities when operating at
- * different voltages, so find out the current voltage first.
+ * different voltages, so find out its max current first.
*/
- voltage = 1 << card->host->ios.vdd;
+ max_current = sd_get_host_max_current(card->host);
/*
* We only check host's capability here, if we set a limit that is
@@ -547,34 +572,15 @@ 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 (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 & (MMC_VDD_29_30 | MMC_VDD_30_31)) {
- 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 & (MMC_VDD_32_33 | MMC_VDD_33_34)) {
- 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_330)
- current_limit = SD_SET_CURRENT_LIMIT_600;
- 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_330)
- 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);
@@ -707,6 +713,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
@@ -734,9 +741,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:
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 455a093..a72ad30 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2906,73 +2906,30 @@ 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;
-
- /* 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;
-
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;
-
- /* 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;
-
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_180;
- else if (max_current_180 >= 600)
- mmc->caps |= MMC_CAP_MAX_CURRENT_600_180;
- else if (max_current_180 >= 400)
- mmc->caps |= MMC_CAP_MAX_CURRENT_400_180;
- else if (max_current_180 >= 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 79d8921..8d2c052 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -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 */
@@ -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_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,14 +257,6 @@ 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 */
#define MMC_CAP2_PACKED_RD (1 << 20) /* Allow packed read */
#define MMC_CAP2_PACKED_WR (1 << 21) /* Allow packed write */
#define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \
Thanks,
Aaron
next prev parent reply other threads:[~2012-07-18 6:22 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-07-03 6:16 [PATCH 0/2] SD current limit setting fix Aaron Lu
2012-07-03 6:16 ` [PATCH 1/2] mmc: core: Simplify and fix for SD switch processing Aaron Lu
2012-07-04 0:48 ` Chris Ball
2012-07-03 6:16 ` [PATCH 2/2] mmc: sd: Fix sd current limit setting Aaron Lu
2012-07-03 14:18 ` Philip Rakity
2012-07-04 0:52 ` Chris Ball
2012-07-04 5:31 ` [PATCH v2 " Aaron Lu
2012-07-09 1:23 ` Philip Rakity
2012-07-10 2:57 ` Chris Ball
2012-07-17 9:34 ` [PATCH " Girish K S
2012-07-17 13:43 ` Aaron Lu
2012-07-17 15:43 ` Chris Ball
2012-07-18 5:09 ` Aaron Lu
2012-07-18 5:28 ` Chris Ball
2012-07-18 6:22 ` Aaron Lu [this message]
2012-07-19 2:41 ` Chris Ball
2012-07-19 3:47 ` Philip Rakity
2012-07-19 6:25 ` Chris Ball
2012-07-19 4:47 ` Girish K S
2012-07-19 5:03 ` Chris Ball
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120718062223.GA2711@aarontestpc.amd.com \
--to=aaron.lu@amd.com \
--cc=aaron.lwe@gmail.com \
--cc=cjb@laptop.org \
--cc=girish.shivananjappa@linaro.org \
--cc=linux-mmc@vger.kernel.org \
--cc=prakity@marvell.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox