[RFC 4/4] sdhci: add quick for controllers with for CIRQ issues

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

 



This adds an SDHCI quick for controller which cannot
cannot detect CIRQ reliably when in 4-bit mode. What
we do is while bus is idle we leave it in 1-bit mode at
the controller level.

This allows the PCI SDCHI ENE 712 controller to work
correctly.

Cc: Chris Ball <cjb@xxxxxxxxxx>
Cc: Kalle Valo <kvalo@xxxxxxxxxx>
Cc: Naveen Singh <nsingh@xxxxxxxxxxx>
Cc: Vipin Mehta <Vipin.Mehta@xxxxxxxxxxx>
Signed-off-by: Luis R. Rodriguez <lrodriguez@xxxxxxxxxxx>
---
 drivers/mmc/host/sdhci-pci.c |    3 ++-
 drivers/mmc/host/sdhci.c     |   25 +++++++++++++++++++++++++
 include/linux/mmc/sdhci.h    |    2 ++
 3 files changed, 29 insertions(+), 1 deletions(-)

diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 2f8d468..8b13f61 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -130,7 +130,8 @@ static const struct sdhci_pci_fixes sdhci_ricoh_mmc = {
 
 static const struct sdhci_pci_fixes sdhci_ene_712 = {
 	.quirks		= SDHCI_QUIRK_SINGLE_POWER_WRITE |
-			  SDHCI_QUIRK_BROKEN_DMA,
+			  SDHCI_QUIRK_BROKEN_DMA |
+			  SDHCI_QUIRK_1BIT_INTERRUPT,
 };
 
 static const struct sdhci_pci_fixes sdhci_ene_714 = {
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index a4cf0c0..fac075e 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -245,6 +245,27 @@ static void sdhci_led_control(struct led_classdev *led,
 }
 #endif
 
+/* handle bus case where controller cannot detect CIRQ reliably when in 4-bit mode */
+static void sdhci_idle_bus_adjust(struct sdhci_host *host, u8 idle)
+{
+	u8 ctrl;
+
+	if (!(host->flags & SDHCI_IN_4BIT_MODE))
+		return;
+
+	if (!(host->quirks & SDHCI_QUIRK_1BIT_INTERRUPT))
+		return;
+
+	/* while bus is idle, leave it in 1-bit mode at the controller level */
+	ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
+	ctrl &= ~SDHCI_CTRL_4BITBUS;
+
+	if (!idle)
+		ctrl |= SDHCI_CTRL_4BITBUS;
+
+	writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
+}
+
 /*****************************************************************************\
  *                                                                           *
  * Core functions                                                            *
@@ -919,6 +940,8 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
 
 	mod_timer(&host->timer, jiffies + 10 * HZ);
 
+	sdhci_idle_bus_adjust(host, 0);
+
 	host->cmd = cmd;
 
 	sdhci_prepare_data(host, cmd->data);
@@ -1374,6 +1397,8 @@ static void sdhci_tasklet_finish(unsigned long param)
 	host->cmd = NULL;
 	host->data = NULL;
 
+	sdhci_idle_bus_adjust(host, 1);
+
 #ifndef SDHCI_USE_LEDS_CLASS
 	sdhci_deactivate_led(host);
 #endif
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index 266f796..4f1b26263 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -85,6 +85,8 @@ struct sdhci_host {
 #define SDHCI_QUIRK_NO_HISPD_BIT			(1<<29)
 /* Controller treats ADMA descriptors with length 0000h incorrectly */
 #define SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC		(1<<30)
+/* Controller cannot detect CIRQ reliably when in 4-bit mode */
+#define SDHCI_QUIRK_1BIT_INTERRUPT			(1<<31)
 
 	int irq;		/* Device IRQ */
 	void __iomem *ioaddr;	/* Mapped address */
-- 
1.7.4.15.g7811d

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