Commit 300ad899 authored by Daniel Kurtz's avatar Daniel Kurtz Committed by Ulf Hansson

mmc: sdhci-pci: Only do AMD tuning for HS200

Commit c31165d7 ("mmc: sdhci-pci: Add support for HS200 tuning mode
on AMD, eMMC-4.5.1") added a HS200 tuning method for use with AMD SDHCI
controllers.  As described in the commit subject, this tuning is specific
for HS200.  However, as implemented, this method is used for all host
timings, because platform_execute_tuning, if it exists, is called
unconditionally by sdhci_execute_tuning().  This breaks tuning when using
the AMD controller with, for example, a DDR50 SD card.

Instead, we can implement an amd execute_tuning wrapper callback, and
then conditionally do the HS200 specific tuning for HS200, and otherwise
call back to the standard sdhci_execute_tuning().
Signed-off-by: default avatarDaniel Kurtz <djkurtz@chromium.org>
Acked-by: default avatarShyam Sundar S K <Shyam-sundar.S-k@amd.com>
Acked-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Fixes: c31165d7 ("mmc: sdhci-pci: Add support for HS200 tuning mode on AMD, eMMC-4.5.1")
Cc: stable@vger.kernel.org # v4.11+
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent fc167daf
...@@ -1312,7 +1312,7 @@ static void amd_enable_manual_tuning(struct pci_dev *pdev) ...@@ -1312,7 +1312,7 @@ static void amd_enable_manual_tuning(struct pci_dev *pdev)
pci_write_config_dword(pdev, AMD_SD_MISC_CONTROL, val); pci_write_config_dword(pdev, AMD_SD_MISC_CONTROL, val);
} }
static int amd_execute_tuning(struct sdhci_host *host, u32 opcode) static int amd_execute_tuning_hs200(struct sdhci_host *host, u32 opcode)
{ {
struct sdhci_pci_slot *slot = sdhci_priv(host); struct sdhci_pci_slot *slot = sdhci_priv(host);
struct pci_dev *pdev = slot->chip->pdev; struct pci_dev *pdev = slot->chip->pdev;
...@@ -1351,6 +1351,27 @@ static int amd_execute_tuning(struct sdhci_host *host, u32 opcode) ...@@ -1351,6 +1351,27 @@ static int amd_execute_tuning(struct sdhci_host *host, u32 opcode)
return 0; return 0;
} }
static int amd_execute_tuning(struct mmc_host *mmc, u32 opcode)
{
struct sdhci_host *host = mmc_priv(mmc);
/* AMD requires custom HS200 tuning */
if (host->timing == MMC_TIMING_MMC_HS200)
return amd_execute_tuning_hs200(host, opcode);
/* Otherwise perform standard SDHCI tuning */
return sdhci_execute_tuning(mmc, opcode);
}
static int amd_probe_slot(struct sdhci_pci_slot *slot)
{
struct mmc_host_ops *ops = &slot->host->mmc_host_ops;
ops->execute_tuning = amd_execute_tuning;
return 0;
}
static int amd_probe(struct sdhci_pci_chip *chip) static int amd_probe(struct sdhci_pci_chip *chip)
{ {
struct pci_dev *smbus_dev; struct pci_dev *smbus_dev;
...@@ -1385,12 +1406,12 @@ static const struct sdhci_ops amd_sdhci_pci_ops = { ...@@ -1385,12 +1406,12 @@ static const struct sdhci_ops amd_sdhci_pci_ops = {
.set_bus_width = sdhci_set_bus_width, .set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset, .reset = sdhci_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling, .set_uhs_signaling = sdhci_set_uhs_signaling,
.platform_execute_tuning = amd_execute_tuning,
}; };
static const struct sdhci_pci_fixes sdhci_amd = { static const struct sdhci_pci_fixes sdhci_amd = {
.probe = amd_probe, .probe = amd_probe,
.ops = &amd_sdhci_pci_ops, .ops = &amd_sdhci_pci_ops,
.probe_slot = amd_probe_slot,
}; };
static const struct pci_device_id pci_ids[] = { static const struct pci_device_id pci_ids[] = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment