#include <linux/mmc/mmc.h>
 #include <linux/scatterlist.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/gpio.h>
 #include <linux/pm_runtime.h>
 #include <linux/mmc/slot-gpio.h>
        return 0;
 }
 
+static u32 sdhci_read_present_state(struct sdhci_host *host)
+{
+       return sdhci_readl(host, SDHCI_PRESENT_STATE);
+}
+
+void amd_sdhci_reset(struct sdhci_host *host, u8 mask)
+{
+       struct sdhci_pci_slot *slot = sdhci_priv(host);
+       struct pci_dev *pdev = slot->chip->pdev;
+       u32 present_state;
+
+       /*
+        * SDHC 0x7906 requires a hard reset to clear all internal state.
+        * Otherwise it can get into a bad state where the DATA lines are always
+        * read as zeros.
+        */
+       if (pdev->device == 0x7906 && (mask & SDHCI_RESET_ALL)) {
+               pci_clear_master(pdev);
+
+               pci_save_state(pdev);
+
+               pci_set_power_state(pdev, PCI_D3cold);
+               pr_debug("%s: power_state=%u\n", mmc_hostname(host->mmc),
+                       pdev->current_state);
+               pci_set_power_state(pdev, PCI_D0);
+
+               pci_restore_state(pdev);
+
+               /*
+                * SDHCI_RESET_ALL says the card detect logic should not be
+                * reset, but since we need to reset the entire controller
+                * we should wait until the card detect logic has stabilized.
+                *
+                * This normally takes about 40ms.
+                */
+               readx_poll_timeout(
+                       sdhci_read_present_state,
+                       host,
+                       present_state,
+                       present_state & SDHCI_CD_STABLE,
+                       10000,
+                       100000
+               );
+       }
+
+       return sdhci_reset(host, mask);
+}
+
 static const struct sdhci_ops amd_sdhci_pci_ops = {
        .set_clock                      = sdhci_set_clock,
        .enable_dma                     = sdhci_pci_enable_dma,
        .set_bus_width                  = sdhci_set_bus_width,
-       .reset                          = sdhci_reset,
+       .reset                          = amd_sdhci_reset,
        .set_uhs_signaling              = sdhci_set_uhs_signaling,
 };