diff mbox series

[2/2] mmc: core: sd: Fix and simplify SD card current limit handling

Message ID 20250619085620.144181-3-avri.altman@sandisk.com
State New
Headers show
Series mmc: Fix max current limit handling for SD cards | expand

Commit Message

Avri Altman June 19, 2025, 8:56 a.m. UTC
The SD spec says: "In UHS-I mode, after selecting one of SDR50, SDR104,
or DDR50 mode by Function Group 1, host needs to change the Power Limit
to enable the card to operate in higher performance".

The driver previously determined SD card current limits incorrectly by
checking capability bits before bus speed was established, and by using
support bits in function group 4 (bytes 6 & 7) rather than the actual
current requirement (bytes 0 & 1). This is wrong because the card
responds for a given bus speed.

This patch queries the card's current requirement after setting the bus
speed, and uses the reported value to select the appropriate current
limit.

while at it, remove some unused constants and the misleading comment in
the code.

Fixes: d9812780a020 ("mmc: sd: limit SD card power limit according to cards capabilities")
Signed-off-by: Avri Altman <avri.altman@sandisk.com>
Cc: stable@vger.kernel.org
---
 drivers/mmc/core/sd.c    | 36 +++++++++++++-----------------------
 include/linux/mmc/card.h |  6 ------
 2 files changed, 13 insertions(+), 29 deletions(-)
diff mbox series

Patch

diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index cf92c5b2059a..357edfb910df 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -365,7 +365,6 @@  static int mmc_read_switch(struct mmc_card *card)
 		card->sw_caps.sd3_bus_mode = status[13];
 		/* Driver Strengths supported by the card */
 		card->sw_caps.sd3_drv_type = status[9];
-		card->sw_caps.sd3_curr_limit = status[7] | status[6] << 8;
 	}
 
 out:
@@ -556,7 +555,7 @@  static int sd_set_current_limit(struct mmc_card *card, u8 *status)
 {
 	int current_limit = SD_SET_CURRENT_LIMIT_200;
 	int err;
-	u32 max_current;
+	u32 max_current, card_needs;
 
 	/*
 	 * Current limit switch is only defined for SDR50, SDR104, and DDR50
@@ -575,33 +574,24 @@  static int sd_set_current_limit(struct mmc_card *card, u8 *status)
 	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.
-	 *
-	 * The above is incorrect: if we try to set a current limit that is
-	 * not supported by the card, the card can rightfully error out the
-	 * attempt, and remain at the default current limit.  This results
-	 * in a 300mA card being limited to 200mA even though the host
-	 * supports 800mA. Failures seen with SanDisk 8GB UHS cards with
-	 * an iMX6 host. --rmk
+	 * query the card of its maximun current/power consumption given the
+	 * bus speed mode
 	 */
-	if (max_current >= 800 &&
-	    card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_800)
+	err = mmc_sd_switch(card, 0, 0, card->sd_bus_speed, status);
+	if (err)
+		return err;
+
+	card_needs = status[1] | status[0] << 8;
+
+	if (max_current >= 800 && card_needs > 600)
 		current_limit = SD_SET_CURRENT_LIMIT_800;
-	else if (max_current >= 600 &&
-		 card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_600)
+	else if (max_current >= 600 && card_needs > 400)
 		current_limit = SD_SET_CURRENT_LIMIT_600;
-	else if (max_current >= 400 &&
-		 card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_400)
+	else if (max_current >= 400 && card_needs > 200)
 		current_limit = SD_SET_CURRENT_LIMIT_400;
 
 	if (current_limit != SD_SET_CURRENT_LIMIT_200) {
-		err = mmc_sd_switch(card, SD_SWITCH_SET, 3,
-				current_limit, status);
+		err = mmc_sd_switch(card, SD_SWITCH_SET, 3, current_limit, status);
 		if (err)
 			return err;
 
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index e9e964c20e53..67c1386ca574 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -177,17 +177,11 @@  struct sd_switch_caps {
 #define SD_DRIVER_TYPE_A	0x02
 #define SD_DRIVER_TYPE_C	0x04
 #define SD_DRIVER_TYPE_D	0x08
-	unsigned int		sd3_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)
-
 #define SD4_SET_POWER_LIMIT_0_72W	0
 #define SD4_SET_POWER_LIMIT_1_44W	1
 #define SD4_SET_POWER_LIMIT_2_16W	2