[PATCH] omap-hsmmc: Implementation of i761 errata

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

 



Errata description:
Due to a bad behavior of an internal signal, the Card Error interrupt bit
MMCHS_STAT[28] CERR may not be set sometimes when an error occurred in the
card response.

Workaround:
After responses of type R1/R1b for all cards and responses of type R5/R5b/R6
for SD and SDIO cards, software must read two registers: MMCHS_RSP10 and
MMCHS_CSRE. When a MMCHS_CSRE[i] bit is set to 1, if the corresponding bit at
the same position in the response MMCHS_RSP10[i] is set to 1, the host
controller indicates a card error and software should proceed in the same way
as if a CERR interrupt would have been detected in the MMCHS_STAT register.

Note:
This errata is applicable for omap44xx.

Signed-off-by: Semen Protsenko <semen.protsenko@xxxxxx>
---
 drivers/mmc/host/omap_hsmmc.c |   38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 3a09f93..17803de 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -34,6 +34,7 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/core.h>
 #include <linux/mmc/mmc.h>
+#include <linux/mmc/card.h>
 #include <linux/io.h>
 #include <linux/semaphore.h>
 #include <linux/gpio.h>
@@ -47,6 +48,7 @@
 /* OMAP HSMMC Host Controller Registers */
 #define OMAP_HSMMC_SYSCONFIG	0x0010
 #define OMAP_HSMMC_SYSSTATUS	0x0014
+#define OMAP_HSMMC_CSRE		0x0024
 #define OMAP_HSMMC_CON		0x002C
 #define OMAP_HSMMC_BLK		0x0104
 #define OMAP_HSMMC_ARG		0x0108
@@ -117,6 +119,9 @@
 #define OMAP_MMC_MAX_CLOCK	52000000
 #define DRIVER_NAME		"omap_hsmmc"
 
+/* Errata definitions */
+#define OMAP_HSMMC_ERRATA_I761	BIT(0)
+
 /*
  * One controller can have multiple slots, like on some omap boards using
  * omap.c controller driver. Luckily this is not currently done on any known
@@ -177,6 +182,7 @@ struct omap_hsmmc_host {
 	int			reqs_blocked;
 	int			use_reg;
 	int			req_in_progress;
+	unsigned int		errata;
 	struct omap_hsmmc_next	next_data;
 
 	struct	omap_mmc_platform_data	*pdata;
@@ -857,6 +863,23 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data)
 	omap_hsmmc_start_command(host, data->stop, NULL);
 }
 
+static int
+omap_hsmmc_errata_i761(struct omap_hsmmc_host *host, struct mmc_command *cmd)
+{
+	u32 rsp10, csre;
+
+	if ((cmd->flags & MMC_RSP_R1) == MMC_RSP_R1
+			|| (host->mmc->card && (mmc_card_sd(host->mmc->card)
+			|| mmc_card_sdio(host->mmc->card))
+			&& (cmd->flags & MMC_RSP_R5))) {
+		rsp10 = OMAP_HSMMC_READ(host->base, RSP10);
+		csre = OMAP_HSMMC_READ(host->base, CSRE);
+		return rsp10 & csre;
+	}
+
+	return 0;
+}
+
 /*
  * Notify the core about command completion
  */
@@ -1046,6 +1069,17 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
 		}
 	}
 
+	/* Errata i761 */
+	if ((host->errata & OMAP_HSMMC_ERRATA_I761) && host->cmd
+			&& omap_hsmmc_errata_i761(host, host->cmd)) {
+		/* Do the same as for CARD_ERR case */
+		dev_dbg(mmc_dev(host->mmc), "Ignoring card err CMD%d\n",
+				host->cmd->opcode);
+		end_cmd = 1;
+		if (host->data)
+			end_trans = 1;
+	}
+
 	OMAP_HSMMC_WRITE(host->base, STAT, status);
 
 	if (end_cmd || ((status & CC) && host->cmd))
@@ -1829,6 +1863,10 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
 	host->power_mode = MMC_POWER_OFF;
 	host->next_data.cookie = 1;
 
+	host->errata = 0;
+	if (cpu_is_omap44xx())
+		host->errata |= OMAP_HSMMC_ERRATA_I761;
+
 	platform_set_drvdata(pdev, host);
 
 	mmc->ops	= &omap_hsmmc_ops;
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux