Other Parts Discussed in Thread: CSD, DRA829
Dear, expers
We're having some problems on tda4vm custom board as follows (sdk7.1):
Problem 1: When Setting eMMC Signal Voltage To 1.8V, Then The State Machine Will Be Broken
On some hardware boards with samsung automotive eMMC, we found the following kernel error messages when selecting HS200 mode:
mmc0: mmc_select_hs200 failed, error -110
mmc0: error -110 whilst initialising MMC card
The kernel code snippet is as follow:
static int mmc_select_hs200(struct mmc_card *card)
{
......
old_signal_voltage = host->ios.signal_voltage;
if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
/* If fails try again during next card power cycle */
if (err)
return err;
mmc_select_driver_type(card);
/*
* Set the bus width(4 or 8) with host's support and
* switch to HS200 mode if bus width is set successfully.
*/
err = mmc_select_bus_width(card);
if (err > 0) {
......
}
err:
if (err) {
/* fall back to the old signal voltage, if fails report error */
if (mmc_set_signal_voltage(host, old_signal_voltage))
err = -EIO;
pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host),
__func__, err);
}
return err;
}
This is because the mmc_set_signal_voltage() method will set the MMCSD0_HOST_CONTROL2 register's V1P8_SIGNAL_ENA bit field, this causes the following mmc_select_bus_width() method return time out error.
An introduction can be found through the description of V1P8_SIGNAL_ENA bit field
Host Driver can set this bit to 1h when Host Controller supports 1.8 V signaling (one of support bits is set to 1h: SDR50, SDR104 or DDR50 in the MMCSD0_CAPABILITIES register) and the card or device supports UHS-I.
It seems that there is no need to set this bit when using eMMC HS200/HS400 mode. To work around this work we implemented the sdhci_j721e_voltage_switch() method:
static int sdhci_j721e_voltage_switch(struct mmc_host *mmc,
struct mmc_ios *ios)
{
switch (ios->signal_voltage) {
case MMC_SIGNAL_VOLTAGE_180:
/*
* Plese don't switch to 1V8 as j721e MMCSD0, 5.1 doesn't
* actually refer to this setting to indicate the
* signal voltage and the state machine will be broken
* actually if we force to enable 1V8. That's something
* like broken quirk but we could work around here.
*/
return 0;
case MMC_SIGNAL_VOLTAGE_330:
case MMC_SIGNAL_VOLTAGE_120:
/* We don't support 3V3 and 1V2 */
break;
}
return -EINVAL;
}
static int sdhci_am654_probe(struct platform_device *pdev)
{
......
host->mmc_host_ops.execute_tuning = sdhci_am654_execute_tuning;
/* EXPERIMENTAL: From the TRM 12.3.6, we learned that the MMCSD0
* host controller does not support 3.3V, 3.3V and 1.2V.
* wsl, 09/07/2021.
*/
if (of_device_is_compatible(dev->of_node, "ti,j721e-sdhci-8bit"))
host->mmc_host_ops.start_signal_voltage_switch =
sdhci_j721e_voltage_switch;
......
}