Commit 51ced59c authored by Adrian Hunter's avatar Adrian Hunter Committed by Ulf Hansson

mmc: sdhci-pci: Use ACPI DSM to get driver strength for some Intel devices

Make use  of an Intel ACPI _DSM that provides eMMC driver strength.
Signed-off-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Tested-by: default avatarLudovic Desroches <ludovic.desroches@microchip.com>
parent c959a6b0
...@@ -261,11 +261,13 @@ static const struct sdhci_pci_fixes sdhci_intel_pch_sdio = { ...@@ -261,11 +261,13 @@ static const struct sdhci_pci_fixes sdhci_intel_pch_sdio = {
enum { enum {
INTEL_DSM_FNS = 0, INTEL_DSM_FNS = 0,
INTEL_DSM_DRV_STRENGTH = 9,
INTEL_DSM_D3_RETUNE = 10, INTEL_DSM_D3_RETUNE = 10,
}; };
struct intel_host { struct intel_host {
u32 dsm_fns; u32 dsm_fns;
int drv_strength;
bool d3_retune; bool d3_retune;
}; };
...@@ -326,6 +328,9 @@ static void intel_dsm_init(struct intel_host *intel_host, struct device *dev, ...@@ -326,6 +328,9 @@ static void intel_dsm_init(struct intel_host *intel_host, struct device *dev,
pr_debug("%s: DSM function mask %#x\n", pr_debug("%s: DSM function mask %#x\n",
mmc_hostname(mmc), intel_host->dsm_fns); mmc_hostname(mmc), intel_host->dsm_fns);
err = intel_dsm(intel_host, dev, INTEL_DSM_DRV_STRENGTH, &val);
intel_host->drv_strength = err ? 0 : val;
err = intel_dsm(intel_host, dev, INTEL_DSM_D3_RETUNE, &val); err = intel_dsm(intel_host, dev, INTEL_DSM_D3_RETUNE, &val);
intel_host->d3_retune = err ? true : !!val; intel_host->d3_retune = err ? true : !!val;
} }
...@@ -345,67 +350,15 @@ static void sdhci_pci_int_hw_reset(struct sdhci_host *host) ...@@ -345,67 +350,15 @@ static void sdhci_pci_int_hw_reset(struct sdhci_host *host)
usleep_range(300, 1000); usleep_range(300, 1000);
} }
static int spt_select_drive_strength(struct sdhci_host *host, static int intel_select_drive_strength(struct mmc_card *card,
struct mmc_card *card, unsigned int max_dtr, int host_drv,
unsigned int max_dtr, int card_drv, int *drv_type)
int host_drv, int card_drv, int *drv_type)
{
int drive_strength;
if (sdhci_pci_spt_drive_strength > 0)
drive_strength = sdhci_pci_spt_drive_strength & 0xf;
else
drive_strength = 0; /* Default 50-ohm */
if ((mmc_driver_type_mask(drive_strength) & card_drv) == 0)
drive_strength = 0; /* Default 50-ohm */
return drive_strength;
}
/* Try to read the drive strength from the card */
static void spt_read_drive_strength(struct sdhci_host *host)
{ {
u32 val, i, t; struct sdhci_host *host = mmc_priv(card->host);
u16 m; struct sdhci_pci_slot *slot = sdhci_priv(host);
struct intel_host *intel_host = sdhci_pci_priv(slot);
if (sdhci_pci_spt_drive_strength)
return;
sdhci_pci_spt_drive_strength = -1;
m = sdhci_readw(host, SDHCI_HOST_CONTROL2) & 0x7;
if (m != 3 && m != 5)
return;
val = sdhci_readl(host, SDHCI_PRESENT_STATE);
if (val & 0x3)
return;
sdhci_writel(host, 0x007f0023, SDHCI_INT_ENABLE);
sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
sdhci_writew(host, 0x10, SDHCI_TRANSFER_MODE);
sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL);
sdhci_writew(host, 512, SDHCI_BLOCK_SIZE);
sdhci_writew(host, 1, SDHCI_BLOCK_COUNT);
sdhci_writel(host, 0, SDHCI_ARGUMENT);
sdhci_writew(host, 0x83b, SDHCI_COMMAND);
for (i = 0; i < 1000; i++) {
val = sdhci_readl(host, SDHCI_INT_STATUS);
if (val & 0xffff8000)
return;
if (val & 0x20)
break;
udelay(1);
}
val = sdhci_readl(host, SDHCI_PRESENT_STATE);
if (!(val & 0x800))
return;
for (i = 0; i < 47; i++)
val = sdhci_readl(host, SDHCI_BUFFER);
t = val & 0xf00;
if (t != 0x200 && t != 0x300)
return;
sdhci_pci_spt_drive_strength = 0x10 | ((val >> 12) & 0xf); return intel_host->drv_strength;
} }
static int bxt_get_cd(struct mmc_host *mmc) static int bxt_get_cd(struct mmc_host *mmc)
...@@ -451,10 +404,8 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot) ...@@ -451,10 +404,8 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
slot->hw_reset = sdhci_pci_int_hw_reset; slot->hw_reset = sdhci_pci_int_hw_reset;
if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BSW_EMMC) if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BSW_EMMC)
slot->host->timeout_clk = 1000; /* 1000 kHz i.e. 1 MHz */ slot->host->timeout_clk = 1000; /* 1000 kHz i.e. 1 MHz */
if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_SPT_EMMC) { slot->host->mmc_host_ops.select_drive_strength =
spt_read_drive_strength(slot->host); intel_select_drive_strength;
slot->select_drive_strength = spt_select_drive_strength;
}
return 0; return 0;
} }
......
...@@ -3,6 +3,3 @@ ...@@ -3,6 +3,3 @@
struct sdhci_pci_data *(*sdhci_pci_get_data)(struct pci_dev *pdev, int slotno); struct sdhci_pci_data *(*sdhci_pci_get_data)(struct pci_dev *pdev, int slotno);
EXPORT_SYMBOL_GPL(sdhci_pci_get_data); EXPORT_SYMBOL_GPL(sdhci_pci_get_data);
int sdhci_pci_spt_drive_strength;
EXPORT_SYMBOL_GPL(sdhci_pci_spt_drive_strength);
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