[PATCH 2/4 V2] mmc: esdhc: workaround for dma err in the last system transaction

Subsystems: multimedia card (mmc), secure digital (sd) and sdio subsystem, secure digital host controller interface (sdhci) driver, the rest

STALE4735d

18 messages, 5 authors, 2013-08-26 · open the first message on its own page

[PATCH 2/4 V2] mmc: esdhc: workaround for dma err in the last system transaction

From: Haijun Zhang <hidden>
Date: 2013-07-17 11:02:33

A-004388: eSDHC DMA might not stop if error occurs on system transaction

eSDHC DMA(SDMA/ADMA) might not stop if an error occurs in the last system
transaction. It may continue initiating additional transactions until
software reset for data/all is issued during error recovery. There is not
any data corruption to the SD data. The IRQSTAT[DMAE] is set when the
erratum occurs.
The only conditions under which issues occur are the following:
1. SDMA - For SD Write , the error occurs in the last system transaction.
No issue for SD read
2. ADMA
a. Block count is enabled: For SD write, the error occurs in the last system
transaction. There is no issue for SD read when block count is enabled.
b. Block count is disabled: Block count is designated by the ADMA descriptor
table, and the error occurs in the last system transaction when ADMA is
executing last descriptor line of table.

eSDHC may initiate additional system transactions. There is no data integrity
issue for case 1 and 2a described below. For case 2b, system data might be
corrupted.

Workaround: Set eSDHC_SYSCTL[RSTD] when IRQSTAT[DMAE] is set. For cases 2a and
2b above, add an extra descriptor line with zero data next to the last
descriptor line.

Signed-off-by: Haijun Zhang <redacted>
---
changes for V2:
	- Update the svr version list

 drivers/mmc/host/sdhci-of-esdhc.c | 112 ++++++++++++++++++++++++++++++++++----
 1 file changed, 102 insertions(+), 10 deletions(-)
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 15039e2..adfaadd 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -21,9 +21,13 @@
 #include <linux/mmc/host.h>
 #include "sdhci-pltfm.h"
 #include "sdhci-esdhc.h"
+#include <asm/mpc85xx.h>
 
 #define VENDOR_V_22	0x12
 #define VENDOR_V_23	0x13
+
+static u32 svr;
+
 static u32 esdhc_readl(struct sdhci_host *host, int reg)
 {
 	u32 ret;
@@ -142,6 +146,26 @@ static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg)
 	sdhci_be32bs_writeb(host, val, reg);
 }
 
+static void esdhc_reset(struct sdhci_host *host, u8 mask)
+{
+	u32 ier;
+	u32 uninitialized_var(isav);
+
+	if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
+		isav = esdhc_readl(host, SDHCI_INT_ENABLE);
+
+	esdhc_writeb(host, mask, SDHCI_SOFTWARE_RESET);
+	mdelay(100);
+
+	if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) {
+		ier = esdhc_readl(host, SDHCI_INT_ENABLE);
+		ier &= ~SDHCI_INT_ALL_MASK;
+		ier |= isav;
+		esdhc_writel(host, ier, SDHCI_INT_ENABLE);
+		esdhc_writel(host, ier, SDHCI_SIGNAL_ENABLE);
+	}
+}
+
 /*
  * For Abort or Suspend after Stop at Block Gap, ignore the ADMA
  * error(IRQSTAT[ADMAE]) if both Transfer Complete(IRQSTAT[TC])
@@ -156,25 +180,92 @@ static void esdhci_of_adma_workaround(struct sdhci_host *host, u32 intmask)
 	dma_addr_t dmastart;
 	dma_addr_t dmanow;
 
-	tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
+	tmp = esdhc_readl(host, SDHCI_SLOT_INT_STATUS);
 	tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
 
 	applicable = (intmask & SDHCI_INT_DATA_END) &&
 		(intmask & SDHCI_INT_BLK_GAP) &&
 		(tmp == VENDOR_V_23);
-	if (!applicable)
+	if (applicable) {
+
+		esdhc_reset(host, SDHCI_RESET_DATA);
+		host->data->error = 0;
+		dmastart = sg_dma_address(host->data->sg);
+		dmanow = dmastart + host->data->bytes_xfered;
+
+		/* Force update to the next DMA block boundary. */
+		dmanow = (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) +
+			SDHCI_DEFAULT_BOUNDARY_SIZE;
+		host->data->bytes_xfered = dmanow - dmastart;
+		esdhc_writel(host, dmanow, SDHCI_DMA_ADDRESS);
+
 		return;
+	}
 
-	host->data->error = 0;
-	dmastart = sg_dma_address(host->data->sg);
-	dmanow = dmastart + host->data->bytes_xfered;
 	/*
-	 * Force update to the next DMA block boundary.
+	 * Check for A-004388: eSDHC DMA might not stop if error
+	 * occurs on system transaction
+	 * Impact list:
+	 * T4240-R1.0 B4860-R1.0 P1010-R1.0
+	 * P3041-R1.0-R2.0-R1.1 P2041-R1.0-R1.1-R2.0
+	 * P5040-R2.0
 	 */
-	dmanow = (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) +
-		SDHCI_DEFAULT_BOUNDARY_SIZE;
-	host->data->bytes_xfered = dmanow - dmastart;
-	sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS);
+	if (!(((SVR_SOC_VER(svr) == SVR_T4240) && (SVR_REV(svr) == 0x10)) ||
+		((SVR_SOC_VER(svr) == SVR_B4860) && (SVR_REV(svr) == 0x10)) ||
+		((SVR_SOC_VER(svr) == SVR_P1010) && (SVR_REV(svr) == 0x10)) ||
+		((SVR_SOC_VER(svr) == SVR_P3041) && (SVR_REV(svr) <= 0x20)) ||
+		((SVR_SOC_VER(svr) == SVR_P2041) && (SVR_REV(svr) <= 0x20)) ||
+		((SVR_SOC_VER(svr) == SVR_P5040) && SVR_REV(svr) == 0x20)))
+		return;
+
+	esdhc_reset(host, SDHCI_RESET_DATA);
+
+	if (host->flags & SDHCI_USE_ADMA) {
+		u32 mod, i, offset;
+		u8 *desc;
+		dma_addr_t addr;
+		struct scatterlist *sg;
+		__le32 *dataddr;
+		__le32 *cmdlen;
+
+		/*
+		 * If block count was enabled, in case read transfer there
+		 * is no data was corrupted
+		 */
+		mod = esdhc_readl(host, SDHCI_TRANSFER_MODE);
+		if ((mod & SDHCI_TRNS_BLK_CNT_EN) &&
+			(host->data->flags & MMC_DATA_READ))
+			host->data->error = 0;
+
+		BUG_ON(!host->data);
+		desc = host->adma_desc;
+		for_each_sg(host->data->sg, sg, host->sg_count, i) {
+			addr = sg_dma_address(sg);
+			offset = (4 - (addr & 0x3)) & 0x3;
+			if (offset)
+				desc += 8;
+			desc += 8;
+		}
+
+		/*
+		 * Add an extra zero descriptor next to the
+		 * terminating descriptor.
+		 */
+		desc += 8;
+		WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4);
+
+		dataddr = (__le32 __force *)(desc + 4);
+		cmdlen = (__le32 __force *)desc;
+
+		cmdlen[0] = cpu_to_le32(0);
+		dataddr[0] = cpu_to_le32(0);
+	}
+
+	if ((host->flags & SDHCI_USE_SDMA) &&
+		(host->data->flags & MMC_DATA_READ))
+		host->data->error = 0;
+
+	return;
 }
 
 static int esdhc_of_enable_dma(struct sdhci_host *host)
@@ -299,6 +390,7 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
 	struct device_node *np;
 	int ret;
 
+	svr = mfspr(SPRN_SVR);
 	host = sdhci_pltfm_init(pdev, &sdhci_esdhc_pdata, 0);
 	if (IS_ERR(host))
 		return PTR_ERR(host);
-- 
1.8.0

[PATCH 3/4 V2] mmc: esdhc: Correct host version of T4240-R1.0

