On HP laptops with JMicron 388 chip, the write-locked SD card isn't detected correctly as read-only in many cases. This is because the PRESENT_STATE register becomes unsable just after plugging, and it returns the WRITE_PROTECT bit wrongly at the first read. This patch fixes the read-only detection by adding the own get_ro op for checking the register more intensively with a relatively long delay. The patch is tested with 2.6.39-rc4 kernel. Cc: Aries Lee <arieslee@xxxxxxxxxxx> Signed-off-by: Takashi Iwai <tiwai@xxxxxxx> --- drivers/mmc/host/sdhci-pci.c | 34 ++++++++++++++++++++++++++++++++++ 1 files changed, 34 insertions(+), 0 deletions(-) diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index a136be7..9037b2a 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -346,6 +346,35 @@ static void jmicron_enable_mmc(struct sdhci_host *host, int on) writeb(scratch, host->ioaddr + 0xC0); } +/* As PRESENT_STATE register becomes unstable just after plugging, + * need to check the RO-cap multiple times with a relatively long delay. + */ + +#define SAMPLE_COUNT 5 + +static unsigned int jmicron_get_ro(struct sdhci_host *host) +{ + int i, ro_count; + + ro_count = 0; + for (i = 0; i < SAMPLE_COUNT; i++) { + int present = sdhci_readl(host, SDHCI_PRESENT_STATE); + if (!(present & SDHCI_WRITE_PROTECT)) { + if (++ro_count > SAMPLE_COUNT / 2) + return 1; + } + msleep(30); + } + return 0; +} + +static int sdhci_pci_enable_dma(struct sdhci_host *host); + +static struct sdhci_ops jmicron_pci_ops = { + .enable_dma = sdhci_pci_enable_dma, + .get_ro = jmicron_get_ro, +}; + static int jmicron_probe_slot(struct sdhci_pci_slot *slot) { if (slot->chip->pdev->revision == 0) { @@ -383,6 +412,11 @@ static int jmicron_probe_slot(struct sdhci_pci_slot *slot) slot->host->mmc->caps |= MMC_CAP_BUS_WIDTH_TEST; + /* Replace the ops for unstable get_ro detection */ + if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_SD || + slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_ESD) + slot->host->ops = &jmicron_pci_ops; + return 0; } -- 1.7.4.2 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html