Fix problem with A-Data 2GB microSD card - Revisited

Sean McNeil sean at mcneil.com
Sun May 11 06:09:54 CEST 2008


Second try. It turns out I was just masking a problem and these 
particular cards can't run faster than /5 for f_max:


diff --git a/drivers/mfd/glamo/Kconfig b/drivers/mfd/glamo/Kconfig
index 86a7c40..7317807 100644
--- a/drivers/mfd/glamo/Kconfig
+++ b/drivers/mfd/glamo/Kconfig
@@ -36,6 +36,7 @@ config MFD_GLAMO_SPI_FB
 config MFD_GLAMO_MCI
 	tristate "Glamo S3C SD/MMC Card Interface support"
 	depends on MFD_GLAMO && MMC
+	select CRC7
 	help
 	  This selects a driver for the MCI interface found in
 	  the S-Media GLAMO chip, as used in Openmoko
diff --git a/drivers/mfd/glamo/glamo-mci.c b/drivers/mfd/glamo/glamo-mci.c
index 789352d..9eaba86 100644
--- a/drivers/mfd/glamo/glamo-mci.c
+++ b/drivers/mfd/glamo/glamo-mci.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/clk.h>
+#include <linux/crc7.h>
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/host.h>
 #include <linux/platform_device.h>
@@ -38,23 +39,6 @@ extern struct glamo_mci_pdata glamo_mci_def_pdata;
 
 static void glamo_mci_send_request(struct mmc_host *mmc);
 
-unsigned char CRC7(u8 * pu8, int cnt)
-{
-	u8 crc = 0;
-
-	while (cnt--) {
-		int n;
-		u8 d = *pu8++;
-		for (n = 0; n < 8; n++) {
-			crc <<= 1;
-			if ((d & 0x80) ^ (crc & 0x80))
-				crc ^= 0x09;
-			d <<= 1;
-		}
-	}
-	return (crc << 1) | 1;
-}
-
 /* these _dly versions account for the dead time rules for reg access */
 static u16 readw_dly(u16 __iomem * pu16)
 {
@@ -188,15 +172,15 @@ static void glamo_mci_irq(unsigned int irq, struct irq_desc *desc)
 	writew(GLAMO_IRQ_MMC,
 	       glamo_mci_def_pdata.pglamo->base + GLAMO_REG_IRQ_CLEAR);
 
-	if (status & (GLAMO_STAT1_MMC_RTOUT |
-		      GLAMO_STAT1_MMC_DTOUT))
+	if (status & GLAMO_STAT1_MMC_DTOUT)
 		cmd->error = -ETIMEDOUT;
 	if (status & (GLAMO_STAT1_MMC_BWERR |
 		      GLAMO_STAT1_MMC_BRERR))
 		cmd->error = -EILSEQ;
 	if (cmd->error) {
-		dev_info(&host->pdev->dev, "Error after cmd: 0x%x\n", status);
-		goto done;
+		dev_info(&host->pdev->dev, "Error in irq after cmd: 0x%x\n", status);
+		if (!(status & GLAMO_STAT1_MMC_RB_DRDY))
+			goto done;
 	}
 
 	if (host->pio_active == XFER_READ)
@@ -227,7 +211,7 @@ static int glamo_mci_send_command(struct glamo_mci_host *host,
 
 	/* if we can't do it, reject as busy */
 	if (!(readw_dly(host->base + GLAMO_REG_MMC_RB_STAT1) &
-	     GLAMO_STAT1_MMC_IDLE)) {
+		 GLAMO_STAT1_MMC_IDLE)) {
 		host->mrq = NULL;
 		cmd->error = -EBUSY;
 		mmc_request_done(host->mmc, cmd->mrq);
@@ -240,7 +224,7 @@ static int glamo_mci_send_command(struct glamo_mci_host *host,
 	u8a[2] = (u8)(cmd->arg >> 16);
 	u8a[3] = (u8)(cmd->arg >> 8);
 	u8a[4] = (u8)cmd->arg;
-	u8a[5] = CRC7(&u8a[0], 5); /* CRC7 on first 5 bytes of packet */
+	u8a[5] = crc7(0, &u8a[0], 5) | 0x01; /* CRC7 on first 5 bytes of packet */
 
 	/* issue the wire-order array including CRC in register order */
 	writew_dly((u8a[4] << 8) | u8a[5], host->base + GLAMO_REG_MMC_CMD_REG1);
@@ -336,7 +320,7 @@ static int glamo_mci_send_command(struct glamo_mci_host *host,
 	/* enforce timeout */
 	if (cmd->data) {
 		if (cmd->data->timeout_clks)
-			writew_dly(cmd->data->timeout_clks >> 4, /* / 16 clks */
+			writew_dly((cmd->data->timeout_clks >> 4) | 1, /* / 16 clks */
 					host->base + GLAMO_REG_MMC_TIMEOUT);
 		else
 			writew_dly(0xfff, host->base + GLAMO_REG_MMC_TIMEOUT);
@@ -468,20 +452,22 @@ static void glamo_mci_send_request(struct mmc_host *mmc)
 
 	if (cmd->error) {
 		dev_info(&host->pdev->dev, "Error after cmd: 0x%x\n", status);
-		goto done;
 	}
-	/*
-	 * mangle the response registers in two different exciting
-	 * undocumented ways discovered by trial and error
-	 */
-	if (mmc_resp_type(cmd) == MMC_RSP_R2)
-		/* grab the response */
-		for (n = 0; n < 8; n++) /* super mangle power 1 */
-			pu16[n ^ 6] = readw_dly(&reg_resp[n]);
-	else
-		for (n = 0; n < 3; n++) /* super mangle power 2 */
-			pu16[n] = (readw_dly(&reg_resp[n]) >> 8) |
-				  (readw_dly(&reg_resp[n + 1]) << 8);
+
+	if (status & GLAMO_STAT1_MMC_RB_RRDY) {
+		/*
+		 * mangle the response registers in two different exciting
+		 * undocumented ways discovered by trial and error
+		 */
+		if (mmc_resp_type(cmd) == MMC_RSP_R2)
+			/* grab the response */
+			for (n = 0; n < 8; n++) /* super mangle power 1 */
+				pu16[n ^ 6] = readw_dly(&reg_resp[n]);
+		else
+			for (n = 0; n < 3; n++) /* super mangle power 2 */
+				pu16[n] = (readw_dly(&reg_resp[n]) >> 8) |
+					  (readw_dly(&reg_resp[n + 1]) << 8);
+	}
 	/*
 	 * if we don't have bulk data to take care of, we're done
 	 */
@@ -753,7 +739,7 @@ static int glamo_mci_probe(struct platform_device *pdev)
 	 * held at /4 due to concerns of 100R recommended series resistor
 	 * allows 16MHz @ 4-bit --> 8MBytes/sec raw
 	 */
-	mmc->f_max 	= host->clk_rate / 3;
+	mmc->f_max 	= host->clk_rate / 5;
 
 	mmc->max_blk_count	= (1 << 16) - 1; /* GLAMO_REG_MMC_RB_BLKCNT */
 	mmc->max_blk_size	= (1 << 12) - 1; /* GLAMO_REG_MMC_RB_BLKLEN */





More information about the openmoko-kernel mailing list