* [PATCH V4] Powerpc eSDHC Recover from the ADMA error
@ 2012-09-20 2:19 Haijun.Zhang
2012-09-20 2:57 ` Anton Vorontsov
0 siblings, 1 reply; 10+ messages in thread
From: Haijun.Zhang @ 2012-09-20 2:19 UTC (permalink / raw)
To: linux-mmc; +Cc: Haijun Zhang, Jerry Huang, Anton Vorontsov
From: Haijun Zhang <Haijun.Zhang@freescale.com>
Signed-off-by: Haijun Zhang <Haijun.Zhang@freescale.com>
Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
CC: Anton Vorontsov <cbouatmailru@gmail.com>
---
changes for v4:
- Correct inconsistent issue
changes for v3:
- Correct the if statement in function workground
changes for v2:
- Invert the condition of the if statement in function workground
drivers/mmc/host/sdhci-of-esdhc.c | 52 ++++++++++++++++++++++++++++++++++++-
drivers/mmc/host/sdhci.c | 2 +
drivers/mmc/host/sdhci.h | 5 +++-
3 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 1cba55a..9c6bf78 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -21,6 +21,7 @@
#include "sdhci-esdhc.h"
#define VENDOR_V_22 0x12
+#define VENDOR_V_23 0x13
static u32 esdhc_readl(struct sdhci_host *host, int reg)
{
u32 ret;
@@ -83,6 +84,18 @@ static u8 esdhc_readb(struct sdhci_host *host, int reg)
return ret;
}
+static void esdhc_writel(struct sdhci_host *host, u32 val, int reg)
+{
+ /*
+ * Enable IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE]
+ * when SYSCTL[RSTD]) is set for some special operations.
+ * No any impact other operation.
+ */
+ if (reg == SDHCI_INT_ENABLE)
+ val |= SDHCI_INT_BLK_GAP;
+ sdhci_be32bs_writel(host, val, reg);
+}
+
static void esdhc_writew(struct sdhci_host *host, u16 val, int reg)
{
if (reg == SDHCI_BLOCK_SIZE) {
@@ -138,6 +151,42 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
return of_host->clock / 256 / 16;
}
+/*
+ * For Abort or Suspend after Stop at Block Gap, ignore the ADMA
+ * error(IRQSTAT[ADMAE]) if both Transfer Complete(IRQSTAT[TC])
+ * and Block Gap Event(IRQSTAT[BGE]) are also set.
+ * For Continue, apply soft reset for data(SYSCTL[RSTD]);
+ * and re-issue the entire read
+ * transaction from beginning.
+ */
+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 = in_be32(host->ioaddr + 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)
+ 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.
+ */
+ dmanow = (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) +
+ SDHCI_DEFAULT_BOUNDARY_SIZE;
+ host->data->bytes_xfered = dmanow - dmastart;
+ sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS);
+}
+
#ifdef CONFIG_PM
static u32 esdhc_proctl;
static void esdhc_of_suspend(struct sdhci_host *host)
@@ -164,7 +213,7 @@ struct sdhci_of_data sdhci_esdhc = {
.read_l = esdhc_readl,
.read_w = esdhc_readw,
.read_b = esdhc_readb,
- .write_l = sdhci_be32bs_writel,
+ .write_l = esdhc_writel,
.write_w = esdhc_writew,
.write_b = esdhc_writeb,
.set_clock = esdhc_set_clock,
@@ -175,5 +224,6 @@ struct sdhci_of_data sdhci_esdhc = {
.platform_suspend = esdhc_of_suspend,
.platform_resume = esdhc_of_resume,
#endif
+ .adma_workaround = esdhci_of_adma_workaround,
},
};
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 684f1a4..3d9365a 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2143,6 +2143,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
printk(KERN_ERR "%s: ADMA error\n", mmc_hostname(host->mmc));
sdhci_show_adma_error(host);
host->data->error = -EIO;
+ if (host->ops->adma_workaround)
+ host->ops->adma_workaround(host, intmask);
}
if (host->data->error)
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 209f707..138d8fc 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -120,6 +120,7 @@
#define SDHCI_SIGNAL_ENABLE 0x38
#define SDHCI_INT_RESPONSE 0x00000001
#define SDHCI_INT_DATA_END 0x00000002
+#define SDHCI_INT_BLK_GAP 0x00000004
#define SDHCI_INT_DMA_END 0x00000008
#define SDHCI_INT_SPACE_AVAIL 0x00000010
#define SDHCI_INT_DATA_AVAIL 0x00000020
@@ -146,7 +147,8 @@
#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \
SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \
SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \
- SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR)
+ SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR | \
+ SDHCI_INT_BLK_GAP)
#define SDHCI_INT_ALL_MASK ((unsigned int)-1)
#define SDHCI_ACMD12_ERR 0x3C
@@ -275,6 +277,7 @@ struct sdhci_ops {
int (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
void (*platform_suspend)(struct sdhci_host *host);
void (*platform_resume)(struct sdhci_host *host);
+ void (*adma_workaround)(struct sdhci_host *host, u32 intmask);
};
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH V4] Powerpc eSDHC Recover from the ADMA error
2012-09-20 2:19 [PATCH V4] Powerpc eSDHC Recover from the ADMA error Haijun.Zhang
@ 2012-09-20 2:57 ` Anton Vorontsov
2012-10-23 5:49 ` Huang Changming-R66093
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Anton Vorontsov @ 2012-09-20 2:57 UTC (permalink / raw)
To: Haijun.Zhang; +Cc: linux-mmc, Jerry Huang
On Thu, Sep 20, 2012 at 10:19:23AM +0800, Haijun.Zhang@freescale.com wrote:
> From: Haijun Zhang <Haijun.Zhang@freescale.com>
>
> Signed-off-by: Haijun Zhang <Haijun.Zhang@freescale.com>
> Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
> CC: Anton Vorontsov <cbouatmailru@gmail.com>
> ---
This one looks perfect, thanks!
Acked-by: Anton Vorontsov <cbouatmailru@gmail.com>
> changes for v4:
> - Correct inconsistent issue
>
> changes for v3:
> - Correct the if statement in function workground
>
> changes for v2:
> - Invert the condition of the if statement in function workground
^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: [PATCH V4] Powerpc eSDHC Recover from the ADMA error
2012-09-20 2:57 ` Anton Vorontsov
@ 2012-10-23 5:49 ` Huang Changming-R66093
2012-11-05 9:10 ` Huang Changming-R66093
2012-11-13 7:51 ` Huang Changming-R66093
2 siblings, 0 replies; 10+ messages in thread
From: Huang Changming-R66093 @ 2012-10-23 5:49 UTC (permalink / raw)
To: Chris Ball
Cc: linux-mmc@vger.kernel.org, Zhang Haijun-B42677, Anton Vorontsov
HI, Chris,
This patch has been ACKED by Anton one month ago.
Could you have any comment about it?
Best Regards
Jerry Huang
> -----Original Message-----
> From: Anton Vorontsov [mailto:cbouatmailru@gmail.com]
> Sent: Thursday, September 20, 2012 10:57 AM
> To: Zhang Haijun-B42677
> Cc: linux-mmc@vger.kernel.org; Huang Changming-R66093
> Subject: Re: [PATCH V4] Powerpc eSDHC Recover from the ADMA error
>
> On Thu, Sep 20, 2012 at 10:19:23AM +0800, Haijun.Zhang@freescale.com
> wrote:
> > From: Haijun Zhang <Haijun.Zhang@freescale.com>
> >
> > Signed-off-by: Haijun Zhang <Haijun.Zhang@freescale.com>
> > Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
> > CC: Anton Vorontsov <cbouatmailru@gmail.com>
> > ---
>
> This one looks perfect, thanks!
>
> Acked-by: Anton Vorontsov <cbouatmailru@gmail.com>
>
> > changes for v4:
> > - Correct inconsistent issue
> >
> > changes for v3:
> > - Correct the if statement in function workground
> >
> > changes for v2:
> > - Invert the condition of the if statement in function
> workground
^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: [PATCH V4] Powerpc eSDHC Recover from the ADMA error
2012-09-20 2:57 ` Anton Vorontsov
2012-10-23 5:49 ` Huang Changming-R66093
@ 2012-11-05 9:10 ` Huang Changming-R66093
2012-11-13 7:51 ` Huang Changming-R66093
2 siblings, 0 replies; 10+ messages in thread
From: Huang Changming-R66093 @ 2012-11-05 9:10 UTC (permalink / raw)
To: Chris Ball
Cc: linux-mmc@vger.kernel.org, Anton Vorontsov, Zhang Haijun-B42677
Hi, Chris
Have you any comment about this patch?
Anton has ACKed on Sep 20, and no any other feedback.
Best Regards
Jerry Huang
> -----Original Message-----
> From: Anton Vorontsov [mailto:cbouatmailru@gmail.com]
> Sent: Thursday, September 20, 2012 10:57 AM
> To: Zhang Haijun-B42677
> Cc: linux-mmc@vger.kernel.org; Huang Changming-R66093
> Subject: Re: [PATCH V4] Powerpc eSDHC Recover from the ADMA error
>
> On Thu, Sep 20, 2012 at 10:19:23AM +0800, Haijun.Zhang@freescale.com
> wrote:
> > From: Haijun Zhang <Haijun.Zhang@freescale.com>
> >
> > Signed-off-by: Haijun Zhang <Haijun.Zhang@freescale.com>
> > Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
> > CC: Anton Vorontsov <cbouatmailru@gmail.com>
> > ---
>
> This one looks perfect, thanks!
>
> Acked-by: Anton Vorontsov <cbouatmailru@gmail.com>
>
> > changes for v4:
> > - Correct inconsistent issue
> >
> > changes for v3:
> > - Correct the if statement in function workground
> >
> > changes for v2:
> > - Invert the condition of the if statement in function
> workground
^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: [PATCH V4] Powerpc eSDHC Recover from the ADMA error
2012-09-20 2:57 ` Anton Vorontsov
2012-10-23 5:49 ` Huang Changming-R66093
2012-11-05 9:10 ` Huang Changming-R66093
@ 2012-11-13 7:51 ` Huang Changming-R66093
2012-11-17 20:56 ` Chris Ball
2 siblings, 1 reply; 10+ messages in thread
From: Huang Changming-R66093 @ 2012-11-13 7:51 UTC (permalink / raw)
To: Chris Ball
Cc: linux-mmc@vger.kernel.org, Anton Vorontsov, Zhang Haijun-B42677
Hi, Chris,
This patch has been ACKed by Anton on Sep 20.
Have you any comment about it?
Best Regards
Jerry Huang
> -----Original Message-----
> From: Anton Vorontsov [mailto:cbouatmailru@gmail.com]
> Sent: Thursday, September 20, 2012 10:57 AM
> To: Zhang Haijun-B42677
> Cc: linux-mmc@vger.kernel.org; Huang Changming-R66093
> Subject: Re: [PATCH V4] Powerpc eSDHC Recover from the ADMA error
>
> On Thu, Sep 20, 2012 at 10:19:23AM +0800, Haijun.Zhang@freescale.com
> wrote:
> > From: Haijun Zhang <Haijun.Zhang@freescale.com>
> >
> > Signed-off-by: Haijun Zhang <Haijun.Zhang@freescale.com>
> > Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
> > CC: Anton Vorontsov <cbouatmailru@gmail.com>
> > ---
>
> This one looks perfect, thanks!
>
> Acked-by: Anton Vorontsov <cbouatmailru@gmail.com>
>
> > changes for v4:
> > - Correct inconsistent issue
> >
> > changes for v3:
> > - Correct the if statement in function workground
> >
> > changes for v2:
> > - Invert the condition of the if statement in function
> workground
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH V4] Powerpc eSDHC Recover from the ADMA error
2012-11-13 7:51 ` Huang Changming-R66093
@ 2012-11-17 20:56 ` Chris Ball
2012-11-29 5:49 ` Zhang Haijun-B42677
0 siblings, 1 reply; 10+ messages in thread
From: Chris Ball @ 2012-11-17 20:56 UTC (permalink / raw)
To: Huang Changming-R66093
Cc: linux-mmc@vger.kernel.org, Anton Vorontsov, Zhang Haijun-B42677
Hi,
On Tue, Nov 13 2012, Huang Changming-R66093 wrote:
> Hi, Chris,
> This patch has been ACKed by Anton on Sep 20.
> Have you any comment about it?
Something weird has happened with this patch -- the latest version has
no commit message even though an earlier version did, and there seem
to be two separate runs of v2-v3-v4 with the same subject but with
different changes in each.
Could you merge the changelog into a single list of changes, rebase
against mmc-next, add the full commit message and Anton's ACK, and
resend? Then I'll merge it.
Thanks,
- Chris.
--
Chris Ball <cjb@laptop.org> <http://printf.net/>
One Laptop Per Child
^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: [PATCH V4] Powerpc eSDHC Recover from the ADMA error
2012-11-17 20:56 ` Chris Ball
@ 2012-11-29 5:49 ` Zhang Haijun-B42677
0 siblings, 0 replies; 10+ messages in thread
From: Zhang Haijun-B42677 @ 2012-11-29 5:49 UTC (permalink / raw)
To: Chris Ball, Huang Changming-R66093
Cc: linux-mmc@vger.kernel.org, Anton Vorontsov
Hi chris,
Sorry to miss this mail.
Patch V4 for this patch had resend. Pls review.
Thanks.
Regards
Haijun.
> -----Original Message-----
> From: linux-mmc-owner@vger.kernel.org [mailto:linux-mmc-
> owner@vger.kernel.org] On Behalf Of Chris Ball
> Sent: Sunday, November 18, 2012 4:56 AM
> To: Huang Changming-R66093
> Cc: linux-mmc@vger.kernel.org; Anton Vorontsov; Zhang Haijun-B42677
> Subject: Re: [PATCH V4] Powerpc eSDHC Recover from the ADMA error
>
> Hi,
>
> On Tue, Nov 13 2012, Huang Changming-R66093 wrote:
> > Hi, Chris,
> > This patch has been ACKed by Anton on Sep 20.
> > Have you any comment about it?
>
> Something weird has happened with this patch -- the latest version has no
> commit message even though an earlier version did, and there seem to be
> two separate runs of v2-v3-v4 with the same subject but with different
> changes in each.
>
> Could you merge the changelog into a single list of changes, rebase
> against mmc-next, add the full commit message and Anton's ACK, and resend?
> Then I'll merge it.
>
> Thanks,
>
> - Chris.
> --
> Chris Ball <cjb@laptop.org> <http://printf.net/>
> One Laptop Per Child
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org More majordomo info at
> http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH V4] Powerpc eSDHC Recover from the ADMA error
@ 2012-11-29 5:22 Haijun Zhang
0 siblings, 0 replies; 10+ messages in thread
From: Haijun Zhang @ 2012-11-29 5:22 UTC (permalink / raw)
To: linux-mmc; +Cc: Haijun Zhang, Jerry Huang, Chris Ball
Signed-off-by: Haijun Zhang <Haijun.Zhang@freescale.com>
Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
Acked-by: Anton Vorontsov <cbouatmailru@gmail.com>
CC: Chris Ball <cjb@laptop.org>
---
changes for v4:
- Correct inconsistent issue
changes for v3:
- Correct the if statement in function workground
changes for v2:
- Invert the condition of the if statement in function workground
drivers/mmc/host/sdhci-of-esdhc.c | 52 ++++++++++++++++++++++++++++++++++++-
drivers/mmc/host/sdhci.c | 2 +
drivers/mmc/host/sdhci.h | 5 +++-
3 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 1cba55a..9c6bf78 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -21,6 +21,7 @@
#include "sdhci-esdhc.h"
#define VENDOR_V_22 0x12
+#define VENDOR_V_23 0x13
static u32 esdhc_readl(struct sdhci_host *host, int reg)
{
u32 ret;
@@ -83,6 +84,18 @@ static u8 esdhc_readb(struct sdhci_host *host, int reg)
return ret;
}
+static void esdhc_writel(struct sdhci_host *host, u32 val, int reg)
+{
+ /*
+ * Enable IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE]
+ * when SYSCTL[RSTD]) is set for some special operations.
+ * No any impact other operation.
+ */
+ if (reg == SDHCI_INT_ENABLE)
+ val |= SDHCI_INT_BLK_GAP;
+ sdhci_be32bs_writel(host, val, reg);
+}
+
static void esdhc_writew(struct sdhci_host *host, u16 val, int reg)
{
if (reg == SDHCI_BLOCK_SIZE) {
@@ -138,6 +151,42 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
return of_host->clock / 256 / 16;
}
+/*
+ * For Abort or Suspend after Stop at Block Gap, ignore the ADMA
+ * error(IRQSTAT[ADMAE]) if both Transfer Complete(IRQSTAT[TC])
+ * and Block Gap Event(IRQSTAT[BGE]) are also set.
+ * For Continue, apply soft reset for data(SYSCTL[RSTD]);
+ * and re-issue the entire read
+ * transaction from beginning.
+ */
+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 = in_be32(host->ioaddr + 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)
+ 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.
+ */
+ dmanow = (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) +
+ SDHCI_DEFAULT_BOUNDARY_SIZE;
+ host->data->bytes_xfered = dmanow - dmastart;
+ sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS);
+}
+
#ifdef CONFIG_PM
static u32 esdhc_proctl;
static void esdhc_of_suspend(struct sdhci_host *host)
@@ -164,7 +213,7 @@ struct sdhci_of_data sdhci_esdhc = {
.read_l = esdhc_readl,
.read_w = esdhc_readw,
.read_b = esdhc_readb,
- .write_l = sdhci_be32bs_writel,
+ .write_l = esdhc_writel,
.write_w = esdhc_writew,
.write_b = esdhc_writeb,
.set_clock = esdhc_set_clock,
@@ -175,5 +224,6 @@ struct sdhci_of_data sdhci_esdhc = {
.platform_suspend = esdhc_of_suspend,
.platform_resume = esdhc_of_resume,
#endif
+ .adma_workaround = esdhci_of_adma_workaround,
},
};
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 684f1a4..3d9365a 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2143,6 +2143,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
printk(KERN_ERR "%s: ADMA error\n", mmc_hostname(host->mmc));
sdhci_show_adma_error(host);
host->data->error = -EIO;
+ if (host->ops->adma_workaround)
+ host->ops->adma_workaround(host, intmask);
}
if (host->data->error)
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 209f707..138d8fc 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -120,6 +120,7 @@
#define SDHCI_SIGNAL_ENABLE 0x38
#define SDHCI_INT_RESPONSE 0x00000001
#define SDHCI_INT_DATA_END 0x00000002
+#define SDHCI_INT_BLK_GAP 0x00000004
#define SDHCI_INT_DMA_END 0x00000008
#define SDHCI_INT_SPACE_AVAIL 0x00000010
#define SDHCI_INT_DATA_AVAIL 0x00000020
@@ -146,7 +147,8 @@
#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \
SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \
SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \
- SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR)
+ SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR | \
+ SDHCI_INT_BLK_GAP)
#define SDHCI_INT_ALL_MASK ((unsigned int)-1)
#define SDHCI_ACMD12_ERR 0x3C
@@ -275,6 +277,7 @@ struct sdhci_ops {
int (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
void (*platform_suspend)(struct sdhci_host *host);
void (*platform_resume)(struct sdhci_host *host);
+ void (*adma_workaround)(struct sdhci_host *host, u32 intmask);
};
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH V4] Powerpc eSDHC Recover from the ADMA error
@ 2012-08-31 7:36 Haijun.Zhang
2012-09-07 6:12 ` Huang Changming-R66093
0 siblings, 1 reply; 10+ messages in thread
From: Haijun.Zhang @ 2012-08-31 7:36 UTC (permalink / raw)
To: linux-mmc; +Cc: Haijun Zhang, Jerry Huang
From: Haijun Zhang <Haijun.Zhang@freescale.com>
False ADMA Error might be reported when ADMA is used for multiple block
read command with Stop at Block Gap. If PROCTL[SABGREQ] is set
when the particular block's data is received by the System side logic
before entire block(with CRC) data is received by the SD side logic,
and also if ADMA descriptor line is fetched at the same time,
then DMA engine might report false ADMA error. eSDHC might not be able
to Continue(PROCTL[CREQ]=1)after Stop at Block Gap.
This issue will impact the eSDHC IP VVN2.3.
Signed-off-by: Haijun Zhang <Haijun.Zhang@freescale.com>
Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
---
changes for v4:
- Add comments for the Enable of IRQSTATEN[BGESEN].
changes for v3:
- Add codes to check eSDHC VVN2.3
changes for v2:
- Change the subject with Powerpc prefix
- Change the code for coding style issue
drivers/mmc/host/sdhci-of-esdhc.c | 50 ++++++++++++++++++++++++++++++++++++-
drivers/mmc/host/sdhci.c | 2 +
drivers/mmc/host/sdhci.h | 5 +++-
3 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 91b328b..3ebee9b 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -21,6 +21,7 @@
#include "sdhci-esdhc.h"
#define VENDOR_V_22 0x12
+#define VENDOR_V_23 0x13
static u32 esdhc_readl(struct sdhci_host *host, int reg)
{
u32 ret;
@@ -84,6 +85,18 @@ static u8 esdhc_readb(struct sdhci_host *host, int reg)
return ret;
}
+static void esdhc_writel(struct sdhci_host *host, u32 val, int reg)
+{
+ /*
+ * Enable IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE]
+ * when SYSCTL[RSTD]) is set for some special operations.
+ * No any impact other operation.
+ */
+ if (reg == SDHCI_INT_ENABLE)
+ val |= SDHCI_INT_BLK_GAP;
+ sdhci_be32bs_writel(host, val, reg);
+}
+
static void esdhc_writew(struct sdhci_host *host, u16 val, int reg)
{
if (reg == SDHCI_BLOCK_SIZE) {
@@ -139,6 +152,40 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
return of_host->clock / 256 / 16;
}
+/*
+ * For Abort or Suspend after Stop at Block Gap, ignore the ADMA
+ * error(IRQSTAT[ADMAE]) if both Transfer Complete(IRQSTAT[TC])
+ * and Block Gap Event(IRQSTAT[BGE]) are also set.
+ * For Continue, apply soft reset for data(SYSCTL[RSTD]);
+ * and re-issue the entire read
+ * transaction from beginning.
+ */
+static void esdhci_of_adma_workaround(struct sdhci_host *host, u32 intmask)
+{
+ u32 tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
+
+ tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
+ if (tmp == VENDOR_V_23) {
+ if ((intmask & SDHCI_INT_DATA_END) &&
+ (intmask & SDHCI_INT_BLK_GAP)) {
+ dma_addr_t dmastart;
+ dma_addr_t dmanow;
+
+ 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;
+ sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS);
+ }
+ }
+}
+
#ifdef CONFIG_PM
static u32 esdhc_proctl;
static void esdhc_of_suspend(struct sdhci_host *host)
@@ -166,7 +213,7 @@ struct sdhci_of_data sdhci_esdhc = {
.read_l = esdhc_readl,
.read_w = esdhc_readw,
.read_b = esdhc_readb,
- .write_l = sdhci_be32bs_writel,
+ .write_l = esdhc_writel,
.write_w = esdhc_writew,
.write_b = esdhc_writeb,
.set_clock = esdhc_set_clock,
@@ -177,5 +224,6 @@ struct sdhci_of_data sdhci_esdhc = {
.platform_suspend = esdhc_of_suspend,
.platform_resume = esdhc_of_resume,
#endif
+ .adma_workaround = esdhci_of_adma_workaround,
},
};
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 684f1a4..3d9365a 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2143,6 +2143,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
printk(KERN_ERR "%s: ADMA error\n", mmc_hostname(host->mmc));
sdhci_show_adma_error(host);
host->data->error = -EIO;
+ if (host->ops->adma_workaround)
+ host->ops->adma_workaround(host, intmask);
}
if (host->data->error)
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 209f707..138d8fc 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -120,6 +120,7 @@
#define SDHCI_SIGNAL_ENABLE 0x38
#define SDHCI_INT_RESPONSE 0x00000001
#define SDHCI_INT_DATA_END 0x00000002
+#define SDHCI_INT_BLK_GAP 0x00000004
#define SDHCI_INT_DMA_END 0x00000008
#define SDHCI_INT_SPACE_AVAIL 0x00000010
#define SDHCI_INT_DATA_AVAIL 0x00000020
@@ -146,7 +147,8 @@
#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \
SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \
SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \
- SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR)
+ SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR | \
+ SDHCI_INT_BLK_GAP)
#define SDHCI_INT_ALL_MASK ((unsigned int)-1)
#define SDHCI_ACMD12_ERR 0x3C
@@ -275,6 +277,7 @@ struct sdhci_ops {
int (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
void (*platform_suspend)(struct sdhci_host *host);
void (*platform_resume)(struct sdhci_host *host);
+ void (*adma_workaround)(struct sdhci_host *host, u32 intmask);
};
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* RE: [PATCH V4] Powerpc eSDHC Recover from the ADMA error
2012-08-31 7:36 Haijun.Zhang
@ 2012-09-07 6:12 ` Huang Changming-R66093
0 siblings, 0 replies; 10+ messages in thread
From: Huang Changming-R66093 @ 2012-09-07 6:12 UTC (permalink / raw)
To: Zhang Haijun-B42677, linux-mmc@vger.kernel.org
Hi,
Anyone has some comment?
Best Regards
Jerry Huang
> -----Original Message-----
> From: Zhang Haijun-B42677
> Sent: Friday, August 31, 2012 3:36 PM
> To: linux-mmc@vger.kernel.org
> Cc: Zhang Haijun-B42677; Huang Changming-R66093
> Subject: [PATCH V4] Powerpc eSDHC Recover from the ADMA error
>
> From: Haijun Zhang <Haijun.Zhang@freescale.com>
>
> False ADMA Error might be reported when ADMA is used for multiple block
> read command with Stop at Block Gap. If PROCTL[SABGREQ] is set
> when the particular block's data is received by the System side logic
> before entire block(with CRC) data is received by the SD side logic,
> and also if ADMA descriptor line is fetched at the same time,
> then DMA engine might report false ADMA error. eSDHC might not be able
> to Continue(PROCTL[CREQ]=1)after Stop at Block Gap.
> This issue will impact the eSDHC IP VVN2.3.
>
>
> Signed-off-by: Haijun Zhang <Haijun.Zhang@freescale.com>
> Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
> ---
> changes for v4:
> - Add comments for the Enable of IRQSTATEN[BGESEN].
>
> changes for v3:
> - Add codes to check eSDHC VVN2.3
>
> changes for v2:
> - Change the subject with Powerpc prefix
> - Change the code for coding style issue
>
> drivers/mmc/host/sdhci-of-esdhc.c | 50
> ++++++++++++++++++++++++++++++++++++-
> drivers/mmc/host/sdhci.c | 2 +
> drivers/mmc/host/sdhci.h | 5 +++-
> 3 files changed, 55 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-
> of-esdhc.c
> index 91b328b..3ebee9b 100644
> --- a/drivers/mmc/host/sdhci-of-esdhc.c
> +++ b/drivers/mmc/host/sdhci-of-esdhc.c
> @@ -21,6 +21,7 @@
> #include "sdhci-esdhc.h"
>
> #define VENDOR_V_22 0x12
> +#define VENDOR_V_23 0x13
> static u32 esdhc_readl(struct sdhci_host *host, int reg)
> {
> u32 ret;
> @@ -84,6 +85,18 @@ static u8 esdhc_readb(struct sdhci_host *host, int reg)
> return ret;
> }
>
> +static void esdhc_writel(struct sdhci_host *host, u32 val, int reg)
> +{
> + /*
> + * Enable IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE]
> + * when SYSCTL[RSTD]) is set for some special operations.
> + * No any impact other operation.
> + */
> + if (reg == SDHCI_INT_ENABLE)
> + val |= SDHCI_INT_BLK_GAP;
> + sdhci_be32bs_writel(host, val, reg);
> +}
> +
> static void esdhc_writew(struct sdhci_host *host, u16 val, int reg)
> {
> if (reg == SDHCI_BLOCK_SIZE) {
> @@ -139,6 +152,40 @@ static unsigned int esdhc_of_get_min_clock(struct
> sdhci_host *host)
> return of_host->clock / 256 / 16;
> }
>
> +/*
> + * For Abort or Suspend after Stop at Block Gap, ignore the ADMA
> + * error(IRQSTAT[ADMAE]) if both Transfer Complete(IRQSTAT[TC])
> + * and Block Gap Event(IRQSTAT[BGE]) are also set.
> + * For Continue, apply soft reset for data(SYSCTL[RSTD]);
> + * and re-issue the entire read
> + * transaction from beginning.
> + */
> +static void esdhci_of_adma_workaround(struct sdhci_host *host, u32
> intmask)
> +{
> + u32 tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
> +
> + tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
> + if (tmp == VENDOR_V_23) {
> + if ((intmask & SDHCI_INT_DATA_END) &&
> + (intmask & SDHCI_INT_BLK_GAP)) {
> + dma_addr_t dmastart;
> + dma_addr_t dmanow;
> +
> + 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;
> + sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS);
> + }
> + }
> +}
> +
> #ifdef CONFIG_PM
> static u32 esdhc_proctl;
> static void esdhc_of_suspend(struct sdhci_host *host)
> @@ -166,7 +213,7 @@ struct sdhci_of_data sdhci_esdhc = {
> .read_l = esdhc_readl,
> .read_w = esdhc_readw,
> .read_b = esdhc_readb,
> - .write_l = sdhci_be32bs_writel,
> + .write_l = esdhc_writel,
> .write_w = esdhc_writew,
> .write_b = esdhc_writeb,
> .set_clock = esdhc_set_clock,
> @@ -177,5 +224,6 @@ struct sdhci_of_data sdhci_esdhc = {
> .platform_suspend = esdhc_of_suspend,
> .platform_resume = esdhc_of_resume,
> #endif
> + .adma_workaround = esdhci_of_adma_workaround,
> },
> };
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 684f1a4..3d9365a 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -2143,6 +2143,8 @@ static void sdhci_data_irq(struct sdhci_host *host,
> u32 intmask)
> printk(KERN_ERR "%s: ADMA error\n", mmc_hostname(host->mmc));
> sdhci_show_adma_error(host);
> host->data->error = -EIO;
> + if (host->ops->adma_workaround)
> + host->ops->adma_workaround(host, intmask);
> }
>
> if (host->data->error)
> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> index 209f707..138d8fc 100644
> --- a/drivers/mmc/host/sdhci.h
> +++ b/drivers/mmc/host/sdhci.h
> @@ -120,6 +120,7 @@
> #define SDHCI_SIGNAL_ENABLE 0x38
> #define SDHCI_INT_RESPONSE 0x00000001
> #define SDHCI_INT_DATA_END 0x00000002
> +#define SDHCI_INT_BLK_GAP 0x00000004
> #define SDHCI_INT_DMA_END 0x00000008
> #define SDHCI_INT_SPACE_AVAIL 0x00000010
> #define SDHCI_INT_DATA_AVAIL 0x00000020
> @@ -146,7 +147,8 @@
> #define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \
> SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \
> SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \
> - SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR)
> + SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR | \
> + SDHCI_INT_BLK_GAP)
> #define SDHCI_INT_ALL_MASK ((unsigned int)-1)
>
> #define SDHCI_ACMD12_ERR 0x3C
> @@ -275,6 +277,7 @@ struct sdhci_ops {
> int (*set_uhs_signaling)(struct sdhci_host *host, unsigned int
> uhs);
> void (*platform_suspend)(struct sdhci_host *host);
> void (*platform_resume)(struct sdhci_host *host);
> + void (*adma_workaround)(struct sdhci_host *host, u32 intmask);
>
> };
>
> --
> 1.7.0.4
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2012-11-29 5:49 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-09-20 2:19 [PATCH V4] Powerpc eSDHC Recover from the ADMA error Haijun.Zhang
2012-09-20 2:57 ` Anton Vorontsov
2012-10-23 5:49 ` Huang Changming-R66093
2012-11-05 9:10 ` Huang Changming-R66093
2012-11-13 7:51 ` Huang Changming-R66093
2012-11-17 20:56 ` Chris Ball
2012-11-29 5:49 ` Zhang Haijun-B42677
-- strict thread matches above, loose matches on Subject: below --
2012-11-29 5:22 Haijun Zhang
2012-08-31 7:36 Haijun.Zhang
2012-09-07 6:12 ` Huang Changming-R66093
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).