Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mmc: esdhc: Fix bug when writing to SDHCI_HOST_CONTROL register

The P2020 has a non-standard implementation of the SDHCI_HOST_CONTROL
register. This patch adds a QUIRK in the SDHCI header to signal that
a host controller has a non-standard SDHCI_HOST_CONTROL register. The
patch adds a check to the function esdhc_writeb in file
sdhci-of-esdhc.c, where it checks if the write is done to the
SDHCI_HOST_CONTROL register and th host has the above mentioned QUIRK,
then the function simply returns instead of writing to the register.
The patch also detects if the processor is P2020 (by looking in dev
tree) and if so, adds the QUIRK to the host->quirk2

Signed-off-by: Oded Gabbay <ogabbay@advaoptical.com>
Reviewed-by: Anton Vorontsov <anton@enomsg.org>
Signed-off-by: Chris Ball <cjb@laptop.org>

authored by

Oded Gabbay and committed by
Chris Ball
dcaff04d 66b50a00

+19
+17
drivers/mmc/host/sdhci-of-esdhc.c
··· 121 121 if (reg == SDHCI_HOST_CONTROL) { 122 122 u32 dma_bits; 123 123 124 + /* 125 + * If host control register is not standard, exit 126 + * this function 127 + */ 128 + if (host->quirks2 & SDHCI_QUIRK2_BROKEN_HOST_CONTROL) 129 + return; 130 + 124 131 /* DMA select is 22,23 bits in Protocol Control Register */ 125 132 dma_bits = (val & SDHCI_CTRL_DMA_MASK) << 5; 126 133 clrsetbits_be32(host->ioaddr + reg , SDHCI_CTRL_DMA_MASK << 5, ··· 296 289 static int sdhci_esdhc_probe(struct platform_device *pdev) 297 290 { 298 291 struct sdhci_host *host; 292 + struct device_node *np; 299 293 int ret; 300 294 301 295 host = sdhci_pltfm_init(pdev, &sdhci_esdhc_pdata, 0); ··· 304 296 return PTR_ERR(host); 305 297 306 298 sdhci_get_of_property(pdev); 299 + 300 + np = pdev->dev.of_node; 301 + if (of_device_is_compatible(np, "fsl,p2020-esdhc")) { 302 + /* 303 + * Freescale messed up with P2020 as it has a non-standard 304 + * host control register 305 + */ 306 + host->quirks2 |= SDHCI_QUIRK2_BROKEN_HOST_CONTROL; 307 + } 307 308 308 309 /* call to generic mmc_of_parse to support additional capabilities */ 309 310 mmc_of_parse(host->mmc);
+2
include/linux/mmc/sdhci.h
··· 96 96 #define SDHCI_QUIRK2_NO_1_8_V (1<<2) 97 97 #define SDHCI_QUIRK2_PRESET_VALUE_BROKEN (1<<3) 98 98 #define SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON (1<<4) 99 + /* Controller has a non-standard host control register */ 100 + #define SDHCI_QUIRK2_BROKEN_HOST_CONTROL (1<<5) 99 101 100 102 int irq; /* Device IRQ */ 101 103 void __iomem *ioaddr; /* Mapped address */