Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mmc: sdhci-acpi: support runtime PM for ACPI HID 80860F14 SD cards

Enable runtime PM for ACPI HID 80860F14 SD cards, adding support for
card detect GPIO.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Chris Ball <cjb@laptop.org>

authored by

Adrian Hunter and committed by
Chris Ball
a61abe6e f0710a55

+63 -1
+63 -1
drivers/mmc/host/sdhci-acpi.c
··· 31 31 #include <linux/bitops.h> 32 32 #include <linux/types.h> 33 33 #include <linux/err.h> 34 + #include <linux/gpio.h> 34 35 #include <linux/interrupt.h> 35 36 #include <linux/acpi.h> 37 + #include <linux/acpi_gpio.h> 36 38 #include <linux/pm.h> 37 39 #include <linux/pm_runtime.h> 38 40 ··· 103 101 }; 104 102 105 103 static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = { 104 + .flags = SDHCI_ACPI_SD_CD | SDHCI_ACPI_RUNTIME_PM, 105 + .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON, 106 106 }; 107 107 108 108 struct sdhci_acpi_uid_slot { ··· 165 161 return slot; 166 162 } 167 163 164 + #ifdef CONFIG_PM_RUNTIME 165 + 166 + static irqreturn_t sdhci_acpi_sd_cd(int irq, void *dev_id) 167 + { 168 + mmc_detect_change(dev_id, msecs_to_jiffies(200)); 169 + return IRQ_HANDLED; 170 + } 171 + 172 + static int sdhci_acpi_add_own_cd(struct device *dev, int gpio, 173 + struct mmc_host *mmc) 174 + { 175 + unsigned long flags; 176 + int err, irq; 177 + 178 + if (gpio < 0) { 179 + err = gpio; 180 + goto out; 181 + } 182 + 183 + err = devm_gpio_request_one(dev, gpio, GPIOF_DIR_IN, "sd_cd"); 184 + if (err) 185 + goto out; 186 + 187 + irq = gpio_to_irq(gpio); 188 + if (irq < 0) 189 + goto out_free; 190 + 191 + flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; 192 + err = devm_request_irq(dev, irq, sdhci_acpi_sd_cd, flags, "sd_cd", mmc); 193 + if (err) 194 + goto out_free; 195 + 196 + return 0; 197 + 198 + out_free: 199 + devm_gpio_free(dev, gpio); 200 + out: 201 + dev_warn(dev, "failed to setup card detect wake up\n"); 202 + return err; 203 + } 204 + 205 + #else 206 + 207 + static int sdhci_acpi_add_own_cd(struct device *dev, int gpio, 208 + struct mmc_host *mmc) 209 + { 210 + return 0; 211 + } 212 + 213 + #endif 214 + 168 215 static int sdhci_acpi_probe(struct platform_device *pdev) 169 216 { 170 217 struct device *dev = &pdev->dev; ··· 226 171 struct resource *iomem; 227 172 resource_size_t len; 228 173 const char *hid; 229 - int err; 174 + int err, gpio; 230 175 231 176 if (acpi_bus_get_device(handle, &device)) 232 177 return -ENODEV; ··· 250 195 host = sdhci_alloc_host(dev, sizeof(struct sdhci_acpi_host)); 251 196 if (IS_ERR(host)) 252 197 return PTR_ERR(host); 198 + 199 + gpio = acpi_get_gpio_by_index(dev, 0, NULL); 253 200 254 201 c = sdhci_priv(host); 255 202 c->host = host; ··· 307 250 err = sdhci_add_host(host); 308 251 if (err) 309 252 goto err_free; 253 + 254 + if (sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD)) { 255 + if (sdhci_acpi_add_own_cd(dev, gpio, host->mmc)) 256 + c->use_runtime_pm = false; 257 + } 310 258 311 259 if (c->use_runtime_pm) { 312 260 pm_runtime_set_active(dev);