From 645289dca5021224279e67b4655796cafdfdad00 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 30 Jun 2006 02:22:33 -0700 Subject: [MMC] sdhci: quirk for broken reset Some controllers fail to complete a reset unless you touch the clock register first. Signed-off-by: Pierre Ossman Signed-off-by: Andrew Morton Signed-off-by: Russell King --- drivers/mmc/sdhci.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'drivers/mmc') diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index e192f3c9a437..7994c0b70f15 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -32,9 +32,21 @@ static unsigned int debug_nodma = 0; static unsigned int debug_forcedma = 0; static unsigned int debug_quirks = 0; +#define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1<<0) + static const struct pci_device_id pci_ids[] __devinitdata = { - /* handle any SD host controller */ - {PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)}, + { + .vendor = PCI_VENDOR_ID_RICOH, + .device = PCI_DEVICE_ID_RICOH_R5C822, + .subvendor = PCI_VENDOR_ID_IBM, + .subdevice = PCI_ANY_ID, + .driver_data = SDHCI_QUIRK_CLOCK_BEFORE_RESET, + }, + + { /* Generic SD host controller */ + PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) + }, + { /* end: all zeroes */ }, }; @@ -808,6 +820,19 @@ static void sdhci_tasklet_finish(unsigned long param) if ((mrq->cmd->error != MMC_ERR_NONE) || (mrq->data && ((mrq->data->error != MMC_ERR_NONE) || (mrq->data->stop && (mrq->data->stop->error != MMC_ERR_NONE))))) { + + /* Some controllers need this kick or reset won't work here */ + if (host->chip->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) { + unsigned int clock; + + /* This is to force an update */ + clock = host->clock; + host->clock = 0; + sdhci_set_clock(host, clock); + } + + /* Spec says we should do both at the same time, but Ricoh + controllers do not like that. */ sdhci_reset(host, SDHCI_RESET_CMD); sdhci_reset(host, SDHCI_RESET_DATA); } -- cgit v1.2.1 From 98608076a21914ab12f1c858a0cdf55366260f12 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 30 Jun 2006 02:22:34 -0700 Subject: [MMC] sdhci: force DMA on some controllers Some controllers incorrectly report that the cannot do DMA. Forcefully enable it for those that we know it works fine on. Signed-off-by: Pierre Ossman Signed-off-by: Andrew Morton Signed-off-by: Russell King --- drivers/mmc/sdhci.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'drivers/mmc') diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 7994c0b70f15..16ed2ae929d3 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -33,6 +33,7 @@ static unsigned int debug_forcedma = 0; static unsigned int debug_quirks = 0; #define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1<<0) +#define SDHCI_QUIRK_FORCE_DMA (1<<1) static const struct pci_device_id pci_ids[] __devinitdata = { { @@ -40,7 +41,24 @@ static const struct pci_device_id pci_ids[] __devinitdata = { .device = PCI_DEVICE_ID_RICOH_R5C822, .subvendor = PCI_VENDOR_ID_IBM, .subdevice = PCI_ANY_ID, - .driver_data = SDHCI_QUIRK_CLOCK_BEFORE_RESET, + .driver_data = SDHCI_QUIRK_CLOCK_BEFORE_RESET | + SDHCI_QUIRK_FORCE_DMA, + }, + + { + .vendor = PCI_VENDOR_ID_RICOH, + .device = PCI_DEVICE_ID_RICOH_R5C822, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = SDHCI_QUIRK_FORCE_DMA, + }, + + { + .vendor = PCI_VENDOR_ID_TI, + .device = PCI_DEVICE_ID_TI_XX21_XX11_SD, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = SDHCI_QUIRK_FORCE_DMA, }, { /* Generic SD host controller */ @@ -1190,7 +1208,9 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) else if (debug_forcedma) { DBG("DMA forced on\n"); host->flags |= SDHCI_USE_DMA; - } else if ((pdev->class & 0x0000FF) != PCI_SDHCI_IFDMA) + } else if (chip->quirks & SDHCI_QUIRK_FORCE_DMA) + host->flags |= SDHCI_USE_DMA; + else if ((pdev->class & 0x0000FF) != PCI_SDHCI_IFDMA) DBG("Controller doesn't have DMA interface\n"); else if (!(caps & SDHCI_CAN_DO_DMA)) DBG("Controller doesn't have DMA capability\n"); -- cgit v1.2.1 From 4cca56c50427eecfa2428cdee722848cd82f443c Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 30 Jun 2006 02:22:34 -0700 Subject: [MMC] sdhci: remove duplicate error message When there is remaining blocks untransferred, we get two error messages saying almost the same thing. Make sure at most one is shown. Signed-off-by: Pierre Ossman Signed-off-by: Andrew Morton Signed-off-by: Russell King --- drivers/mmc/sdhci.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/mmc') diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 16ed2ae929d3..60a40cb0a49a 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -470,9 +470,7 @@ static void sdhci_finish_data(struct sdhci_host *host) "though there were blocks left. Please report this " "to " BUGMAIL ".\n", mmc_hostname(host->mmc)); data->error = MMC_ERR_FAILED; - } - - if (host->size != 0) { + } else if (host->size != 0) { printk(KERN_ERR "%s: %d bytes were left untransferred. " "Please report this to " BUGMAIL ".\n", mmc_hostname(host->mmc), host->size); -- cgit v1.2.1