From: Haijun Zhang <hidden>
Date: 2013-07-17 11:02:41

Vender version and sdhc spec version of T4240-R1.0 is incorrect.
The right value should be VVN=0x13, SVN = 0x1. The wrong version
number will break down the ADMA data transfer.
This defect only exist in T4240-R1.0. Will be fixed in T4240-R2.0.
Also share vvn and svr for public use.

Signed-off-by: Haijun Zhang <redacted>
---
changes for V2:
	- Remove broken ADMA quirk.
	- Rebuild patch of  Add quirks to support T4240 board

 drivers/mmc/host/sdhci-of-esdhc.c | 29 +++++++++++++----------------
 1 file changed, 13 insertions(+), 16 deletions(-)
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index adfaadd..570bca8 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -26,7 +26,7 @@
 #define VENDOR_V_22	0x12
 #define VENDOR_V_23	0x13
 
-static u32 svr;
+static u32 svr, vvn;
 
 static u32 esdhc_readl(struct sdhci_host *host, int reg)
 {
@@ -43,11 +43,9 @@ static u32 esdhc_readl(struct sdhci_host *host, int reg)
 	 * For FSL eSDHC, must aligned 4-byte, so use 0xFC to read the
 	 * the verdor version number, oxFE is SDHCI_HOST_VERSION.
 	 */
-	if ((reg == SDHCI_CAPABILITIES) && (ret & SDHCI_CAN_DO_ADMA1)) {
-		u32 tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
-		tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
-		if (tmp > VENDOR_V_22)
-			ret |= SDHCI_CAN_DO_ADMA2;
+	if ((reg == SDHCI_CAPABILITIES) && (ret & SDHCI_CAN_DO_ADMA1) &&
+		(vvn > VENDOR_V_22)) {
+		ret |= SDHCI_CAN_DO_ADMA2;
 	}
 
 	return ret;
@@ -63,6 +61,12 @@ static u16 esdhc_readw(struct sdhci_host *host, int reg)
 		ret = in_be32(host->ioaddr + base) & 0xffff;
 	else
 		ret = (in_be32(host->ioaddr + base) >> shift) & 0xffff;
+
+	/* T4240-R1.0 had a incorrect vendor version and spec version */
+	if ((reg == SDHCI_HOST_VERSION) &&
+		((SVR_SOC_VER(svr) == SVR_T4240) && (SVR_REV(svr) == 0x10)))
+		ret = (VENDOR_V_23 << SDHCI_VENDOR_VER_SHIFT) | SDHCI_SPEC_200;
+
 	return ret;
 }
 
@@ -175,17 +179,12 @@ static void esdhc_reset(struct sdhci_host *host, u8 mask)
  */
 static void esdhci_of_adma_workaround(struct sdhci_host *host, u32 intmask)
 {
-	u32 tmp;
 	bool applicable;
 	dma_addr_t dmastart;
 	dma_addr_t dmanow;
 
-	tmp = esdhc_readl(host, SDHCI_SLOT_INT_STATUS);
-	tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
-
 	applicable = (intmask & SDHCI_INT_DATA_END) &&
-		(intmask & SDHCI_INT_BLK_GAP) &&
-		(tmp == VENDOR_V_23);
+		(intmask & SDHCI_INT_BLK_GAP) && (vvn == VENDOR_V_23);
 	if (applicable) {
 
 		esdhc_reset(host, SDHCI_RESET_DATA);
@@ -318,10 +317,9 @@ static void esdhc_of_resume(struct sdhci_host *host)
 
 static void esdhc_of_platform_init(struct sdhci_host *host)
 {
-	u32 vvn;
+	svr = mfspr(SPRN_SVR);
+	vvn = esdhc_readw(host, SDHCI_HOST_VERSION);
 
-	vvn = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
-	vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
 	if (vvn == VENDOR_V_22)
 		host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
 
@@ -390,7 +388,6 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
 	struct device_node *np;
 	int ret;
 
-	svr = mfspr(SPRN_SVR);
 	host = sdhci_pltfm_init(pdev, &sdhci_esdhc_pdata, 0);
 	if (IS_ERR(host))
 		return PTR_ERR(host);
-- 
1.8.0

[PATCH 4/4 V2] mmc: esdhc: Add broken timeout quirk for p4/p5 board

From: Haijun Zhang <hidden>
Date: 2013-07-17 11:02:53

Sometimes command can't be completed within the time give
in eSDHC_SYSCTL[DTOCV]. So just give the max value 0x14 to
avoid this issue.

Signed-off-by: Haijun Zhang <redacted>
---
changes for v2:
	- Rebuild patch of eSDHC host need long time to generate
	 command interrupt

 drivers/mmc/host/sdhci-of-esdhc.c | 6 ++++++
 1 file changed, 6 insertions(+)
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 570bca8..30bfb5c 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -325,6 +325,12 @@ static void esdhc_of_platform_init(struct sdhci_host *host)
 
 	if (vvn > VENDOR_V_22)
 		host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
+
+	if ((SVR_SOC_VER(svr) == SVR_B4860) ||
+		(SVR_SOC_VER(svr) == SVR_P5020) ||
+		(SVR_SOC_VER(svr) == SVR_P5040) ||
+		(SVR_SOC_VER(svr) == SVR_P4080))
+		host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 }
 
 static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)
-- 
1.8.0

Re: [PATCH 3/4 V2] mmc: esdhc: Correct host version of T4240-R1.0

From: Scott Wood <hidden>
Date: 2013-07-17 17:11:25

On 07/17/2013 05:11:30 AM, Haijun Zhang wrote:
Vender version and sdhc spec version of T4240-R1.0 is incorrect.
The right value should be VVN=3D0x13, SVN =3D 0x1. The wrong version
number will break down the ADMA data transfer.
This defect only exist in T4240-R1.0. Will be fixed in T4240-R2.0.
Also share vvn and svr for public use.
=20
Signed-off-by: Haijun Zhang <redacted>
We're not supporting T4240 rev 1.0 in upstream Linux, as it's not =20
production silicon.

-Scott=

Re: [PATCH 4/4 V2] mmc: esdhc: Add broken timeout quirk for p4/p5 board

From: Scott Wood <hidden>
Date: 2013-07-17 17:14:09

On 07/17/2013 05:11:31 AM, Haijun Zhang wrote:
quoted hunk
Sometimes command can't be completed within the time give
in eSDHC_SYSCTL[DTOCV]. So just give the max value 0x14 to
avoid this issue.
=20
Signed-off-by: Haijun Zhang <redacted>
---
changes for v2:
	- Rebuild patch of eSDHC host need long time to generate
	 command interrupt
=20
 drivers/mmc/host/sdhci-of-esdhc.c | 6 ++++++
 1 file changed, 6 insertions(+)
=20
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c =20
b/drivers/mmc/host/sdhci-of-esdhc.c
index 570bca8..30bfb5c 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -325,6 +325,12 @@ static void esdhc_of_platform_init(struct =20
sdhci_host *host)
=20
 	if (vvn > VENDOR_V_22)
 		host->quirks &=3D ~SDHCI_QUIRK_NO_BUSY_IRQ;
+
+	if ((SVR_SOC_VER(svr) =3D=3D SVR_B4860) ||
+		(SVR_SOC_VER(svr) =3D=3D SVR_P5020) ||
+		(SVR_SOC_VER(svr) =3D=3D SVR_P5040) ||
+		(SVR_SOC_VER(svr) =3D=3D SVR_P4080))
+		host->quirks |=3D SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 }
Please don't line up the continuation lines of the if-condition with =20
the if-body.

Please check variant SoCs as well.  If the bug exists on p4080, then it =20
exists on p4040.  Likewise with p5040/p5021, and p5020/p5010.

Is it present on all revisions of these SoCs?  How about p3041, which =20
is usually pretty similar to p5020?  p2040/p2041?  Is there an erratum =20
number for this problem?

-Scott=

RE: [PATCH 3/4 V2] mmc: esdhc: Correct host version of T4240-R1.0

From: Zang Roy-R61911 <hidden>
Date: 2013-07-18 02:31:13

-----Original Message-----
From: linux-mmc-owner@vger.kernel.org [mailto:linux-mmc-
owner@vger.kernel.org] On Behalf Of Scott Wood
=20
On 07/17/2013 05:11:30 AM, Haijun Zhang wrote:
quoted
Vender version and sdhc spec version of T4240-R1.0 is incorrect.
The right value should be VVN=3D0x13, SVN =3D 0x1. The wrong version
number will break down the ADMA data transfer.
This defect only exist in T4240-R1.0. Will be fixed in T4240-R2.0.
Also share vvn and svr for public use.

Signed-off-by: Haijun Zhang <redacted>
=20
We're not supporting T4240 rev 1.0 in upstream Linux, as it's not
production silicon.
As discussed, production silicon Rev 2.0 will also suffer this issue. So ne=
ed to address it beyond T4240-R2.0.
thanks.
Roy

Re: [PATCH 3/4 V2] mmc: esdhc: Correct host version of T4240-R1.0

From: Scott Wood <hidden>
Date: 2013-07-18 15:24:24

On 07/17/2013 09:30:45 PM, Zang Roy-R61911 wrote:
=20
=20
quoted
-----Original Message-----
From: linux-mmc-owner@vger.kernel.org [mailto:linux-mmc-
owner@vger.kernel.org] On Behalf Of Scott Wood

On 07/17/2013 05:11:30 AM, Haijun Zhang wrote:
quoted
Vender version and sdhc spec version of T4240-R1.0 is incorrect.
The right value should be VVN=3D0x13, SVN =3D 0x1. The wrong version
number will break down the ADMA data transfer.
This defect only exist in T4240-R1.0. Will be fixed in T4240-R2.0.
Also share vvn and svr for public use.

Signed-off-by: Haijun Zhang <redacted>
We're not supporting T4240 rev 1.0 in upstream Linux, as it's not
production silicon.
As discussed, production silicon Rev 2.0 will also suffer this issue. =20
So need to address it beyond T4240-R2.0.
OK -- please update the commit message.

-Scott=

RE: [PATCH 4/4 V2] mmc: esdhc: Add broken timeout quirk for p4/p5 board

From: Zhang Haijun-B42677 <hidden>
Date: 2013-07-19 02:20:39


Thanks.

Regards
Haijun.

-----Original Message-----
From: Wood Scott-B07421
Sent: Thursday, July 18, 2013 1:14 AM
To: Zhang Haijun-B42677
Cc: linux-mmc@vger.kernel.org; linuxppc-dev@lists.ozlabs.org;
cbouatmailru@gmail.com; cjb@laptop.org; Fleming Andy-AFLEMING; Zhang
Haijun-B42677; Zhang Haijun-B42677
Subject: Re: [PATCH 4/4 V2] mmc: esdhc: Add broken timeout quirk for
p4/p5 board
=20
On 07/17/2013 05:11:31 AM, Haijun Zhang wrote:
quoted
Sometimes command can't be completed within the time give in
eSDHC_SYSCTL[DTOCV]. So just give the max value 0x14 to avoid this
issue.

Signed-off-by: Haijun Zhang <redacted>
---
changes for v2:
	- Rebuild patch of eSDHC host need long time to generate
	 command interrupt

 drivers/mmc/host/sdhci-of-esdhc.c | 6 ++++++
 1 file changed, 6 insertions(+)
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c
b/drivers/mmc/host/sdhci-of-esdhc.c
index 570bca8..30bfb5c 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -325,6 +325,12 @@ static void esdhc_of_platform_init(struct
sdhci_host *host)

 	if (vvn > VENDOR_V_22)
 		host->quirks &=3D ~SDHCI_QUIRK_NO_BUSY_IRQ;
+
+	if ((SVR_SOC_VER(svr) =3D=3D SVR_B4860) ||
+		(SVR_SOC_VER(svr) =3D=3D SVR_P5020) ||
+		(SVR_SOC_VER(svr) =3D=3D SVR_P5040) ||
+		(SVR_SOC_VER(svr) =3D=3D SVR_P4080))
+		host->quirks |=3D SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 }
=20
Please don't line up the continuation lines of the if-condition with the
if-body.
[Haijun Wrote:] I'll correct it.
=20
Please check variant SoCs as well.  If the bug exists on p4080, then it
exists on p4040.  Likewise with p5040/p5021, and p5020/p5010.
=20
Is it present on all revisions of these SoCs?  How about p3041, which is
usually pretty similar to p5020?  p2040/p2041?  Is there an erratum
number for this problem?
=20
[Haijun Wrote:] I only checked this on these boards. No errata number yet, =
This
quirk only give the host max detecting time value to check card's response.=
 No
