Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0d58864b authored by Tony Lin's avatar Tony Lin Committed by Chris Ball
Browse files

mmc: esdhc-imx: fix card interrupt loss on freescale eSDHC



Apply a workaround for the imx eSDHC controller to avoid missing
card interrupts.  This makes SDIO work.

Signed-off-by: default avatarTony Lin <tony.lin@freescale.com>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent 55156d24
Loading
Loading
Loading
Loading
+31 −9
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include "sdhci-pltfm.h"
#include "sdhci-esdhc.h"

#define	SDHCI_CTRL_D3CD			0x08
/* VENDOR SPEC register */
#define SDHCI_VENDOR_SPEC		0xC0
#define  SDHCI_VENDOR_SPEC_SDIO_QUIRK	0x00000002
@@ -141,14 +142,33 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct pltfm_imx_data *imx_data = pltfm_host->priv;
	struct esdhc_platform_data *boarddata = &imx_data->boarddata;
	u32 data;

	if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)
			&& (boarddata->cd_type == ESDHC_CD_GPIO)))
	if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) {
		if (boarddata->cd_type == ESDHC_CD_GPIO)
			/*
		 * these interrupts won't work with a custom card_detect gpio
			 * These interrupts won't work with a custom
			 * card_detect gpio (only applied to mx25/35)
			 */
			val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);

		if (val & SDHCI_INT_CARD_INT) {
			/*
			 * Clear and then set D3CD bit to avoid missing the
			 * card interrupt.  This is a eSDHC controller problem
			 * so we need to apply the following workaround: clear
			 * and set D3CD bit will make eSDHC re-sample the card
			 * interrupt. In case a card interrupt was lost,
			 * re-sample it by the following steps.
			 */
			data = readl(host->ioaddr + SDHCI_HOST_CONTROL);
			data &= ~SDHCI_CTRL_D3CD;
			writel(data, host->ioaddr + SDHCI_HOST_CONTROL);
			data |= SDHCI_CTRL_D3CD;
			writel(data, host->ioaddr + SDHCI_HOST_CONTROL);
		}
	}

	if (unlikely((imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT)
				&& (reg == SDHCI_INT_STATUS)
				&& (val & SDHCI_INT_DATA_END))) {
@@ -217,8 +237,10 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
		 */
		return;
	case SDHCI_HOST_CONTROL:
		/* FSL messed up here, so we can just keep those two */
		new_val = val & (SDHCI_CTRL_LED | SDHCI_CTRL_4BITBUS);
		/* FSL messed up here, so we can just keep those three */
		new_val = val & (SDHCI_CTRL_LED | \
				SDHCI_CTRL_4BITBUS | \
				SDHCI_CTRL_D3CD);
		/* ensure the endianess */
		new_val |= ESDHC_HOST_CONTROL_LE;
		/* DMA mode bits are shifted */