23
23
#include <linux/pm.h>
24
24
#include <linux/pm_runtime.h>
25
25
#include <linux/delay.h>
26
+ #include <linux/dmi.h>
26
27
27
28
#include <linux/mmc/host.h>
28
29
#include <linux/mmc/pm.h>
@@ -72,9 +73,16 @@ struct sdhci_acpi_host {
72
73
const struct sdhci_acpi_slot * slot ;
73
74
struct platform_device * pdev ;
74
75
bool use_runtime_pm ;
76
+ bool is_intel ;
77
+ bool reset_signal_volt_on_suspend ;
75
78
unsigned long private [0 ] ____cacheline_aligned ;
76
79
};
77
80
81
+ enum {
82
+ DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP = BIT (0 ),
83
+ DMI_QUIRK_SD_NO_WRITE_PROTECT = BIT (1 ),
84
+ };
85
+
78
86
static inline void * sdhci_acpi_priv (struct sdhci_acpi_host * c )
79
87
{
80
88
return (void * )c -> private ;
@@ -391,6 +399,8 @@ static int intel_probe_slot(struct platform_device *pdev, struct acpi_device *ad
391
399
host -> mmc_host_ops .start_signal_voltage_switch =
392
400
intel_start_signal_voltage_switch ;
393
401
402
+ c -> is_intel = true;
403
+
394
404
return 0 ;
395
405
}
396
406
@@ -647,6 +657,36 @@ static const struct acpi_device_id sdhci_acpi_ids[] = {
647
657
};
648
658
MODULE_DEVICE_TABLE (acpi , sdhci_acpi_ids );
649
659
660
+ static const struct dmi_system_id sdhci_acpi_quirks [] = {
661
+ {
662
+ /*
663
+ * The Lenovo Miix 320-10ICR has a bug in the _PS0 method of
664
+ * the SHC1 ACPI device, this bug causes it to reprogram the
665
+ * wrong LDO (DLDO3) to 1.8V if 1.8V modes are used and the
666
+ * card is (runtime) suspended + resumed. DLDO3 is used for
667
+ * the LCD and setting it to 1.8V causes the LCD to go black.
668
+ */
669
+ .matches = {
670
+ DMI_MATCH (DMI_SYS_VENDOR , "LENOVO" ),
671
+ DMI_MATCH (DMI_PRODUCT_VERSION , "Lenovo MIIX 320-10ICR" ),
672
+ },
673
+ .driver_data = (void * )DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP ,
674
+ },
675
+ {
676
+ /*
677
+ * The Acer Aspire Switch 10 (SW5-012) microSD slot always
678
+ * reports the card being write-protected even though microSD
679
+ * cards do not have a write-protect switch at all.
680
+ */
681
+ .matches = {
682
+ DMI_MATCH (DMI_SYS_VENDOR , "Acer" ),
683
+ DMI_MATCH (DMI_PRODUCT_NAME , "Aspire SW5-012" ),
684
+ },
685
+ .driver_data = (void * )DMI_QUIRK_SD_NO_WRITE_PROTECT ,
686
+ },
687
+ {} /* Terminating entry */
688
+ };
689
+
650
690
static const struct sdhci_acpi_slot * sdhci_acpi_get_slot (struct acpi_device * adev )
651
691
{
652
692
const struct sdhci_acpi_uid_slot * u ;
@@ -663,17 +703,23 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
663
703
struct device * dev = & pdev -> dev ;
664
704
const struct sdhci_acpi_slot * slot ;
665
705
struct acpi_device * device , * child ;
706
+ const struct dmi_system_id * id ;
666
707
struct sdhci_acpi_host * c ;
667
708
struct sdhci_host * host ;
668
709
struct resource * iomem ;
669
710
resource_size_t len ;
670
711
size_t priv_size ;
712
+ int quirks = 0 ;
671
713
int err ;
672
714
673
715
device = ACPI_COMPANION (dev );
674
716
if (!device )
675
717
return - ENODEV ;
676
718
719
+ id = dmi_first_match (sdhci_acpi_quirks );
720
+ if (id )
721
+ quirks = (long )id -> driver_data ;
722
+
677
723
slot = sdhci_acpi_get_slot (device );
678
724
679
725
/* Power on the SDHCI controller and its children */
@@ -759,6 +805,12 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
759
805
dev_warn (dev , "failed to setup card detect gpio\n" );
760
806
c -> use_runtime_pm = false;
761
807
}
808
+
809
+ if (quirks & DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP )
810
+ c -> reset_signal_volt_on_suspend = true;
811
+
812
+ if (quirks & DMI_QUIRK_SD_NO_WRITE_PROTECT )
813
+ host -> mmc -> caps2 |= MMC_CAP2_NO_WRITE_PROTECT ;
762
814
}
763
815
764
816
err = sdhci_setup_host (host );
@@ -823,17 +875,39 @@ static int sdhci_acpi_remove(struct platform_device *pdev)
823
875
return 0 ;
824
876
}
825
877
878
+ static void __maybe_unused sdhci_acpi_reset_signal_voltage_if_needed (
879
+ struct device * dev )
880
+ {
881
+ struct sdhci_acpi_host * c = dev_get_drvdata (dev );
882
+ struct sdhci_host * host = c -> host ;
883
+
884
+ if (c -> is_intel && c -> reset_signal_volt_on_suspend &&
885
+ host -> mmc -> ios .signal_voltage != MMC_SIGNAL_VOLTAGE_330 ) {
886
+ struct intel_host * intel_host = sdhci_acpi_priv (c );
887
+ unsigned int fn = INTEL_DSM_V33_SWITCH ;
888
+ u32 result = 0 ;
889
+
890
+ intel_dsm (intel_host , dev , fn , & result );
891
+ }
892
+ }
893
+
826
894
#ifdef CONFIG_PM_SLEEP
827
895
828
896
static int sdhci_acpi_suspend (struct device * dev )
829
897
{
830
898
struct sdhci_acpi_host * c = dev_get_drvdata (dev );
831
899
struct sdhci_host * host = c -> host ;
900
+ int ret ;
832
901
833
902
if (host -> tuning_mode != SDHCI_TUNING_MODE_3 )
834
903
mmc_retune_needed (host -> mmc );
835
904
836
- return sdhci_suspend_host (host );
905
+ ret = sdhci_suspend_host (host );
906
+ if (ret )
907
+ return ret ;
908
+
909
+ sdhci_acpi_reset_signal_voltage_if_needed (dev );
910
+ return 0 ;
837
911
}
838
912
839
913
static int sdhci_acpi_resume (struct device * dev )
@@ -853,11 +927,17 @@ static int sdhci_acpi_runtime_suspend(struct device *dev)
853
927
{
854
928
struct sdhci_acpi_host * c = dev_get_drvdata (dev );
855
929
struct sdhci_host * host = c -> host ;
930
+ int ret ;
856
931
857
932
if (host -> tuning_mode != SDHCI_TUNING_MODE_3 )
858
933
mmc_retune_needed (host -> mmc );
859
934
860
- return sdhci_runtime_suspend_host (host );
935
+ ret = sdhci_runtime_suspend_host (host );
936
+ if (ret )
937
+ return ret ;
938
+
939
+ sdhci_acpi_reset_signal_voltage_if_needed (dev );
940
+ return 0 ;
861
941
}
862
942
863
943
static int sdhci_acpi_runtime_resume (struct device * dev )
0 commit comments