impact on performance or other functions.=20
-Scott

RE: [PATCH 2/4 V2] mmc: esdhc: workaround for dma err in the last system transaction

From: Zhang Haijun-B42677 <hidden>
Date: 2013-07-19 02:22:07

Hi, all

Expect your advice and any comments.


Thanks.

Regards
Haijun.

quoted hunk
-----Original Message-----
From: Zhang Haijun-B42677
Sent: Wednesday, July 17, 2013 6:11 PM
To: linux-mmc@vger.kernel.org; linuxppc-dev@lists.ozlabs.org
Cc: cbouatmailru@gmail.com; cjb@laptop.org; Wood Scott-B07421; Fleming
Andy-AFLEMING; Zhang Haijun-B42677; Zhang Haijun-B42677
Subject: [PATCH 2/4 V2] mmc: esdhc: workaround for dma err in the last
system transaction
=20
A-004388: eSDHC DMA might not stop if error occurs on system transaction
=20
eSDHC DMA(SDMA/ADMA) might not stop if an error occurs in the last system
transaction. It may continue initiating additional transactions until
software reset for data/all is issued during error recovery. There is not
any data corruption to the SD data. The IRQSTAT[DMAE] is set when the
erratum occurs.
The only conditions under which issues occur are the following:
1. SDMA - For SD Write , the error occurs in the last system transaction.
No issue for SD read
2. ADMA
a. Block count is enabled: For SD write, the error occurs in the last
system transaction. There is no issue for SD read when block count is
enabled.
b. Block count is disabled: Block count is designated by the ADMA
descriptor table, and the error occurs in the last system transaction
when ADMA is executing last descriptor line of table.
=20
eSDHC may initiate additional system transactions. There is no data
integrity issue for case 1 and 2a described below. For case 2b, system
data might be corrupted.
=20
Workaround: Set eSDHC_SYSCTL[RSTD] when IRQSTAT[DMAE] is set. For cases
2a and 2b above, add an extra descriptor line with zero data next to the
last descriptor line.
=20
Signed-off-by: Haijun Zhang <redacted>
---
changes for V2:
	- Update the svr version list
=20
 drivers/mmc/host/sdhci-of-esdhc.c | 112
++++++++++++++++++++++++++++++++++----
 1 file changed, 102 insertions(+), 10 deletions(-)
=20
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-
of-esdhc.c
index 15039e2..adfaadd 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -21,9 +21,13 @@
 #include <linux/mmc/host.h>
 #include "sdhci-pltfm.h"
 #include "sdhci-esdhc.h"
+#include <asm/mpc85xx.h>
=20
 #define VENDOR_V_22	0x12
 #define VENDOR_V_23	0x13
+
+static u32 svr;
+
 static u32 esdhc_readl(struct sdhci_host *host, int reg)  {
 	u32 ret;
@@ -142,6 +146,26 @@ static void esdhc_writeb(struct sdhci_host *host, u8
val, int reg)
 	sdhci_be32bs_writeb(host, val, reg);
 }
=20
+static void esdhc_reset(struct sdhci_host *host, u8 mask) {
+	u32 ier;
+	u32 uninitialized_var(isav);
+
+	if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
+		isav =3D esdhc_readl(host, SDHCI_INT_ENABLE);
+
+	esdhc_writeb(host, mask, SDHCI_SOFTWARE_RESET);
+	mdelay(100);
+
+	if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) {
+		ier =3D esdhc_readl(host, SDHCI_INT_ENABLE);
+		ier &=3D ~SDHCI_INT_ALL_MASK;
+		ier |=3D isav;
+		esdhc_writel(host, ier, SDHCI_INT_ENABLE);
+		esdhc_writel(host, ier, SDHCI_SIGNAL_ENABLE);
+	}
+}
+
 /*
  * For Abort or Suspend after Stop at Block Gap, ignore the ADMA
  * error(IRQSTAT[ADMAE]) if both Transfer Complete(IRQSTAT[TC]) @@ -
156,25 +180,92 @@ static void esdhci_of_adma_workaround(struct sdhci_host
*host, u32 intmask)
 	dma_addr_t dmastart;
 	dma_addr_t dmanow;
=20
-	tmp =3D in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
+	tmp =3D esdhc_readl(host, SDHCI_SLOT_INT_STATUS);
 	tmp =3D (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
=20
 	applicable =3D (intmask & SDHCI_INT_DATA_END) &&
 		(intmask & SDHCI_INT_BLK_GAP) &&
 		(tmp =3D=3D VENDOR_V_23);
-	if (!applicable)
+	if (applicable) {
+
+		esdhc_reset(host, SDHCI_RESET_DATA);
+		host->data->error =3D 0;
+		dmastart =3D sg_dma_address(host->data->sg);
+		dmanow =3D dmastart + host->data->bytes_xfered;
+
+		/* Force update to the next DMA block boundary. */
+		dmanow =3D (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) +
+			SDHCI_DEFAULT_BOUNDARY_SIZE;
+		host->data->bytes_xfered =3D dmanow - dmastart;
+		esdhc_writel(host, dmanow, SDHCI_DMA_ADDRESS);
+
 		return;
+	}
=20
-	host->data->error =3D 0;
-	dmastart =3D sg_dma_address(host->data->sg);
-	dmanow =3D dmastart + host->data->bytes_xfered;
 	/*
-	 * Force update to the next DMA block boundary.
+	 * Check for A-004388: eSDHC DMA might not stop if error
+	 * occurs on system transaction
+	 * Impact list:
+	 * T4240-R1.0 B4860-R1.0 P1010-R1.0
+	 * P3041-R1.0-R2.0-R1.1 P2041-R1.0-R1.1-R2.0
+	 * P5040-R2.0
 	 */
-	dmanow =3D (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) +
-		SDHCI_DEFAULT_BOUNDARY_SIZE;
-	host->data->bytes_xfered =3D dmanow - dmastart;
-	sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS);
+	if (!(((SVR_SOC_VER(svr) =3D=3D SVR_T4240) && (SVR_REV(svr) =3D=3D 0x10=
))
quoted hunk
||
+		((SVR_SOC_VER(svr) =3D=3D SVR_B4860) && (SVR_REV(svr) =3D=3D 0x10))
||
+		((SVR_SOC_VER(svr) =3D=3D SVR_P1010) && (SVR_REV(svr) =3D=3D 0x10))
||
+		((SVR_SOC_VER(svr) =3D=3D SVR_P3041) && (SVR_REV(svr) <=3D 0x20))
||
+		((SVR_SOC_VER(svr) =3D=3D SVR_P2041) && (SVR_REV(svr) <=3D 0x20))
||
+		((SVR_SOC_VER(svr) =3D=3D SVR_P5040) && SVR_REV(svr) =3D=3D 0x20)))
+		return;
+
+	esdhc_reset(host, SDHCI_RESET_DATA);
+
+	if (host->flags & SDHCI_USE_ADMA) {
+		u32 mod, i, offset;
+		u8 *desc;
+		dma_addr_t addr;
+		struct scatterlist *sg;
+		__le32 *dataddr;
+		__le32 *cmdlen;
+
+		/*
+		 * If block count was enabled, in case read transfer there
+		 * is no data was corrupted
+		 */
+		mod =3D esdhc_readl(host, SDHCI_TRANSFER_MODE);
+		if ((mod & SDHCI_TRNS_BLK_CNT_EN) &&
+			(host->data->flags & MMC_DATA_READ))
+			host->data->error =3D 0;
+
+		BUG_ON(!host->data);
+		desc =3D host->adma_desc;
+		for_each_sg(host->data->sg, sg, host->sg_count, i) {
+			addr =3D sg_dma_address(sg);
+			offset =3D (4 - (addr & 0x3)) & 0x3;
+			if (offset)
+				desc +=3D 8;
+			desc +=3D 8;
+		}
+
+		/*
+		 * Add an extra zero descriptor next to the
+		 * terminating descriptor.
+		 */
+		desc +=3D 8;
+		WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4);
+
+		dataddr =3D (__le32 __force *)(desc + 4);
+		cmdlen =3D (__le32 __force *)desc;
+
+		cmdlen[0] =3D cpu_to_le32(0);
+		dataddr[0] =3D cpu_to_le32(0);
+	}
+
+	if ((host->flags & SDHCI_USE_SDMA) &&
+		(host->data->flags & MMC_DATA_READ))
+		host->data->error =3D 0;
+
+	return;
 }
=20
 static int esdhc_of_enable_dma(struct sdhci_host *host) @@ -299,6 +390,7
@@ static int sdhci_esdhc_probe(struct platform_device *pdev)
 	struct device_node *np;
 	int ret;
=20
+	svr =3D mfspr(SPRN_SVR);
 	host =3D sdhci_pltfm_init(pdev, &sdhci_esdhc_pdata, 0);
 	if (IS_ERR(host))
 		return PTR_ERR(host);
--
1.8.0

Re: [PATCH 4/4 V2] mmc: esdhc: Add broken timeout quirk for p4/p5 board

From: Scott Wood <hidden>
Date: 2013-07-19 17:24:31

On 07/18/2013 09:19:59 PM, Zhang Haijun-B42677 wrote:
=20
=20
Thanks.
=20
Regards
Haijun.
=20
=20
quoted
-----Original Message-----
From: Wood Scott-B07421
Sent: Thursday, July 18, 2013 1:14 AM
To: Zhang Haijun-B42677
Cc: linux-mmc@vger.kernel.org; linuxppc-dev@lists.ozlabs.org;
cbouatmailru@gmail.com; cjb@laptop.org; Fleming Andy-AFLEMING; Zhang
Haijun-B42677; Zhang Haijun-B42677
Subject: Re: [PATCH 4/4 V2] mmc: esdhc: Add broken timeout quirk for
p4/p5 board

On 07/17/2013 05:11:31 AM, Haijun Zhang wrote:
quoted
Sometimes command can't be completed within the time give in
eSDHC_SYSCTL[DTOCV]. So just give the max value 0x14 to avoid this
issue.

Signed-off-by: Haijun Zhang <redacted>
---
changes for v2:
	- Rebuild patch of eSDHC host need long time to generate
	 command interrupt

 drivers/mmc/host/sdhci-of-esdhc.c | 6 ++++++
 1 file changed, 6 insertions(+)
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c
b/drivers/mmc/host/sdhci-of-esdhc.c
index 570bca8..30bfb5c 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -325,6 +325,12 @@ static void esdhc_of_platform_init(struct
sdhci_host *host)

 	if (vvn > VENDOR_V_22)
 		host->quirks &=3D ~SDHCI_QUIRK_NO_BUSY_IRQ;
+
+	if ((SVR_SOC_VER(svr) =3D=3D SVR_B4860) ||
+		(SVR_SOC_VER(svr) =3D=3D SVR_P5020) ||
+		(SVR_SOC_VER(svr) =3D=3D SVR_P5040) ||
+		(SVR_SOC_VER(svr) =3D=3D SVR_P4080))
+		host->quirks |=3D SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 }
Please don't line up the continuation lines of the if-condition =20
with the
quoted
if-body.
[Haijun Wrote:] I'll correct it.
quoted
Please check variant SoCs as well.  If the bug exists on p4080, =20
then it
quoted
exists on p4040.  Likewise with p5040/p5021, and p5020/p5010.

