[PATCH 2/6] SDHCI: AHB2MAG IRQ bypass hardware workaround

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Jerry Huang <Chang-Ming.Huang@xxxxxxxxxxxxx>

For Fsl eSDHC controller, the bit DCR[DMA__AHB2MAG_IRQ_BYPASS] cannot be
set automatically, when SoC reset, therefore, we need to set this bit manually.

Signed-off-by: Gao Guanhua <B22826@xxxxxxxxxxxxx>
Signed-off-by: Jerry Huang <Chang-Ming.Huang@xxxxxxxxxxxxx>
---
 drivers/mmc/host/sdhci-esdhc.h    |    1 +
 drivers/mmc/host/sdhci-of-esdhc.c |    7 +++++++
 drivers/mmc/host/sdhci-pltfm.c    |    3 +++
 drivers/mmc/host/sdhci.c          |    4 ++++
 drivers/mmc/host/sdhci.h          |    1 +
 include/linux/mmc/sdhci.h         |    2 ++
 6 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
index c3b08f1..7cbaffe 100644
--- a/drivers/mmc/host/sdhci-esdhc.h
+++ b/drivers/mmc/host/sdhci-esdhc.h
@@ -39,6 +39,7 @@
 /* OF-specific */
 #define ESDHC_DMA_SYSCTL	0x40c
 #define ESDHC_DMA_SNOOP		0x00000040
+#define ESDHC_AHB2MAG_IRQ_BYPASS	0x20
 
 #define ESDHC_HOST_CONTROL_RES	0x05
 
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 7d5ae82..413ded5 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -68,6 +68,12 @@ static int esdhc_of_enable_dma(struct sdhci_host *host)
 	return 0;
 }
 
+static int esdhc_of_enable_irq_bypass(struct sdhci_host *host)
+{
+	setbits32(host->ioaddr + ESDHC_DMA_SYSCTL, ESDHC_AHB2MAG_IRQ_BYPASS);
+	return 0;
+}
+
 static unsigned int esdhc_of_get_max_clock(struct sdhci_host *host)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -116,6 +122,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
 	.get_max_clock = esdhc_of_get_max_clock,
 	.get_min_clock = esdhc_of_get_min_clock,
 	.get_cd = esdhc_of_get_cd,
+	.enable_irq_bypass = esdhc_of_enable_irq_bypass,
 };
 
 static struct sdhci_pltfm_data sdhci_esdhc_pdata = {
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index 2a77435..de182c6 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -74,6 +74,9 @@ void sdhci_get_of_property(struct platform_device *pdev)
 		if (of_get_property(np, "sdhci,dma-broken", NULL))
 			host->quirks |= SDHCI_QUIRK_BROKEN_DMA;
 
+		if (of_get_property(np, "sdhci,ahb2mag-irq-bypass", NULL))
+			host->quirks2 |= SDHCI_QUIRK2_SET_AHB2MAG_IRQ_BYPASS;
+
 		clk = of_get_property(np, "clock-frequency", &size);
 		if (clk && size == sizeof(*clk) && *clk)
 			pltfm_host->clock = be32_to_cpup(clk);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index fbe2f46..ae52ab9 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -226,6 +226,10 @@ static void sdhci_init(struct sdhci_host *host, int soft)
 	else
 		sdhci_reset(host, SDHCI_RESET_ALL);
 
+	if (host->quirks2 & SDHCI_QUIRK2_SET_AHB2MAG_IRQ_BYPASS)
+		if (host->ops->enable_irq_bypass)
+			host->ops->enable_irq_bypass(host);
+
 	sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK,
 		SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
 		SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 82f4d27..1326557 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -263,6 +263,7 @@ struct sdhci_ops {
 	void	(*set_clock)(struct sdhci_host *host, unsigned int clock);
 
 	int		(*get_cd)(struct sdhci_host *host);
+	int		(*enable_irq_bypass)(struct sdhci_host *host);
 	int		(*enable_dma)(struct sdhci_host *host);
 	unsigned int	(*get_max_clock)(struct sdhci_host *host);
 	unsigned int	(*get_min_clock)(struct sdhci_host *host);
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index e4b6935..1dbe22b 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -91,6 +91,8 @@ struct sdhci_host {
 	unsigned int quirks2;	/* More deviations from spec. */
 
 #define SDHCI_QUIRK2_OWN_CARD_DETECTION			(1<<0)
+/* Controller cannot set DCR[DMA__AHB2MAG_IRQ_BYPASS] automatically */
+#define SDHCI_QUIRK2_SET_AHB2MAG_IRQ_BYPASS		(1<<1)
 
 	int irq;		/* Device IRQ */
 	void __iomem *ioaddr;	/* Mapped address */
-- 
1.7.5.4


--
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


[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux