Re: [PATCH] mmc: sdhci-pci: disable intel voltage switch if unsupported

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 16/11/18 6:57 PM, Anisse Astier wrote:
> Hi Adrian,
> 
> On Fri, Nov 16, 2018 at 04:01:36PM +0200, Adrian Hunter wrote:
>> On 16/11/18 11:50 AM, Adrian Hunter wrote:
>>> On 16/11/18 11:37 AM, Anisse Astier wrote:
>>>> Hi Adrian, 
>>>>
>>>> On Thu, Nov 08, 2018 at 05:43:32PM +0000, Hunter, Adrian wrote:
>>>>> [snip]
>>>>> I found some time today.  It seems that the ACPI _PS3 method is failing to save the tuning value.
>>>>> That results in a CRC error, but the driver does not recover very gracefully.
>>>>>
>>>>> I will look at making a patch for the driver recovery, but also add some diagnostics prints to the ACPI DSDT to try to figure out what is going wrong there.
>>>>>
>>>>>
>>>>
>>>> Have you had the time to look at what diagnostics could be added ?
>>>
>>> I have a patch, but I am still testing it.
>>>
>>
>> Please try the attached patch
> 
>> From 5c33302367e7852aa0a723e311b1749bea59f055 Mon Sep 17 00:00:00 2001
>> From: Adrian Hunter <adrian.hunter@xxxxxxxxx>
>> Date: Fri, 16 Nov 2018 14:02:12 +0200
>> Subject: [PATCH] mmc: sdhci-pci: Workaround GLK firmware failing to restore
>>  the tuning value
>>
>> GLK firmware can indicate that the tuning value will be restored after
>> runtime suspend, but not actually do that. Add a workaround that detects
>> such cases, and lets the driver do re-tuning instead.
>>
> 
> This looks like it solves the issue. Please find the boot log here:
> 
> https://anisse.astier.eu/static/dmesg-sdhci-glk-workaround.txt.xz
> 
> We still have I/O errors I don't understand, but no more long CQE
> timeouts.

Please try this patch instead.
>From ff445c899af814f0623ef191213b9d7ddb51aa69 Mon Sep 17 00:00:00 2001
From: Adrian Hunter <adrian.hunter@xxxxxxxxx>
Date: Fri, 16 Nov 2018 14:02:12 +0200
Subject: [PATCH V2] mmc: sdhci-pci: Workaround GLK firmware failing to restore
 the tuning value

GLK firmware can indicate that the tuning value will be restored after
runtime suspend, but not actually do that. Add a workaround that detects
such cases, and lets the driver do re-tuning instead.

Signed-off-by: Adrian Hunter <adrian.hunter@xxxxxxxxx>
---
 drivers/mmc/host/sdhci-pci-core.c | 79 ++++++++++++++++++++++++++++++-
 1 file changed, 77 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index 7bfd366d970d..f5176d974a88 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -12,6 +12,7 @@
  *     - JMicron (hardware and technical support)
  */
 
+#include <linux/bitfield.h>
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/highmem.h>
@@ -462,6 +463,9 @@ struct intel_host {
 	u32	dsm_fns;
 	int	drv_strength;
 	bool	d3_retune;
+	bool	rpm_retune_ok;
+	u32	glk_rx_ctrl1;
+	u32	glk_tun_val;
 };
 
 static const guid_t intel_dsm_guid =
@@ -791,6 +795,77 @@ static int glk_emmc_add_host(struct sdhci_pci_slot *slot)
 	return ret;
 }
 
+#ifdef CONFIG_PM
+#define GLK_RX_CTRL1	0x834
+#define GLK_TUN_VAL	0x840
+#define GLK_PATH_PLL	GENMASK(13, 8)
+#define GLK_DLY		GENMASK(6, 0)
+/* Workaround firmware failing to restore the tuning value */
+static void glk_rpm_retune_wa(struct sdhci_pci_chip *chip, bool susp)
+{
+	struct sdhci_pci_slot *slot = chip->slots[0];
+	struct intel_host *intel_host = sdhci_pci_priv(slot);
+	struct sdhci_host *host = slot->host;
+	u32 glk_rx_ctrl1;
+	u32 glk_tun_val;
+	u32 dly;
+
+	if (intel_host->rpm_retune_ok || !mmc_can_retune(host->mmc))
+		return;
+
+	glk_rx_ctrl1 = sdhci_readl(host, GLK_RX_CTRL1);
+	glk_tun_val = sdhci_readl(host, GLK_TUN_VAL);
+
+	if (susp) {
+		intel_host->glk_rx_ctrl1 = glk_rx_ctrl1;
+		intel_host->glk_tun_val = glk_tun_val;
+		return;
+	}
+
+	if (!intel_host->glk_tun_val)
+		return;
+
+	if (glk_rx_ctrl1 != intel_host->glk_rx_ctrl1) {
+		intel_host->rpm_retune_ok = true;
+		return;
+	}
+
+	dly = FIELD_PREP(GLK_DLY, FIELD_GET(GLK_PATH_PLL, glk_rx_ctrl1) +
+				  (intel_host->glk_tun_val << 1));
+	if (dly == FIELD_GET(GLK_DLY, glk_rx_ctrl1))
+		return;
+
+	glk_rx_ctrl1 = (glk_rx_ctrl1 & ~GLK_DLY) | dly;
+	sdhci_writel(host, glk_rx_ctrl1, GLK_RX_CTRL1);
+
+	intel_host->rpm_retune_ok = true;
+	chip->rpm_retune = true;
+	mmc_retune_needed(host->mmc);
+	pr_info("%s: Requiring re-tune after rpm resume", mmc_hostname(host->mmc));
+}
+
+static void glk_rpm_retune_chk(struct sdhci_pci_chip *chip, bool susp)
+{
+	if (chip->pdev->device == PCI_DEVICE_ID_INTEL_GLK_EMMC &&
+	    !chip->rpm_retune)
+		glk_rpm_retune_wa(chip, susp);
+}
+
+static int glk_runtime_suspend(struct sdhci_pci_chip *chip)
+{
+	glk_rpm_retune_chk(chip, true);
+
+	return sdhci_cqhci_runtime_suspend(chip);
+}
+
+static int glk_runtime_resume(struct sdhci_pci_chip *chip)
+{
+	glk_rpm_retune_chk(chip, false);
+
+	return sdhci_cqhci_runtime_resume(chip);
+}
+#endif
+
 #ifdef CONFIG_ACPI
 static int ni_set_max_freq(struct sdhci_pci_slot *slot)
 {
@@ -879,8 +954,8 @@ static const struct sdhci_pci_fixes sdhci_intel_glk_emmc = {
 	.resume			= sdhci_cqhci_resume,
 #endif
 #ifdef CONFIG_PM
-	.runtime_suspend	= sdhci_cqhci_runtime_suspend,
-	.runtime_resume		= sdhci_cqhci_runtime_resume,
+	.runtime_suspend	= glk_runtime_suspend,
+	.runtime_resume		= glk_runtime_resume,
 #endif
 	.quirks			= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
 	.quirks2		= SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
-- 
2.17.1


[Index of Archives]     [Linux Memonry Technology]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux