[...]
/* * 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);
Looking at the implementation of sd_get_host_max_current(), it's very limiting.
For example, if we are using MMC_VDD_34_35 or MMC_VDD_35_36, the function returns 0. Maybe this is good enough based upon those host drivers that actually sets host->max_current_180|300|330, but it kind of looks wrong to me.
I think we should re-work this interface to let us retrieve the maximum current from the host in a more flexible way. What we are really looking for is a value in Watt instead, I think. Don't get me wrong, this deserved it's own standalone patch on top of $subject patch.
I still need to consult internally, but Yes - I agree. Ultimately however, CMD6 expects us to fill the current limit value, so multiplying by voltage and dividing it back seems superfluous. How about adding to missing vdd and treat them as max_current_330, like in sdhci_get_vdd_value? Maybe something like:
+/*
- Get host's max current setting at its current voltage normalized to 3.6
- volt which is the voltage in which the card defines its limits
- */
+static u32 sd_host_normalized_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 * 180 / 360;
break;
case MMC_VDD_29_30:
case MMC_VDD_30_31:
max_current = host->max_current_300 * 300 / 360;
break;
case MMC_VDD_32_33:
case MMC_VDD_33_34:
case MMC_VDD_34_35:
case MMC_VDD_35_36:
max_current = host->max_current_330 * 330 / 360;
break;
default:
max_current = 0;
}
return max_current;
+}
I think it's way better than the current implementation in sd_get_host_max_current().
Still, I still think it's weird to have three different variables in the host, max_current_180, max_current_300 and max_current_330. That seems like an SDHCI specific thing to me, unless I am mistaken.
I would rather see a more flexible interface where we move away from using host->max_current_180|300|330 entirely and have a function that returns the supported limit (whatever unit we decide). Maybe it also makes sense to provide some additional helpers from the core that host drivers can call, to fetch/translate the values it should provide for this.
/* Get host's max current setting at its current voltage */ static u32 sd_get_host_max_current(struct mmc_host *host) { @@ -572,7 +602,7 @@ 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 its max current first. */
max_current = sd_get_host_max_current(card->host);
max_current = sd_host_normalized_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
I think it's important to keep some of the information from above, as it still stands, if I understand correctly.
I believe this highlights a common misunderstanding: it conflates the card’s capabilities (i.e., the maximum current it can support) with its actual power consumption, which depends on the required bus speed and operating conditions. The card will never specify or attempt to draw more current than it is capable of handling. If a current limit is set that exceeds the card’s capability, the card will not draw beyond its maximum; instead, it will operate within its own limits or may reject unsupported current limit settings as per the specification. Therefore, the logic should distinguish between the card’s advertised capabilities and its real-time power requirements, ensuring we do not confuse the two concepts.
I understand what you are saying and it makes perfect sense to me.
My point is, I think we need some more information in the comment rather than the two lines below that you propose. It doesn't matter to me if you drop the comments above, just make sure we understand what goes on here by giving more details, then I will be happy. :-)
* 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;
[...]
Kind regards Uffe