int (*probe)(struct sdhci_pci_chip*);
int (*probe_slot)(struct sdhci_pci_slot*);
- void (*remove_slot)(struct sdhci_pci_slot*);
+ void (*remove_slot)(struct sdhci_pci_slot*, int);
int (*suspend)(struct sdhci_pci_chip*,
pm_message_t);
static const struct sdhci_pci_fixes sdhci_ricoh = {
.probe = ricoh_probe,
+ .quirks = SDHCI_QUIRK_32BIT_DMA_ADDR,
};
static const struct sdhci_pci_fixes sdhci_ene_712 = {
{
int ret;
+ if (chip->pdev->revision == 0) {
+ chip->quirks |= SDHCI_QUIRK_32BIT_DMA_ADDR |
+ SDHCI_QUIRK_32BIT_DMA_SIZE |
+ SDHCI_QUIRK_32BIT_ADMA_SIZE |
+ SDHCI_QUIRK_RESET_AFTER_REQUEST;
+ }
+
/*
* JMicron chips can have two interfaces to the same hardware
* in order to work around limitations in Microsoft's driver.
static int jmicron_probe_slot(struct sdhci_pci_slot *slot)
{
+ if (slot->chip->pdev->revision == 0) {
+ u16 version;
+
+ version = readl(slot->host->ioaddr + SDHCI_HOST_VERSION);
+ version = (version & SDHCI_VENDOR_VER_MASK) >>
+ SDHCI_VENDOR_VER_SHIFT;
+
+ /*
+ * Older versions of the chip have lots of nasty glitches
+ * in the ADMA engine. It's best just to avoid it
+ * completely.
+ */
+ if (version < 0xAC)
+ slot->host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
+ }
+
/*
* The secondary interface requires a bit set to get the
* interrupts.
return 0;
}
-static void jmicron_remove_slot(struct sdhci_pci_slot *slot)
+static void jmicron_remove_slot(struct sdhci_pci_slot *slot, int dead)
{
+ if (dead)
+ return;
+
if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC)
jmicron_enable_mmc(slot->host, 0);
}
}
static const struct sdhci_pci_fixes sdhci_jmicron = {
- .quirks = SDHCI_QUIRK_32BIT_DMA_ADDR |
- SDHCI_QUIRK_32BIT_DMA_SIZE |
- SDHCI_QUIRK_RESET_AFTER_REQUEST,
-
.probe = jmicron_probe,
.probe_slot = jmicron_probe_slot,
remove:
if (chip->fixes && chip->fixes->remove_slot)
- chip->fixes->remove_slot(slot);
+ chip->fixes->remove_slot(slot, 0);
unmap:
iounmap(host->ioaddr);
static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot)
{
- sdhci_remove_host(slot->host);
+ int dead;
+ u32 scratch;
+
+ dead = 0;
+ scratch = readl(slot->host->ioaddr + SDHCI_INT_STATUS);
+ if (scratch == (u32)-1)
+ dead = 1;
+
+ sdhci_remove_host(slot->host, dead);
if (slot->chip->fixes && slot->chip->fixes->remove_slot)
- slot->chip->fixes->remove_slot(slot);
+ slot->chip->fixes->remove_slot(slot, dead);
pci_release_region(slot->chip->pdev, slot->pci_bar);