summary refs log tree commit diff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorPierre Ossman <drzeus@drzeus.cx>2007-12-02 19:58:16 +0100
committerPierre Ossman <drzeus@drzeus.cx>2007-12-12 20:01:00 +0100
commit84c46a53fc4ea4ff36df783a20187b2f65dd21cc (patch)
treecfd19b5b6afb71526512fe2241140d0057dd701e /drivers/mmc
parentc9fddbc4f844f5a16b5957c61fe2cfcb5c12f990 (diff)
downloadlinux-84c46a53fc4ea4ff36df783a20187b2f65dd21cc.tar.gz
sdhci: support JMicron JMB38x chips
The JMicron JMB38x chip doesn't support transfers that aren't 32-bit
aligned (both size and start address). It also doesn't like switching
between PIO and DMA mode, so it needs to be reset after each request.

Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/sdhci.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index a5300f238d98..785bbdcf4a58 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -7,6 +7,10 @@
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or (at
  * your option) any later version.
+ *
+ * Thanks to the following companies for their support:
+ *
+ *     - JMicron (hardware and technical support)
  */
 
 #include <linux/delay.h>
@@ -47,6 +51,8 @@ static unsigned int debug_quirks = 0;
 #define SDHCI_QUIRK_32BIT_DMA_ADDR			(1<<6)
 /* Controller can only DMA chunk sizes that are a multiple of 32 bits */
 #define SDHCI_QUIRK_32BIT_DMA_SIZE			(1<<7)
+/* Controller needs to be reset after each request to stay stable */
+#define SDHCI_QUIRK_RESET_AFTER_REQUEST			(1<<8)
 
 static const struct pci_device_id pci_ids[] __devinitdata = {
 	{
@@ -111,6 +117,16 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
 				  SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS,
 	},
 
+	{
+		.vendor         = PCI_VENDOR_ID_JMICRON,
+		.device         = PCI_DEVICE_ID_JMICRON_JMB38X_SD,
+		.subvendor      = PCI_ANY_ID,
+		.subdevice      = PCI_ANY_ID,
+		.driver_data    = SDHCI_QUIRK_32BIT_DMA_ADDR |
+				  SDHCI_QUIRK_32BIT_DMA_SIZE |
+				  SDHCI_QUIRK_RESET_AFTER_REQUEST,
+	},
+
 	{	/* Generic SD host controller */
 		PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
 	},
@@ -922,7 +938,8 @@ static void sdhci_tasklet_finish(unsigned long param)
 	 */
 	if (mrq->cmd->error ||
 		(mrq->data && (mrq->data->error ||
-		(mrq->data->stop && mrq->data->stop->error)))) {
+		(mrq->data->stop && mrq->data->stop->error))) ||
+		(host->chip->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)) {
 
 		/* Some controllers need this kick or reset won't work here */
 		if (host->chip->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) {