olpc: sdhci: add quirk for the Marvell CaFe's interrupt timeout

The CaFe chip has a hardware bug that ends up with us getting a timeout
value that's too small, causing the following sorts of problems:

[ 60.525138] mmcblk0: error -110 transferring data
[ 60.531477] end_request: I/O error, dev mmcblk0, sector 1484353
[ 60.533371] Buffer I/O error on device mmcblk0p2, logical block 181632
[ 60.533371] lost page write due to I/O error on mmcblk0p2

Presumably this is an off-by-one error in the hardware. Incrementing
the timeout count value that we stuff into the TIMEOUT_CONTROL register
gets us a value that works. This bug was originally discovered by
Pierre Ossman, I believe.

[thanks to Robert Millan for proving that this was still a problem]

Signed-off-by: Andres Salomon <dilinger@debian.org>
Cc: Pierre Ossman <drzeus-list@drzeus.cx>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by Andres Salomon and committed by Linus Torvalds 603ded16 e08c1694

+11 -1
+11 -1
drivers/mmc/host/sdhci.c
··· 57 #define SDHCI_QUIRK_RESET_AFTER_REQUEST (1<<8) 58 /* Controller needs voltage and power writes to happen separately */ 59 #define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1<<9) 60 61 static const struct pci_device_id pci_ids[] __devinitdata = { 62 { ··· 136 .device = PCI_DEVICE_ID_MARVELL_CAFE_SD, 137 .subvendor = PCI_ANY_ID, 138 .subdevice = PCI_ANY_ID, 139 - .driver_data = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER, 140 }, 141 142 { ··· 481 if (count >= 0xF) 482 break; 483 } 484 485 if (count >= 0xF) { 486 printk(KERN_WARNING "%s: Too large timeout requested!\n",
··· 57 #define SDHCI_QUIRK_RESET_AFTER_REQUEST (1<<8) 58 /* Controller needs voltage and power writes to happen separately */ 59 #define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1<<9) 60 + /* Controller has an off-by-one issue with timeout value */ 61 + #define SDHCI_QUIRK_INCR_TIMEOUT_CONTROL (1<<10) 62 63 static const struct pci_device_id pci_ids[] __devinitdata = { 64 { ··· 134 .device = PCI_DEVICE_ID_MARVELL_CAFE_SD, 135 .subvendor = PCI_ANY_ID, 136 .subdevice = PCI_ANY_ID, 137 + .driver_data = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | 138 + SDHCI_QUIRK_INCR_TIMEOUT_CONTROL, 139 }, 140 141 { ··· 478 if (count >= 0xF) 479 break; 480 } 481 + 482 + /* 483 + * Compensate for an off-by-one error in the CaFe hardware; otherwise, 484 + * a too-small count gives us interrupt timeouts. 485 + */ 486 + if ((host->chip->quirks & SDHCI_QUIRK_INCR_TIMEOUT_CONTROL)) 487 + count++; 488 489 if (count >= 0xF) { 490 printk(KERN_WARNING "%s: Too large timeout requested!\n",