Is it present on all revisions of these SoCs?  How about p3041, =20
which is
quoted
usually pretty similar to p5020?  p2040/p2041?  Is there an erratum
number for this problem?
[Haijun Wrote:] I only checked this on these boards.
These aren't boards; they're chips.

Please find out for sure which chips are affected, or else we'll have =20
support issues later when someone is using a chip you didn't test =20
with.  And always include the fewer-core variants -- if p4080 is =20
affected, then p4040 is affected, and so on as described above.
No errata number yet,
Will one be coming?
This quirk only give the host max detecting time value to check =20
card's response. No
impact on performance or other functions.
Does this affect boot time if a card is not present?

-Scott=

RE: [PATCH 4/4 V2] mmc: esdhc: Add broken timeout quirk for p4/p5 board

From: Zhang Haijun-B42677 <hidden>
Date: 2013-07-22 01:58:01


Thanks.

Regards
Haijun.
-----Original Message-----
From: Wood Scott-B07421
Sent: Saturday, July 20, 2013 1:24 AM
To: Zhang Haijun-B42677
Cc: Wood Scott-B07421; linux-mmc@vger.kernel.org; linuxppc-
dev@lists.ozlabs.org; cbouatmailru@gmail.com; cjb@laptop.org; Fleming
Andy-AFLEMING
Subject: Re: [PATCH 4/4 V2] mmc: esdhc: Add broken timeout quirk for
p4/p5 board
=20
On 07/18/2013 09:19:59 PM, Zhang Haijun-B42677 wrote:
quoted

Thanks.

Regards
Haijun.

quoted
-----Original Message-----
From: Wood Scott-B07421
Sent: Thursday, July 18, 2013 1:14 AM
To: Zhang Haijun-B42677
Cc: linux-mmc@vger.kernel.org; linuxppc-dev@lists.ozlabs.org;
cbouatmailru@gmail.com; cjb@laptop.org; Fleming Andy-AFLEMING; Zhang
Haijun-B42677; Zhang Haijun-B42677
Subject: Re: [PATCH 4/4 V2] mmc: esdhc: Add broken timeout quirk for
p4/p5 board

On 07/17/2013 05:11:31 AM, Haijun Zhang wrote:
quoted
Sometimes command can't be completed within the time give in
eSDHC_SYSCTL[DTOCV]. So just give the max value 0x14 to avoid this
issue.

Signed-off-by: Haijun Zhang <redacted>
---
changes for v2:
	- Rebuild patch of eSDHC host need long time to generate
	 command interrupt

 drivers/mmc/host/sdhci-of-esdhc.c | 6 ++++++
 1 file changed, 6 insertions(+)
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c
b/drivers/mmc/host/sdhci-of-esdhc.c
index 570bca8..30bfb5c 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -325,6 +325,12 @@ static void esdhc_of_platform_init(struct
sdhci_host *host)

 	if (vvn > VENDOR_V_22)
 		host->quirks &=3D ~SDHCI_QUIRK_NO_BUSY_IRQ;
+
+	if ((SVR_SOC_VER(svr) =3D=3D SVR_B4860) ||
+		(SVR_SOC_VER(svr) =3D=3D SVR_P5020) ||
+		(SVR_SOC_VER(svr) =3D=3D SVR_P5040) ||
+		(SVR_SOC_VER(svr) =3D=3D SVR_P4080))
+		host->quirks |=3D SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 }
Please don't line up the continuation lines of the if-condition
with the
quoted
if-body.
[Haijun Wrote:] I'll correct it.
quoted
Please check variant SoCs as well.  If the bug exists on p4080,
then it
quoted
exists on p4040.  Likewise with p5040/p5021, and p5020/p5010.

Is it present on all revisions of these SoCs?  How about p3041,
which is
quoted
usually pretty similar to p5020?  p2040/p2041?  Is there an erratum
number for this problem?
[Haijun Wrote:] I only checked this on these boards.
=20
These aren't boards; they're chips.
=20
Please find out for sure which chips are affected, or else we'll have
support issues later when someone is using a chip you didn't test with.
And always include the fewer-core variants -- if p4080 is affected, then
p4040 is affected, and so on as described above.
[Haijun Wrote:] Ok, I'll try to cover all the chips.
=20
quoted
No errata number yet,
=20
Will one be coming?
[Haijun Wrote:] I need to confirm with integration team. This may take a lo=
ng time for so many chips.
=20
quoted
This quirk only give the host max detecting time value to check card's
response. No impact on performance or other functions.
=20
Does this affect boot time if a card is not present?
[Haijun Wrote:] No impact on boot time. Normally a command can finished wit=
hin 10*HZ, In extreme cases this time will be extended.
=20
-Scott

Re: [PATCH 3/4 V2] mmc: esdhc: Correct host version of T4240-R1.0

From: Kumar Gala <hidden>
Date: 2013-07-22 14:30:32

On Jul 17, 2013, at 5:11 AM, Haijun Zhang wrote:
quoted hunk
Vender version and sdhc spec version of T4240-R1.0 is incorrect.
The right value should be VVN=3D0x13, SVN =3D 0x1. The wrong version
number will break down the ADMA data transfer.
This defect only exist in T4240-R1.0. Will be fixed in T4240-R2.0.
Also share vvn and svr for public use.
=20
Signed-off-by: Haijun Zhang <redacted>
---
changes for V2:
	- Remove broken ADMA quirk.
	- Rebuild patch of  Add quirks to support T4240 board
