On 16/08/18 07:48, Wang Dongsheng wrote: > After host requests RESET_FOR_ALL action, the hardware output an > interrupt for OS and waiting for the OS to approve. > > Before writing this fix, ACPI GED has handled the interrupt. But > the ACPI GED belongs to a slow process, and sometimes the handling > process time is more than 100ms(Mutex wait more than 100ms). So > drop the GED solution and add this quirk fix. > > Signed-off-by: Wang Dongsheng <dongsheng.wang@xxxxxxxxxxxxxxxx> Acked-by: Adrian Hunter <adrian.hunter@xxxxxxxxx> > --- > drivers/mmc/host/sdhci-acpi.c | 60 +++++++++++++++++++++++++++++++++++ > 1 file changed, 60 insertions(+) > > diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c > index c61109f7b793..82c9b9326e9e 100644 > --- a/drivers/mmc/host/sdhci-acpi.c > +++ b/drivers/mmc/host/sdhci-acpi.c > @@ -471,10 +471,70 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = { > .priv_size = sizeof(struct intel_host), > }; > > +#define VENDOR_SPECIFIC_PWRCTL_CLEAR_REG 0x1a8 > +#define VENDOR_SPECIFIC_PWRCTL_CTL_REG 0x1ac > +static irqreturn_t sdhci_acpi_qcom_handler(int irq, void *ptr) > +{ > + struct sdhci_host *host = ptr; > + > + sdhci_writel(host, 0x3, VENDOR_SPECIFIC_PWRCTL_CLEAR_REG); > + sdhci_writel(host, 0x1, VENDOR_SPECIFIC_PWRCTL_CTL_REG); > + > + return IRQ_HANDLED; > +} > + > +static int qcom_probe_slot(struct platform_device *pdev, const char *hid, > + const char *uid) > +{ > + struct sdhci_acpi_host *c = platform_get_drvdata(pdev); > + struct sdhci_host *host = c->host; > + int *irq = sdhci_acpi_priv(c); > + > + *irq = -EINVAL; > + > + if (strcmp(hid, "QCOM8051")) > + return 0; > + > + *irq = platform_get_irq(pdev, 1); > + if (*irq < 0) > + return 0; > + > + return request_threaded_irq(*irq, NULL, sdhci_acpi_qcom_handler, > + IRQF_ONESHOT | IRQF_TRIGGER_HIGH, > + "sdhci_qcom", host); > +} > + > +static int qcom_free_slot(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct sdhci_acpi_host *c = platform_get_drvdata(pdev); > + struct sdhci_host *host = c->host; > + struct acpi_device *adev; > + int *irq = sdhci_acpi_priv(c); > + const char *hid; > + > + adev = ACPI_COMPANION(dev); > + if (!adev) > + return -ENODEV; > + > + hid = acpi_device_hid(adev); > + if (strcmp(hid, "QCOM8051")) > + return 0; > + > + if (*irq < 0) > + return 0; > + > + free_irq(*irq, host); > + return 0; > +} > + > static const struct sdhci_acpi_slot sdhci_acpi_slot_qcom_sd_3v = { > .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION, > .quirks2 = SDHCI_QUIRK2_NO_1_8_V, > .caps = MMC_CAP_NONREMOVABLE, > + .priv_size = sizeof(int), > + .probe_slot = qcom_probe_slot, > + .free_slot = qcom_free_slot, > }; > > static const struct sdhci_acpi_slot sdhci_acpi_slot_qcom_sd = { >