| @@ -21,6 +21,7 @@ · 20 unmodified lines |
| 21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
| 22 | #include <linux/iopoll.h> | 22 | #include <linux/iopoll.h> |
| 23 | #include <linux/gpio.h> | 23 | #include <linux/gpio.h> |
| | 24 | #include <linux/gpio/machine.h> |
| 24 | #include <linux/pm_runtime.h> | 25 | #include <linux/pm_runtime.h> |
| 25 | #include <linux/pm_qos.h> | 26 | #include <linux/pm_qos.h> |
| 26 | #include <linux/debugfs.h> | 27 | #include <linux/debugfs.h> |
| @@ -1236,6 +1237,29 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { · 1209 unmodified lines |
| 1236 | .priv_size = sizeof(struct intel_host), | 1237 | .priv_size = sizeof(struct intel_host), |
| 1237 | }; | 1238 | }; |
| 1238 | | 1239 | |
| | 1240 | /* DMI quirks for devices with missing or broken CD GPIO info */ |
| | 1241 | static const struct gpiod_lookup_table vexia_edu_atla10_cd_gpios = { |
| | 1242 | .dev_id = "0000:00:12.0", |
| | 1243 | .table = { |
| | 1244 | GPIO_LOOKUP("INT33FC:00", 38, "cd", GPIO_ACTIVE_HIGH), |
| | 1245 | { } |
| | 1246 | }, |
| | 1247 | }; |
| | 1248 | |
| | 1249 | static const struct dmi_system_id sdhci_intel_byt_cd_gpio_override[] = { |
| | 1250 | { |
| | 1251 | /* Vexia Edu Atla 10 tablet 9V version */ |
| | 1252 | .matches = { |
| | 1253 | DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), |
| | 1254 | DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), |
| | 1255 | /* Above strings are too generic, also match on BIOS date */ |
| | 1256 | DMI_MATCH(DMI_BIOS_DATE, "08/25/2014"), |
| | 1257 | }, |
| | 1258 | .driver_data = (void *)&vexia_edu_atla10_cd_gpios, |
| | 1259 | }, |
| | 1260 | { } |
| | 1261 | }; |
| | 1262 | |
| 1239 | static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { | 1263 | static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { |
| 1240 | #ifdef CONFIG_PM_SLEEP | 1264 | #ifdef CONFIG_PM_SLEEP |
| 1241 | .resume = byt_resume, | 1265 | .resume = byt_resume, |
| @@ -1254,6 +1278,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { · 12 unmodified lines |
| 1254 | .add_host = byt_add_host, | 1278 | .add_host = byt_add_host, |
| 1255 | .remove_slot = byt_remove_slot, | 1279 | .remove_slot = byt_remove_slot, |
| 1256 | .ops = &sdhci_intel_byt_ops, | 1280 | .ops = &sdhci_intel_byt_ops, |
| | 1281 | .cd_gpio_override = sdhci_intel_byt_cd_gpio_override, |
| 1257 | .priv_size = sizeof(struct intel_host), | 1282 | .priv_size = sizeof(struct intel_host), |
| 1258 | }; | 1283 | }; |
| 1259 | | 1284 | |
| @@ -2055,6 +2080,42 @@ static const struct dev_pm_ops sdhci_pci_pm_ops = { · 795 unmodified lines |
| 2055 | * * | 2080 | * * |
| 2056 | \*****************************************************************************/ | 2081 | \*****************************************************************************/ |
| 2057 | | 2082 | |
| | 2083 | static struct gpiod_lookup_table *sdhci_pci_add_gpio_lookup_table( |
| | 2084 | struct sdhci_pci_chip *chip) |
| | 2085 | { |
| | 2086 | struct gpiod_lookup_table *cd_gpio_lookup_table; |
| | 2087 | const struct dmi_system_id *dmi_id = NULL; |
| | 2088 | size_t count; |
| | 2089 | |
| | 2090 | if (chip->fixes && chip->fixes->cd_gpio_override) |
| | 2091 | dmi_id = dmi_first_match(chip->fixes->cd_gpio_override); |
| | 2092 | |
| | 2093 | if (!dmi_id) |
| | 2094 | return NULL; |
| | 2095 | |
| | 2096 | cd_gpio_lookup_table = dmi_id->driver_data; |
| | 2097 | for (count = 0; cd_gpio_lookup_table->table[count].key; count++) |
| | 2098 | ; |
| | 2099 | |
| | 2100 | cd_gpio_lookup_table = kmemdup(dmi_id->driver_data, |
| | 2101 | /* count + 1 terminating entry */ |
| | 2102 | struct_size(cd_gpio_lookup_table, table, count + 1), |
| | 2103 | GFP_KERNEL); |
| | 2104 | if (!cd_gpio_lookup_table) |
| | 2105 | return ERR_PTR(-ENOMEM); |
| | 2106 | |
| | 2107 | gpiod_add_lookup_table(cd_gpio_lookup_table); |
| | 2108 | return cd_gpio_lookup_table; |
| | 2109 | } |
| | 2110 | |
| | 2111 | static void sdhci_pci_remove_gpio_lookup_table(struct gpiod_lookup_table *lookup_table) |
| | 2112 | { |
| | 2113 | if (lookup_table) { |
| | 2114 | gpiod_remove_lookup_table(lookup_table); |
| | 2115 | kfree(lookup_table); |
| | 2116 | } |
| | 2117 | } |
| | 2118 | |
| 2058 | static struct sdhci_pci_slot *sdhci_pci_probe_slot( | 2119 | static struct sdhci_pci_slot *sdhci_pci_probe_slot( |
| 2059 | struct pci_dev *pdev, struct sdhci_pci_chip *chip, int first_bar, | 2120 | struct pci_dev *pdev, struct sdhci_pci_chip *chip, int first_bar, |
| 2060 | int slotno) | 2121 | int slotno) |
| @@ -2130,8 +2191,19 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot( · 69 unmodified lines |
| 2130 | device_init_wakeup(&pdev->dev, true); | 2191 | device_init_wakeup(&pdev->dev, true); |
| 2131 | | 2192 | |
| 2132 | if (slot->cd_idx >= 0) { | 2193 | if (slot->cd_idx >= 0) { |
| | 2194 | struct gpiod_lookup_table *cd_gpio_lookup_table; |
| | 2195 | |
| | 2196 | cd_gpio_lookup_table = sdhci_pci_add_gpio_lookup_table(chip); |
| | 2197 | if (IS_ERR(cd_gpio_lookup_table)) { |
| | 2198 | ret = PTR_ERR(cd_gpio_lookup_table); |
| | 2199 | goto remove; |
| | 2200 | } |
| | 2201 | |
| 2133 | ret = mmc_gpiod_request_cd(host->mmc, "cd", slot->cd_idx, | 2202 | ret = mmc_gpiod_request_cd(host->mmc, "cd", slot->cd_idx, |
| 2134 | slot->cd_override_level, 0); | 2203 | slot->cd_override_level, 0); |
| | 2204 | |
| | 2205 | sdhci_pci_remove_gpio_lookup_table(cd_gpio_lookup_table); |
| | 2206 | |
| 2135 | if (ret && ret != -EPROBE_DEFER) | 2207 | if (ret && ret != -EPROBE_DEFER) |
| 2136 | ret = mmc_gpiod_request_cd(host->mmc, NULL, | 2208 | ret = mmc_gpiod_request_cd(host->mmc, NULL, |
| 2137 | slot->cd_idx, | 2209 | slot->cd_idx, |