=20
drivers/mmc/host/sdhci-of-esdhc.c | 29 +++++++++++++----------------
1 file changed, 13 insertions(+), 16 deletions(-)
=20
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c =
b/drivers/mmc/host/sdhci-of-esdhc.c
quoted hunk
index adfaadd..570bca8 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -26,7 +26,7 @@
#define VENDOR_V_22	0x12
#define VENDOR_V_23	0x13
=20
-static u32 svr;
+static u32 svr, vvn;
=20
static u32 esdhc_readl(struct sdhci_host *host, int reg)
{
@@ -43,11 +43,9 @@ static u32 esdhc_readl(struct sdhci_host *host, int =
reg)
	 * For FSL eSDHC, must aligned 4-byte, so use 0xFC to read the
	 * the verdor version number, oxFE is SDHCI_HOST_VERSION.
	 */
-	if ((reg =3D=3D SDHCI_CAPABILITIES) && (ret & =
SDHCI_CAN_DO_ADMA1)) {
-		u32 tmp =3D in_be32(host->ioaddr + =
SDHCI_SLOT_INT_STATUS);
-		tmp =3D (tmp & SDHCI_VENDOR_VER_MASK) >> =
SDHCI_VENDOR_VER_SHIFT;
-		if (tmp > VENDOR_V_22)
-			ret |=3D SDHCI_CAN_DO_ADMA2;
+	if ((reg =3D=3D SDHCI_CAPABILITIES) && (ret & =
SDHCI_CAN_DO_ADMA1) &&
quoted hunk
+		(vvn > VENDOR_V_22)) {
+		ret |=3D SDHCI_CAN_DO_ADMA2;
	}
=20
	return ret;
@@ -63,6 +61,12 @@ static u16 esdhc_readw(struct sdhci_host *host, int =
reg)
		ret =3D in_be32(host->ioaddr + base) & 0xffff;
	else
		ret =3D (in_be32(host->ioaddr + base) >> shift) & =
0xffff;
+
+	/* T4240-R1.0 had a incorrect vendor version and spec version */
+	if ((reg =3D=3D SDHCI_HOST_VERSION) &&
+		((SVR_SOC_VER(svr) =3D=3D SVR_T4240) && (SVR_REV(svr) =3D=3D=
 0x10)))
+		ret =3D (VENDOR_V_23 << SDHCI_VENDOR_VER_SHIFT) | =
SDHCI_SPEC_200;
+
is this check correct if this is on v2.0 Si as well?

- k
quoted hunk
	return ret;
}
=20
@@ -175,17 +179,12 @@ static void esdhc_reset(struct sdhci_host *host, =
u8 mask)
 */
static void esdhci_of_adma_workaround(struct sdhci_host *host, u32 =
intmask)
{
-	u32 tmp;
	bool applicable;
	dma_addr_t dmastart;
	dma_addr_t dmanow;
=20
-	tmp =3D esdhc_readl(host, SDHCI_SLOT_INT_STATUS);
-	tmp =3D (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
-
	applicable =3D (intmask & SDHCI_INT_DATA_END) &&
-		(intmask & SDHCI_INT_BLK_GAP) &&
-		(tmp =3D=3D VENDOR_V_23);
+		(intmask & SDHCI_INT_BLK_GAP) && (vvn =3D=3D =
VENDOR_V_23);
quoted hunk
	if (applicable) {
=20
		esdhc_reset(host, SDHCI_RESET_DATA);
@@ -318,10 +317,9 @@ static void esdhc_of_resume(struct sdhci_host =
*host)
quoted hunk
=20
static void esdhc_of_platform_init(struct sdhci_host *host)
{
-	u32 vvn;
+	svr =3D mfspr(SPRN_SVR);
+	vvn =3D esdhc_readw(host, SDHCI_HOST_VERSION);
=20
-	vvn =3D in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
-	vvn =3D (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
	if (vvn =3D=3D VENDOR_V_22)
		host->quirks2 |=3D SDHCI_QUIRK2_HOST_NO_CMD23;
=20
@@ -390,7 +388,6 @@ static int sdhci_esdhc_probe(struct =
platform_device *pdev)
	struct device_node *np;
	int ret;
=20
-	svr =3D mfspr(SPRN_SVR);
	host =3D sdhci_pltfm_init(pdev, &sdhci_esdhc_pdata, 0);
	if (IS_ERR(host))
		return PTR_ERR(host);
--=20
1.8.0
=20
=20
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

RE: [PATCH 3/4 V2] mmc: esdhc: Correct host version of T4240-R1.0

From: Zhang Haijun-B42677 <hidden>
Date: 2013-07-23 02:03:32


Thanks.

Regards
Haijun.

-----Original Message-----
From: Kumar Gala [mailto:galak@kernel.crashing.org]
Sent: Monday, July 22, 2013 10:30 PM
To: Zhang Haijun-B42677
Cc: linux-mmc@vger.kernel.org; linuxppc-dev@lists.ozlabs.org; Wood Scott-
B07421; cjb@laptop.org; Fleming Andy-AFLEMING; cbouatmailru@gmail.com
Subject: Re: [PATCH 3/4 V2] mmc: esdhc: Correct host version of T4240-
R1.0
=20
=20
On Jul 17, 2013, at 5:11 AM, Haijun Zhang wrote:
=20
quoted
Vender version and sdhc spec version of T4240-R1.0 is incorrect.
The right value should be VVN=3D0x13, SVN =3D 0x1. The wrong version
number will break down the ADMA data transfer.
This defect only exist in T4240-R1.0. Will be fixed in T4240-R2.0.
Also share vvn and svr for public use.

Signed-off-by: Haijun Zhang <redacted>
---
changes for V2:
	- Remove broken ADMA quirk.
	- Rebuild patch of  Add quirks to support T4240 board

drivers/mmc/host/sdhci-of-esdhc.c | 29 +++++++++++++----------------
1 file changed, 13 insertions(+), 16 deletions(-)
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c
b/drivers/mmc/host/sdhci-of-esdhc.c
index adfaadd..570bca8 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -26,7 +26,7 @@
#define VENDOR_V_22	0x12
#define VENDOR_V_23	0x13

-static u32 svr;
+static u32 svr, vvn;

static u32 esdhc_readl(struct sdhci_host *host, int reg) { @@ -43,11
+43,9 @@ static u32 esdhc_readl(struct sdhci_host *host, int reg)
	 * For FSL eSDHC, must aligned 4-byte, so use 0xFC to read the
	 * the verdor version number, oxFE is SDHCI_HOST_VERSION.
	 */
-	if ((reg =3D=3D SDHCI_CAPABILITIES) && (ret & SDHCI_CAN_DO_ADMA1)) {
-		u32 tmp =3D in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
-		tmp =3D (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
-		if (tmp > VENDOR_V_22)
-			ret |=3D SDHCI_CAN_DO_ADMA2;
+	if ((reg =3D=3D SDHCI_CAPABILITIES) && (ret & SDHCI_CAN_DO_ADMA1) &&
+		(vvn > VENDOR_V_22)) {
+		ret |=3D SDHCI_CAN_DO_ADMA2;
	}

	return ret;
@@ -63,6 +61,12 @@ static u16 esdhc_readw(struct sdhci_host *host, int
reg)
quoted
		ret =3D in_be32(host->ioaddr + base) & 0xffff;
	else
		ret =3D (in_be32(host->ioaddr + base) >> shift) & 0xffff;
+
+	/* T4240-R1.0 had a incorrect vendor version and spec version */
+	if ((reg =3D=3D SDHCI_HOST_VERSION) &&
+		((SVR_SOC_VER(svr) =3D=3D SVR_T4240) && (SVR_REV(svr) =3D=3D 0x10)))
+		ret =3D (VENDOR_V_23 << SDHCI_VENDOR_VER_SHIFT) |
SDHCI_SPEC_200;
quoted
+
=20
is this check correct if this is on v2.0 Si as well?
[Haijun Wrote:] Oh, I forgot to rewrite the description above. This defect =
exist both
on T4-R1.0 and T4-R2.0. I'll send patch v3 to correct this. thanks
=20
- k
=20
quoted
	return ret;
}
@@ -175,17 +179,12 @@ static void esdhc_reset(struct sdhci_host *host,
u8 mask)  */ static void esdhci_of_adma_workaround(struct sdhci_host
*host, u32 intmask) {
-	u32 tmp;
	bool applicable;
	dma_addr_t dmastart;
	dma_addr_t dmanow;

-	tmp =3D esdhc_readl(host, SDHCI_SLOT_INT_STATUS);
-	tmp =3D (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
-
	applicable =3D (intmask & SDHCI_INT_DATA_END) &&
-		(intmask & SDHCI_INT_BLK_GAP) &&
-		(tmp =3D=3D VENDOR_V_23);
+		(intmask & SDHCI_INT_BLK_GAP) && (vvn =3D=3D VENDOR_V_23);
	if (applicable) {

		esdhc_reset(host, SDHCI_RESET_DATA); @@ -318,10 +317,9 @@
static
quoted
void esdhc_of_resume(struct sdhci_host *host)

static void esdhc_of_platform_init(struct sdhci_host *host) {
-	u32 vvn;
+	svr =3D mfspr(SPRN_SVR);
+	vvn =3D esdhc_readw(host, SDHCI_HOST_VERSION);

-	vvn =3D in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
-	vvn =3D (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
	if (vvn =3D=3D VENDOR_V_22)
		host->quirks2 |=3D SDHCI_QUIRK2_HOST_NO_CMD23;
@@ -390,7 +388,6 @@ static int sdhci_esdhc_probe(struct platform_device
*pdev)
quoted
	struct device_node *np;
	int ret;

-	svr =3D mfspr(SPRN_SVR);
	host =3D sdhci_pltfm_init(pdev, &sdhci_esdhc_pdata, 0);
	if (IS_ERR(host))
		return PTR_ERR(host);
--
1.8.0


_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev
=20

Re: [PATCH 2/4 V2] mmc: esdhc: workaround for dma err in the last system transaction

From: Zhang Haijun <hidden>
Date: 2013-08-23 06:38:00

Hi, Anton and all

Is there any advice on these two patches ?

[PATCH 2/4 V2] mmc: esdhc: workaround for dma err in the last system 
transaction
[PATCH 3/4 V3] mmc: esdhc: Correct host version of T4240-R1.0-R2.0.


[PATCH 1/4 V4] powerpc/85xx: Add support for 85xx cpu type detection
This patch is Act-by Scott.
Patch 4/4 is split to four patches and Act-by Anton.


Thanks all.



On 07/19/2013 10:21 AM, Zhang Haijun-B42677 wrote:
Hi, all

Expect your advice and any comments.


Thanks.

Regards
Haijun.

quoted
-----Original Message-----
From: Zhang Haijun-B42677
Sent: Wednesday, July 17, 2013 6:11 PM
To: linux-mmc@vger.kernel.org; linuxppc-dev@lists.ozlabs.org
Cc: cbouatmailru@gmail.com; cjb@laptop.org; Wood Scott-B07421; Fleming
Andy-AFLEMING; Zhang Haijun-B42677; Zhang Haijun-B42677
Subject: [PATCH 2/4 V2] mmc: esdhc: workaround for dma err in the last
system transaction

A-004388: eSDHC DMA might not stop if error occurs on system transaction

eSDHC DMA(SDMA/ADMA) might not stop if an error occurs in the last system
transaction. It may continue initiating additional transactions until
software reset for data/all is issued during error recovery. There is not
any data corruption to the SD data. The IRQSTAT[DMAE] is set when the
erratum occurs.
The only conditions under which issues occur are the following:
1. SDMA - For SD Write , the error occurs in the last system transaction.
No issue for SD read
2. ADMA
a. Block count is enabled: For SD write, the error occurs in the last
system transaction. There is no issue for SD read when block count is
enabled.
b. Block count is disabled: Block count is designated by the ADMA
descriptor table, and the error occurs in the last system transaction
when ADMA is executing last descriptor line of table.

eSDHC may initiate additional system transactions. There is no data
integrity issue for case 1 and 2a described below. For case 2b, system
data might be corrupted.

Workaround: Set eSDHC_SYSCTL[RSTD] when IRQSTAT[DMAE] is set. For cases
2a and 2b above, add an extra descriptor line with zero data next to the
last descriptor line.

Signed-off-by: Haijun Zhang <redacted>
---
changes for V2:
	- Update the svr version list

  drivers/mmc/host/sdhci-of-esdhc.c | 112
++++++++++++++++++++++++++++++++++----
  1 file changed, 102 insertions(+), 10 deletions(-)
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-
of-esdhc.c
index 15039e2..adfaadd 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -21,9 +21,13 @@
  #include <linux/mmc/host.h>
  #include "sdhci-pltfm.h"
  #include "sdhci-esdhc.h"
+#include <asm/mpc85xx.h>

  #define VENDOR_V_22	0x12
  #define VENDOR_V_23	0x13
+
+static u32 svr;
+
  static u32 esdhc_readl(struct sdhci_host *host, int reg)  {
  	u32 ret;
@@ -142,6 +146,26 @@ static void esdhc_writeb(struct sdhci_host *host, u8
val, int reg)
  	sdhci_be32bs_writeb(host, val, reg);
  }

+static void esdhc_reset(struct sdhci_host *host, u8 mask) {
+	u32 ier;
+	u32 uninitialized_var(isav);
+
+	if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
+		isav = esdhc_readl(host, SDHCI_INT_ENABLE);
+
+	esdhc_writeb(host, mask, SDHCI_SOFTWARE_RESET);
+	mdelay(100);
+
+	if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) {
+		ier = esdhc_readl(host, SDHCI_INT_ENABLE);
+		ier &= ~SDHCI_INT_ALL_MASK;
+		ier |= isav;
+		esdhc_writel(host, ier, SDHCI_INT_ENABLE);
+		esdhc_writel(host, ier, SDHCI_SIGNAL_ENABLE);
+	}
+}
+
  /*
   * For Abort or Suspend after Stop at Block Gap, ignore the ADMA
   * error(IRQSTAT[ADMAE]) if both Transfer Complete(IRQSTAT[TC]) @@ -
156,25 +180,92 @@ static void esdhci_of_adma_workaround(struct sdhci_host
*host, u32 intmask)
  	dma_addr_t dmastart;
  	dma_addr_t dmanow;

-	tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
+	tmp = esdhc_readl(host, SDHCI_SLOT_INT_STATUS);
  	tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;

  	applicable = (intmask & SDHCI_INT_DATA_END) &&
  		(intmask & SDHCI_INT_BLK_GAP) &&
  		(tmp == VENDOR_V_23);
-	if (!applicable)
+	if (applicable) {
+
+		esdhc_reset(host, SDHCI_RESET_DATA);
+		host->data->error = 0;
+		dmastart = sg_dma_address(host->data->sg);
+		dmanow = dmastart + host->data->bytes_xfered;
+
+		/* Force update to the next DMA block boundary. */
+		dmanow = (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) +
+			SDHCI_DEFAULT_BOUNDARY_SIZE;
+		host->data->bytes_xfered = dmanow - dmastart;
+		esdhc_writel(host, dmanow, SDHCI_DMA_ADDRESS);
+
  		return;
+	}

-	host->data->error = 0;
-	dmastart = sg_dma_address(host->data->sg);
-	dmanow = dmastart + host->data->bytes_xfered;
  	/*
-	 * Force update to the next DMA block boundary.
+	 * Check for A-004388: eSDHC DMA might not stop if error
+	 * occurs on system transaction
+	 * Impact list:
+	 * T4240-R1.0 B4860-R1.0 P1010-R1.0
+	 * P3041-R1.0-R2.0-R1.1 P2041-R1.0-R1.1-R2.0
+	 * P5040-R2.0
  	 */
-	dmanow = (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) +
-		SDHCI_DEFAULT_BOUNDARY_SIZE;
-	host->data->bytes_xfered = dmanow - dmastart;
-	sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS);
+	if (!(((SVR_SOC_VER(svr) == SVR_T4240) && (SVR_REV(svr) == 0x10))
||
+		((SVR_SOC_VER(svr) == SVR_B4860) && (SVR_REV(svr) == 0x10))
||
+		((SVR_SOC_VER(svr) == SVR_P1010) && (SVR_REV(svr) == 0x10))
||
+		((SVR_SOC_VER(svr) == SVR_P3041) && (SVR_REV(svr) <= 0x20))
||
+		((SVR_SOC_VER(svr) == SVR_P2041) && (SVR_REV(svr) <= 0x20))
||
+		((SVR_SOC_VER(svr) == SVR_P5040) && SVR_REV(svr) == 0x20)))
+		return;
+
+	esdhc_reset(host, SDHCI_RESET_DATA);
+
+	if (host->flags & SDHCI_USE_ADMA) {
+		u32 mod, i, offset;
+		u8 *desc;
+		dma_addr_t addr;
+		struct scatterlist *sg;
+		__le32 *dataddr;
+		__le32 *cmdlen;
+
+		/*
+		 * If block count was enabled, in case read transfer there
+		 * is no data was corrupted
+		 */
+		mod = esdhc_readl(host, SDHCI_TRANSFER_MODE);
+		if ((mod & SDHCI_TRNS_BLK_CNT_EN) &&
+			(host->data->flags & MMC_DATA_READ))
+			host->data->error = 0;
+
+		BUG_ON(!host->data);
+		desc = host->adma_desc;
+		for_each_sg(host->data->sg, sg, host->sg_count, i) {
+			addr = sg_dma_address(sg);
+			offset = (4 - (addr & 0x3)) & 0x3;
+			if (offset)
+				desc += 8;
+			desc += 8;
+		}
+
+		/*
+		 * Add an extra zero descriptor next to the
+		 * terminating descriptor.
+		 */
+		desc += 8;
+		WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4);
+
+		dataddr = (__le32 __force *)(desc + 4);
+		cmdlen = (__le32 __force *)desc;
+
+		cmdlen[0] = cpu_to_le32(0);
+		dataddr[0] = cpu_to_le32(0);
+	}
+
+	if ((host->flags & SDHCI_USE_SDMA) &&
+		(host->data->flags & MMC_DATA_READ))
+		host->data->error = 0;
+
+	return;
  }

  static int esdhc_of_enable_dma(struct sdhci_host *host) @@ -299,6 +390,7
@@ static int sdhci_esdhc_probe(struct platform_device *pdev)
  	struct device_node *np;
  	int ret;

+	svr = mfspr(SPRN_SVR);
  	host = sdhci_pltfm_init(pdev, &sdhci_esdhc_pdata, 0);
  	if (IS_ERR(host))
  		return PTR_ERR(host);
--
1.8.0

-- 
Thanks & Regards

Haijun

Re: [PATCH 2/4 V2] mmc: esdhc: workaround for dma err in the last system transaction

From: Scott Wood <hidden>
Date: 2013-08-23 15:40:24

On Fri, 2013-08-23 at 14:39 +0800, Zhang Haijun wrote:
Hi, Anton and all

Is there any advice on these two patches ?

[PATCH 2/4 V2] mmc: esdhc: workaround for dma err in the last system 
transaction
[PATCH 3/4 V3] mmc: esdhc: Correct host version of T4240-R1.0-R2.0.


[PATCH 1/4 V4] powerpc/85xx: Add support for 85xx cpu type detection
This patch is Act-by Scott.
Patch 4/4 is split to four patches and Act-by Anton.


Thanks all.

[snip]
quoted
quoted
+	if (!(((SVR_SOC_VER(svr) == SVR_T4240) && (SVR_REV(svr) == 0x10))
||
+		((SVR_SOC_VER(svr) == SVR_B4860) && (SVR_REV(svr) == 0x10))
||
+		((SVR_SOC_VER(svr) == SVR_P1010) && (SVR_REV(svr) == 0x10))
||
+		((SVR_SOC_VER(svr) == SVR_P3041) && (SVR_REV(svr) <= 0x20))
||
+		((SVR_SOC_VER(svr) == SVR_P2041) && (SVR_REV(svr) <= 0x20))
||
+		((SVR_SOC_VER(svr) == SVR_P5040) && SVR_REV(svr) == 0x20)))
+		return;
You need to include variants here.  If P5040 is affected, then P5021 is
affected.  If P2041 is affected, then P2040 is affected, etc.

-Scott

Re: [PATCH 2/4 V2] mmc: esdhc: workaround for dma err in the last system transaction

From: Zhang Haijun <hidden>
Date: 2013-08-26 00:59:41

On 08/23/2013 11:40 PM, Scott Wood wrote:
On Fri, 2013-08-23 at 14:39 +0800, Zhang Haijun wrote:
quoted
Hi, Anton and all

Is there any advice on these two patches ?

[PATCH 2/4 V2] mmc: esdhc: workaround for dma err in the last system
transaction
[PATCH 3/4 V3] mmc: esdhc: Correct host version of T4240-R1.0-R2.0.


[PATCH 1/4 V4] powerpc/85xx: Add support for 85xx cpu type detection
This patch is Act-by Scott.
Patch 4/4 is split to four patches and Act-by Anton.


Thanks all.

[snip]
quoted
quoted
quoted
+	if (!(((SVR_SOC_VER(svr) == SVR_T4240) && (SVR_REV(svr) == 0x10))
||
+		((SVR_SOC_VER(svr) == SVR_B4860) && (SVR_REV(svr) == 0x10))
||
+		((SVR_SOC_VER(svr) == SVR_P1010) && (SVR_REV(svr) == 0x10))
||
+		((SVR_SOC_VER(svr) == SVR_P3041) && (SVR_REV(svr) <= 0x20))
||
+		((SVR_SOC_VER(svr) == SVR_P2041) && (SVR_REV(svr) <= 0x20))
||
+		((SVR_SOC_VER(svr) == SVR_P5040) && SVR_REV(svr) == 0x20)))
+		return;
You need to include variants here.  If P5040 is affected, then P5021 is
affected.  If P2041 is affected, then P2040 is affected, etc.

-Scott
Hi, Scott

This workaround is for CR:ENGR00229586: A-005055, Configs Affected 
onlylist these soc and its version.
I was also wonder why only these boards?

But Ican't add soc like P5021 as I think it should be. Maybe there are 
some difference between them.

-- 
Thanks & Regards

Haijun

Re: [PATCH 2/4 V2] mmc: esdhc: workaround for dma err in the last system transaction

From: Zhang Haijun <hidden>
Date: 2013-08-26 01:46:51

On 08/26/2013 09:03 AM, Zhang Haijun wrote:
On 08/23/2013 11:40 PM, Scott Wood wrote:
quoted
On Fri, 2013-08-23 at 14:39 +0800, Zhang Haijun wrote:
quoted
Hi, Anton and all

Is there any advice on these two patches ?

[PATCH 2/4 V2] mmc: esdhc: workaround for dma err in the last system
transaction
[PATCH 3/4 V3] mmc: esdhc: Correct host version of T4240-R1.0-R2.0.


[PATCH 1/4 V4] powerpc/85xx: Add support for 85xx cpu type detection
This patch is Act-by Scott.
Patch 4/4 is split to four patches and Act-by Anton.


Thanks all.

[snip]
quoted
quoted
quoted
+	if (!(((SVR_SOC_VER(svr) == SVR_T4240) && (SVR_REV(svr) == 0x10))
||
+		((SVR_SOC_VER(svr) == SVR_B4860) && (SVR_REV(svr) == 0x10))
||
+		((SVR_SOC_VER(svr) == SVR_P1010) && (SVR_REV(svr) == 0x10))
||
+		((SVR_SOC_VER(svr) == SVR_P3041) && (SVR_REV(svr) <= 0x20))
||
+		((SVR_SOC_VER(svr) == SVR_P2041) && (SVR_REV(svr) <= 0x20))
||
+		((SVR_SOC_VER(svr) == SVR_P5040) && SVR_REV(svr) == 0x20)))
+		return;
You need to include variants here.  If P5040 is affected, then P5021 is
affected.  If P2041 is affected, then P2040 is affected, etc.

-Scott
Hi, Scott

This workaround is for CR:ENGR00229586: A-005055, Configs Affected 
onlylist these soc and its version.
I was also wonder why only these boards?

But Ican't add soc like P5021 as I think it should be. Maybe there are 
some difference between them.

-- 
Thanks & Regards

Haijun
Hi, Scott

I found there are update about this errata.

I'll update thispatch.

Thanks.

-- 
Thanks & Regards

Haijun

Re: [PATCH 2/4 V2] mmc: esdhc: workaround for dma err in the last system transaction

From: Scott Wood <hidden>
Date: 2013-08-26 16:36:55

On Mon, 2013-08-26 at 09:03 +0800, Zhang Haijun wrote:
On 08/23/2013 11:40 PM, Scott Wood wrote:
quoted
On Fri, 2013-08-23 at 14:39 +0800, Zhang Haijun wrote:
quoted
Hi, Anton and all

Is there any advice on these two patches ?

[PATCH 2/4 V2] mmc: esdhc: workaround for dma err in the last system 
transaction
[PATCH 3/4 V3] mmc: esdhc: Correct host version of T4240-R1.0-R2.0.


[PATCH 1/4 V4] powerpc/85xx: Add support for 85xx cpu type detection
This patch is Act-by Scott.
Patch 4/4 is split to four patches and Act-by Anton.


Thanks all.

[snip]
quoted
quoted
quoted
+	if (!(((SVR_SOC_VER(svr) == SVR_T4240) && (SVR_REV(svr) == 0x10))
||
+		((SVR_SOC_VER(svr) == SVR_B4860) && (SVR_REV(svr) == 0x10))
||
+		((SVR_SOC_VER(svr) == SVR_P1010) && (SVR_REV(svr) == 0x10))
||
+		((SVR_SOC_VER(svr) == SVR_P3041) && (SVR_REV(svr) <= 0x20))
||
+		((SVR_SOC_VER(svr) == SVR_P2041) && (SVR_REV(svr) <= 0x20))
||
+		((SVR_SOC_VER(svr) == SVR_P5040) && SVR_REV(svr) == 0x20)))
+		return;
You need to include variants here.  If P5040 is affected, then P5021 is
affected.  If P2041 is affected, then P2040 is affected, etc.

-Scott
Hi, Scott

This workaround is for CR:ENGR00229586: A-005055, Configs Affected
only list these soc and its version.
I was also wonder why only these boards?

But I can't add soc like P5021 as I think it should be. Maybe there
are some difference between them.
The only difference between P5040 and P5021 is the number of cores
enabled.  It is physically the same silicon.  Likewise with a lot of
other variants.

-Scott
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help