* [PATCH v3 2/2] mmc: sdhci-acpi: Disable write protect detection on Acer Aspire Switch 10 (SW5-012)
2020-03-16 18:47 [PATCH v3 1/2] mmc: sdhci-acpi: Switch signal voltage back to 3.3V on suspend on external microSD on Lenovo Miix 320 Hans de Goede
@ 2020-03-16 18:47 ` Hans de Goede
2020-03-17 7:42 ` Adrian Hunter
2020-03-17 11:58 ` Ulf Hansson
2020-03-17 7:42 ` [PATCH v3 1/2] mmc: sdhci-acpi: Switch signal voltage back to 3.3V on suspend on external microSD on Lenovo Miix 320 Adrian Hunter
2020-03-17 11:58 ` Ulf Hansson
2 siblings, 2 replies; 6+ messages in thread
From: Hans de Goede @ 2020-03-16 18:47 UTC (permalink / raw)
To: Adrian Hunter, Ulf Hansson; +Cc: Hans de Goede, linux-mmc
On the Acer Aspire Switch 10 (SW5-012) microSD slot always reports the card
being write-protected even though microSD cards do not have a write-protect
switch at all.
Add a new DMI_QUIRK_SD_NO_WRITE_PROTECT quirk which when set sets
the MMC_CAP2_NO_WRITE_PROTECT flag on the controller for the external SD
slot; and add a DMI quirk table entry which selects this quirk for the
Acer SW5-012.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
Changes in v2:
- Drop the module option to allow overridig the quirks
---
drivers/mmc/host/sdhci-acpi.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
index b4c1b2367066..2a2173d953f5 100644
--- a/drivers/mmc/host/sdhci-acpi.c
+++ b/drivers/mmc/host/sdhci-acpi.c
@@ -80,6 +80,7 @@ struct sdhci_acpi_host {
enum {
DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP = BIT(0),
+ DMI_QUIRK_SD_NO_WRITE_PROTECT = BIT(1),
};
static inline void *sdhci_acpi_priv(struct sdhci_acpi_host *c)
@@ -671,6 +672,18 @@ static const struct dmi_system_id sdhci_acpi_quirks[] = {
},
.driver_data = (void *)DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP,
},
+ {
+ /*
+ * The Acer Aspire Switch 10 (SW5-012) microSD slot always
+ * reports the card being write-protected even though microSD
+ * cards do not have a write-protect switch at all.
+ */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"),
+ },
+ .driver_data = (void *)DMI_QUIRK_SD_NO_WRITE_PROTECT,
+ },
{} /* Terminating entry */
};
@@ -795,6 +808,9 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
if (quirks & DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP)
c->reset_signal_volt_on_suspend = true;
+
+ if (quirks & DMI_QUIRK_SD_NO_WRITE_PROTECT)
+ host->mmc->caps2 |= MMC_CAP2_NO_WRITE_PROTECT;
}
err = sdhci_setup_host(host);
--
2.25.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v3 2/2] mmc: sdhci-acpi: Disable write protect detection on Acer Aspire Switch 10 (SW5-012)
2020-03-16 18:47 ` [PATCH v3 2/2] mmc: sdhci-acpi: Disable write protect detection on Acer Aspire Switch 10 (SW5-012) Hans de Goede
@ 2020-03-17 7:42 ` Adrian Hunter
2020-03-17 11:58 ` Ulf Hansson
1 sibling, 0 replies; 6+ messages in thread
From: Adrian Hunter @ 2020-03-17 7:42 UTC (permalink / raw)
To: Hans de Goede, Ulf Hansson; +Cc: linux-mmc
On 16/03/20 8:47 pm, Hans de Goede wrote:
> On the Acer Aspire Switch 10 (SW5-012) microSD slot always reports the card
> being write-protected even though microSD cards do not have a write-protect
> switch at all.
>
> Add a new DMI_QUIRK_SD_NO_WRITE_PROTECT quirk which when set sets
> the MMC_CAP2_NO_WRITE_PROTECT flag on the controller for the external SD
> slot; and add a DMI quirk table entry which selects this quirk for the
> Acer SW5-012.
>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
> ---
> Changes in v2:
> - Drop the module option to allow overridig the quirks
> ---
> drivers/mmc/host/sdhci-acpi.c | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
>
> diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
> index b4c1b2367066..2a2173d953f5 100644
> --- a/drivers/mmc/host/sdhci-acpi.c
> +++ b/drivers/mmc/host/sdhci-acpi.c
> @@ -80,6 +80,7 @@ struct sdhci_acpi_host {
>
> enum {
> DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP = BIT(0),
> + DMI_QUIRK_SD_NO_WRITE_PROTECT = BIT(1),
> };
>
> static inline void *sdhci_acpi_priv(struct sdhci_acpi_host *c)
> @@ -671,6 +672,18 @@ static const struct dmi_system_id sdhci_acpi_quirks[] = {
> },
> .driver_data = (void *)DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP,
> },
> + {
> + /*
> + * The Acer Aspire Switch 10 (SW5-012) microSD slot always
> + * reports the card being write-protected even though microSD
> + * cards do not have a write-protect switch at all.
> + */
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
> + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"),
> + },
> + .driver_data = (void *)DMI_QUIRK_SD_NO_WRITE_PROTECT,
> + },
> {} /* Terminating entry */
> };
>
> @@ -795,6 +808,9 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
>
> if (quirks & DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP)
> c->reset_signal_volt_on_suspend = true;
> +
> + if (quirks & DMI_QUIRK_SD_NO_WRITE_PROTECT)
> + host->mmc->caps2 |= MMC_CAP2_NO_WRITE_PROTECT;
> }
>
> err = sdhci_setup_host(host);
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 2/2] mmc: sdhci-acpi: Disable write protect detection on Acer Aspire Switch 10 (SW5-012)
2020-03-16 18:47 ` [PATCH v3 2/2] mmc: sdhci-acpi: Disable write protect detection on Acer Aspire Switch 10 (SW5-012) Hans de Goede
2020-03-17 7:42 ` Adrian Hunter
@ 2020-03-17 11:58 ` Ulf Hansson
1 sibling, 0 replies; 6+ messages in thread
From: Ulf Hansson @ 2020-03-17 11:58 UTC (permalink / raw)
To: Hans de Goede; +Cc: Adrian Hunter, linux-mmc
On Mon, 16 Mar 2020 at 19:48, Hans de Goede <hdegoede@redhat.com> wrote:
>
> On the Acer Aspire Switch 10 (SW5-012) microSD slot always reports the card
> being write-protected even though microSD cards do not have a write-protect
> switch at all.
>
> Add a new DMI_QUIRK_SD_NO_WRITE_PROTECT quirk which when set sets
> the MMC_CAP2_NO_WRITE_PROTECT flag on the controller for the external SD
> slot; and add a DMI quirk table entry which selects this quirk for the
> Acer SW5-012.
>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Applied for fixes and by adding a stable tag, thanks!
Kind regards
Uffe
> ---
> Changes in v2:
> - Drop the module option to allow overridig the quirks
> ---
> drivers/mmc/host/sdhci-acpi.c | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
>
> diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
> index b4c1b2367066..2a2173d953f5 100644
> --- a/drivers/mmc/host/sdhci-acpi.c
> +++ b/drivers/mmc/host/sdhci-acpi.c
> @@ -80,6 +80,7 @@ struct sdhci_acpi_host {
>
> enum {
> DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP = BIT(0),
> + DMI_QUIRK_SD_NO_WRITE_PROTECT = BIT(1),
> };
>
> static inline void *sdhci_acpi_priv(struct sdhci_acpi_host *c)
> @@ -671,6 +672,18 @@ static const struct dmi_system_id sdhci_acpi_quirks[] = {
> },
> .driver_data = (void *)DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP,
> },
> + {
> + /*
> + * The Acer Aspire Switch 10 (SW5-012) microSD slot always
> + * reports the card being write-protected even though microSD
> + * cards do not have a write-protect switch at all.
> + */
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
> + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"),
> + },
> + .driver_data = (void *)DMI_QUIRK_SD_NO_WRITE_PROTECT,
> + },
> {} /* Terminating entry */
> };
>
> @@ -795,6 +808,9 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
>
> if (quirks & DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP)
> c->reset_signal_volt_on_suspend = true;
> +
> + if (quirks & DMI_QUIRK_SD_NO_WRITE_PROTECT)
> + host->mmc->caps2 |= MMC_CAP2_NO_WRITE_PROTECT;
> }
>
> err = sdhci_setup_host(host);
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 1/2] mmc: sdhci-acpi: Switch signal voltage back to 3.3V on suspend on external microSD on Lenovo Miix 320
2020-03-16 18:47 [PATCH v3 1/2] mmc: sdhci-acpi: Switch signal voltage back to 3.3V on suspend on external microSD on Lenovo Miix 320 Hans de Goede
2020-03-16 18:47 ` [PATCH v3 2/2] mmc: sdhci-acpi: Disable write protect detection on Acer Aspire Switch 10 (SW5-012) Hans de Goede
@ 2020-03-17 7:42 ` Adrian Hunter
2020-03-17 11:58 ` Ulf Hansson
2 siblings, 0 replies; 6+ messages in thread
From: Adrian Hunter @ 2020-03-17 7:42 UTC (permalink / raw)
To: Hans de Goede, Ulf Hansson; +Cc: linux-mmc, russianneuromancer
On 16/03/20 8:47 pm, Hans de Goede wrote:
> Based on a sample of 7 DSDTs from Cherry Trail devices using an AXP288
> PMIC depending on the design one of 2 possible LDOs on the PMIC is used
> for the MMC signalling voltage, either DLDO3 or GPIO1LDO (GPIO1 pin in
> low noise LDO mode).
>
> The Lenovo Miix 320-10ICR uses GPIO1LDO in the SHC1 ACPI device's DSM
> methods to set 3.3 or 1.8 signalling voltage and this appears to work
> as advertised, so presumably the device is actually using GPIO1LDO for
> the external microSD signalling voltage.
>
> But this device has a bug in the _PS0 method of the SHC1 ACPI device,
> the DSM remembers the last set signalling voltage and the _PS0 restores
> this after a (runtime) suspend-resume cycle, but it "restores" the voltage
> on DLDO3 instead of setting it on GPIO1LDO as the DSM method does. DLDO3
> is used for the LCD and setting it to 1.8V causes the LCD to go black.
>
> This commit works around this issue by calling the Intel DSM to reset the
> signal voltage to 3.3V after the host has been runtime suspended.
> This will make the _PS0 method reprogram the DLDO3 voltage to 3.3V, which
> leaves it at its original setting fixing the LCD going black.
>
> This commit adds and uses a DMI quirk mechanism to only trigger this
> workaround on the Lenovo Miix 320 while leaving the behavior of the
> driver unchanged on other devices.
>
> BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=111294
> BugLink: https://gitlab.freedesktop.org/drm/intel/issues/355
> Reported-by: russianneuromancer <russianneuromancer@ya.ru>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
> ---
> Changes in v3:
> - Drop code to restore 1.8 signal voltage on suspend, this is not necessary
> - Add an is_intel bool to sdhci_acpi_host instead of checking for:
> mmc_host_ops.start_signal_voltage_switch == intel_start_signal_voltage_switch
>
> Changes in v2:
> - Make the quirk reset the signal voltage to 3.3V at the end of the
> (runtime) suspend handler instead of disabling 1.8V modes
> - Drop the module option to allow overridig the quirks
> ---
> drivers/mmc/host/sdhci-acpi.c | 68 +++++++++++++++++++++++++++++++++--
> 1 file changed, 66 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
> index 9651dca6863e..b4c1b2367066 100644
> --- a/drivers/mmc/host/sdhci-acpi.c
> +++ b/drivers/mmc/host/sdhci-acpi.c
> @@ -23,6 +23,7 @@
> #include <linux/pm.h>
> #include <linux/pm_runtime.h>
> #include <linux/delay.h>
> +#include <linux/dmi.h>
>
> #include <linux/mmc/host.h>
> #include <linux/mmc/pm.h>
> @@ -72,9 +73,15 @@ struct sdhci_acpi_host {
> const struct sdhci_acpi_slot *slot;
> struct platform_device *pdev;
> bool use_runtime_pm;
> + bool is_intel;
> + bool reset_signal_volt_on_suspend;
> unsigned long private[0] ____cacheline_aligned;
> };
>
> +enum {
> + DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP = BIT(0),
> +};
> +
> static inline void *sdhci_acpi_priv(struct sdhci_acpi_host *c)
> {
> return (void *)c->private;
> @@ -391,6 +398,8 @@ static int intel_probe_slot(struct platform_device *pdev, struct acpi_device *ad
> host->mmc_host_ops.start_signal_voltage_switch =
> intel_start_signal_voltage_switch;
>
> + c->is_intel = true;
> +
> return 0;
> }
>
> @@ -647,6 +656,24 @@ static const struct acpi_device_id sdhci_acpi_ids[] = {
> };
> MODULE_DEVICE_TABLE(acpi, sdhci_acpi_ids);
>
> +static const struct dmi_system_id sdhci_acpi_quirks[] = {
> + {
> + /*
> + * The Lenovo Miix 320-10ICR has a bug in the _PS0 method of
> + * the SHC1 ACPI device, this bug causes it to reprogram the
> + * wrong LDO (DLDO3) to 1.8V if 1.8V modes are used and the
> + * card is (runtime) suspended + resumed. DLDO3 is used for
> + * the LCD and setting it to 1.8V causes the LCD to go black.
> + */
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
> + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
> + },
> + .driver_data = (void *)DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP,
> + },
> + {} /* Terminating entry */
> +};
> +
> static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(struct acpi_device *adev)
> {
> const struct sdhci_acpi_uid_slot *u;
> @@ -663,17 +690,23 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
> struct device *dev = &pdev->dev;
> const struct sdhci_acpi_slot *slot;
> struct acpi_device *device, *child;
> + const struct dmi_system_id *id;
> struct sdhci_acpi_host *c;
> struct sdhci_host *host;
> struct resource *iomem;
> resource_size_t len;
> size_t priv_size;
> + int quirks = 0;
> int err;
>
> device = ACPI_COMPANION(dev);
> if (!device)
> return -ENODEV;
>
> + id = dmi_first_match(sdhci_acpi_quirks);
> + if (id)
> + quirks = (long)id->driver_data;
> +
> slot = sdhci_acpi_get_slot(device);
>
> /* Power on the SDHCI controller and its children */
> @@ -759,6 +792,9 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
> dev_warn(dev, "failed to setup card detect gpio\n");
> c->use_runtime_pm = false;
> }
> +
> + if (quirks & DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP)
> + c->reset_signal_volt_on_suspend = true;
> }
>
> err = sdhci_setup_host(host);
> @@ -823,17 +859,39 @@ static int sdhci_acpi_remove(struct platform_device *pdev)
> return 0;
> }
>
> +static void __maybe_unused sdhci_acpi_reset_signal_voltage_if_needed(
> + struct device *dev)
> +{
> + struct sdhci_acpi_host *c = dev_get_drvdata(dev);
> + struct sdhci_host *host = c->host;
> +
> + if (c->is_intel && c->reset_signal_volt_on_suspend &&
> + host->mmc->ios.signal_voltage != MMC_SIGNAL_VOLTAGE_330) {
> + struct intel_host *intel_host = sdhci_acpi_priv(c);
> + unsigned int fn = INTEL_DSM_V33_SWITCH;
> + u32 result = 0;
> +
> + intel_dsm(intel_host, dev, fn, &result);
> + }
> +}
> +
> #ifdef CONFIG_PM_SLEEP
>
> static int sdhci_acpi_suspend(struct device *dev)
> {
> struct sdhci_acpi_host *c = dev_get_drvdata(dev);
> struct sdhci_host *host = c->host;
> + int ret;
>
> if (host->tuning_mode != SDHCI_TUNING_MODE_3)
> mmc_retune_needed(host->mmc);
>
> - return sdhci_suspend_host(host);
> + ret = sdhci_suspend_host(host);
> + if (ret)
> + return ret;
> +
> + sdhci_acpi_reset_signal_voltage_if_needed(dev);
> + return 0;
> }
>
> static int sdhci_acpi_resume(struct device *dev)
> @@ -853,11 +911,17 @@ static int sdhci_acpi_runtime_suspend(struct device *dev)
> {
> struct sdhci_acpi_host *c = dev_get_drvdata(dev);
> struct sdhci_host *host = c->host;
> + int ret;
>
> if (host->tuning_mode != SDHCI_TUNING_MODE_3)
> mmc_retune_needed(host->mmc);
>
> - return sdhci_runtime_suspend_host(host);
> + ret = sdhci_runtime_suspend_host(host);
> + if (ret)
> + return ret;
> +
> + sdhci_acpi_reset_signal_voltage_if_needed(dev);
> + return 0;
> }
>
> static int sdhci_acpi_runtime_resume(struct device *dev)
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 1/2] mmc: sdhci-acpi: Switch signal voltage back to 3.3V on suspend on external microSD on Lenovo Miix 320
2020-03-16 18:47 [PATCH v3 1/2] mmc: sdhci-acpi: Switch signal voltage back to 3.3V on suspend on external microSD on Lenovo Miix 320 Hans de Goede
2020-03-16 18:47 ` [PATCH v3 2/2] mmc: sdhci-acpi: Disable write protect detection on Acer Aspire Switch 10 (SW5-012) Hans de Goede
2020-03-17 7:42 ` [PATCH v3 1/2] mmc: sdhci-acpi: Switch signal voltage back to 3.3V on suspend on external microSD on Lenovo Miix 320 Adrian Hunter
@ 2020-03-17 11:58 ` Ulf Hansson
2 siblings, 0 replies; 6+ messages in thread
From: Ulf Hansson @ 2020-03-17 11:58 UTC (permalink / raw)
To: Hans de Goede; +Cc: Adrian Hunter, linux-mmc, russianneuromancer
On Mon, 16 Mar 2020 at 19:48, Hans de Goede <hdegoede@redhat.com> wrote:
>
> Based on a sample of 7 DSDTs from Cherry Trail devices using an AXP288
> PMIC depending on the design one of 2 possible LDOs on the PMIC is used
> for the MMC signalling voltage, either DLDO3 or GPIO1LDO (GPIO1 pin in
> low noise LDO mode).
>
> The Lenovo Miix 320-10ICR uses GPIO1LDO in the SHC1 ACPI device's DSM
> methods to set 3.3 or 1.8 signalling voltage and this appears to work
> as advertised, so presumably the device is actually using GPIO1LDO for
> the external microSD signalling voltage.
>
> But this device has a bug in the _PS0 method of the SHC1 ACPI device,
> the DSM remembers the last set signalling voltage and the _PS0 restores
> this after a (runtime) suspend-resume cycle, but it "restores" the voltage
> on DLDO3 instead of setting it on GPIO1LDO as the DSM method does. DLDO3
> is used for the LCD and setting it to 1.8V causes the LCD to go black.
>
> This commit works around this issue by calling the Intel DSM to reset the
> signal voltage to 3.3V after the host has been runtime suspended.
> This will make the _PS0 method reprogram the DLDO3 voltage to 3.3V, which
> leaves it at its original setting fixing the LCD going black.
>
> This commit adds and uses a DMI quirk mechanism to only trigger this
> workaround on the Lenovo Miix 320 while leaving the behavior of the
> driver unchanged on other devices.
>
> BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=111294
> BugLink: https://gitlab.freedesktop.org/drm/intel/issues/355
> Reported-by: russianneuromancer <russianneuromancer@ya.ru>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Applied for fixes and by adding a stable tag, thanks!
Kind regards
Uffe
> ---
> Changes in v3:
> - Drop code to restore 1.8 signal voltage on suspend, this is not necessary
> - Add an is_intel bool to sdhci_acpi_host instead of checking for:
> mmc_host_ops.start_signal_voltage_switch == intel_start_signal_voltage_switch
>
> Changes in v2:
> - Make the quirk reset the signal voltage to 3.3V at the end of the
> (runtime) suspend handler instead of disabling 1.8V modes
> - Drop the module option to allow overridig the quirks
> ---
> drivers/mmc/host/sdhci-acpi.c | 68 +++++++++++++++++++++++++++++++++--
> 1 file changed, 66 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
> index 9651dca6863e..b4c1b2367066 100644
> --- a/drivers/mmc/host/sdhci-acpi.c
> +++ b/drivers/mmc/host/sdhci-acpi.c
> @@ -23,6 +23,7 @@
> #include <linux/pm.h>
> #include <linux/pm_runtime.h>
> #include <linux/delay.h>
> +#include <linux/dmi.h>
>
> #include <linux/mmc/host.h>
> #include <linux/mmc/pm.h>
> @@ -72,9 +73,15 @@ struct sdhci_acpi_host {
> const struct sdhci_acpi_slot *slot;
> struct platform_device *pdev;
> bool use_runtime_pm;
> + bool is_intel;
> + bool reset_signal_volt_on_suspend;
> unsigned long private[0] ____cacheline_aligned;
> };
>
> +enum {
> + DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP = BIT(0),
> +};
> +
> static inline void *sdhci_acpi_priv(struct sdhci_acpi_host *c)
> {
> return (void *)c->private;
> @@ -391,6 +398,8 @@ static int intel_probe_slot(struct platform_device *pdev, struct acpi_device *ad
> host->mmc_host_ops.start_signal_voltage_switch =
> intel_start_signal_voltage_switch;
>
> + c->is_intel = true;
> +
> return 0;
> }
>
> @@ -647,6 +656,24 @@ static const struct acpi_device_id sdhci_acpi_ids[] = {
> };
> MODULE_DEVICE_TABLE(acpi, sdhci_acpi_ids);
>
> +static const struct dmi_system_id sdhci_acpi_quirks[] = {
> + {
> + /*
> + * The Lenovo Miix 320-10ICR has a bug in the _PS0 method of
> + * the SHC1 ACPI device, this bug causes it to reprogram the
> + * wrong LDO (DLDO3) to 1.8V if 1.8V modes are used and the
> + * card is (runtime) suspended + resumed. DLDO3 is used for
> + * the LCD and setting it to 1.8V causes the LCD to go black.
> + */
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
> + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
> + },
> + .driver_data = (void *)DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP,
> + },
> + {} /* Terminating entry */
> +};
> +
> static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(struct acpi_device *adev)
> {
> const struct sdhci_acpi_uid_slot *u;
> @@ -663,17 +690,23 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
> struct device *dev = &pdev->dev;
> const struct sdhci_acpi_slot *slot;
> struct acpi_device *device, *child;
> + const struct dmi_system_id *id;
> struct sdhci_acpi_host *c;
> struct sdhci_host *host;
> struct resource *iomem;
> resource_size_t len;
> size_t priv_size;
> + int quirks = 0;
> int err;
>
> device = ACPI_COMPANION(dev);
> if (!device)
> return -ENODEV;
>
> + id = dmi_first_match(sdhci_acpi_quirks);
> + if (id)
> + quirks = (long)id->driver_data;
> +
> slot = sdhci_acpi_get_slot(device);
>
> /* Power on the SDHCI controller and its children */
> @@ -759,6 +792,9 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
> dev_warn(dev, "failed to setup card detect gpio\n");
> c->use_runtime_pm = false;
> }
> +
> + if (quirks & DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP)
> + c->reset_signal_volt_on_suspend = true;
> }
>
> err = sdhci_setup_host(host);
> @@ -823,17 +859,39 @@ static int sdhci_acpi_remove(struct platform_device *pdev)
> return 0;
> }
>
> +static void __maybe_unused sdhci_acpi_reset_signal_voltage_if_needed(
> + struct device *dev)
> +{
> + struct sdhci_acpi_host *c = dev_get_drvdata(dev);
> + struct sdhci_host *host = c->host;
> +
> + if (c->is_intel && c->reset_signal_volt_on_suspend &&
> + host->mmc->ios.signal_voltage != MMC_SIGNAL_VOLTAGE_330) {
> + struct intel_host *intel_host = sdhci_acpi_priv(c);
> + unsigned int fn = INTEL_DSM_V33_SWITCH;
> + u32 result = 0;
> +
> + intel_dsm(intel_host, dev, fn, &result);
> + }
> +}
> +
> #ifdef CONFIG_PM_SLEEP
>
> static int sdhci_acpi_suspend(struct device *dev)
> {
> struct sdhci_acpi_host *c = dev_get_drvdata(dev);
> struct sdhci_host *host = c->host;
> + int ret;
>
> if (host->tuning_mode != SDHCI_TUNING_MODE_3)
> mmc_retune_needed(host->mmc);
>
> - return sdhci_suspend_host(host);
> + ret = sdhci_suspend_host(host);
> + if (ret)
> + return ret;
> +
> + sdhci_acpi_reset_signal_voltage_if_needed(dev);
> + return 0;
> }
>
> static int sdhci_acpi_resume(struct device *dev)
> @@ -853,11 +911,17 @@ static int sdhci_acpi_runtime_suspend(struct device *dev)
> {
> struct sdhci_acpi_host *c = dev_get_drvdata(dev);
> struct sdhci_host *host = c->host;
> + int ret;
>
> if (host->tuning_mode != SDHCI_TUNING_MODE_3)
> mmc_retune_needed(host->mmc);
>
> - return sdhci_runtime_suspend_host(host);
> + ret = sdhci_runtime_suspend_host(host);
> + if (ret)
> + return ret;
> +
> + sdhci_acpi_reset_signal_voltage_if_needed(dev);
> + return 0;
> }
>
> static int sdhci_acpi_runtime_resume(struct device *dev)
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 6+ messages in thread