Message ID | 20190305025811.38328-4-yinbo.zhu@nxp.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v3,1/5] mmc: sdhci-of-esdhc: add erratum eSDHC5 support | expand |
On 5/03/19 4:59 AM, Yinbo Zhu wrote: > From: Yinbo Zhu <yinbo.zhu@nxp.com> > > Invalid Transfer Complete (IRQSTAT[TC]) bit could be set during > multi-write operation even when the BLK_CNT in BLKATTR register > has not reached zero. Therefore, Transfer Complete might be > reported twice due to this erratum since a valid Transfer Complete > occurs when BLK_CNT reaches zero. This erratum is to fix this issue > > Signed-off-by: Yinbo Zhu <yinbo.zhu@nxp.com> One minor comment, nevertheless: Acked-by: Adrian Hunter <adrian.hunter@intel.com> > --- > Change in v3: > Define a host->ops->irq callback to clear the SDHCI_INT_DATA_END bit > > drivers/mmc/host/sdhci-of-esdhc.c | 19 +++++++++++++++++++ > 1 files changed, 19 insertions(+), 0 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c > index 7e0eae8..ef36f46 100644 > --- a/drivers/mmc/host/sdhci-of-esdhc.c > +++ b/drivers/mmc/host/sdhci-of-esdhc.c > @@ -24,6 +24,7 @@ > #include <linux/ktime.h> > #include <linux/dma-mapping.h> > #include <linux/mmc/host.h> > +#include <linux/mmc/mmc.h> > #include "sdhci-pltfm.h" > #include "sdhci-esdhc.h" > > @@ -867,6 +868,22 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, > sdhci_set_uhs_signaling(host, timing); > } > > +static u32 esdhc_irq(struct sdhci_host *host, u32 intmask) > +{ > + u32 command; > + > + if (of_find_compatible_node(NULL, NULL, > + "fsl,p2020-esdhc")) { > + command = SDHCI_GET_CMD(sdhci_readw(host, > + SDHCI_COMMAND)); > + if (command == MMC_WRITE_MULTIPLE_BLOCK && > + sdhci_readw(host, SDHCI_BLOCK_COUNT) > + != 0) > + intmask &= ~SDHCI_INT_DATA_END; Are you sure you don't need to write SDHCI_INT_DATA_END to SDHCI_INT_STATUS to clear it? > + } > + return intmask; > +} > + > #ifdef CONFIG_PM_SLEEP > static u32 esdhc_proctl; > static int esdhc_of_suspend(struct device *dev) > @@ -914,6 +931,7 @@ static SIMPLE_DEV_PM_OPS(esdhc_of_dev_pm_ops, > .set_bus_width = esdhc_pltfm_set_bus_width, > .reset = esdhc_reset, > .set_uhs_signaling = esdhc_set_uhs_signaling, > + .irq = esdhc_irq, > }; > > static const struct sdhci_ops sdhci_esdhc_le_ops = { > @@ -931,6 +949,7 @@ static SIMPLE_DEV_PM_OPS(esdhc_of_dev_pm_ops, > .set_bus_width = esdhc_pltfm_set_bus_width, > .reset = esdhc_reset, > .set_uhs_signaling = esdhc_set_uhs_signaling, > + .irq = esdhc_irq, > }; > > static const struct sdhci_pltfm_data sdhci_esdhc_be_pdata = { >
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 7e0eae8..ef36f46 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -24,6 +24,7 @@ #include <linux/ktime.h> #include <linux/dma-mapping.h> #include <linux/mmc/host.h> +#include <linux/mmc/mmc.h> #include "sdhci-pltfm.h" #include "sdhci-esdhc.h" @@ -867,6 +868,22 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, sdhci_set_uhs_signaling(host, timing); } +static u32 esdhc_irq(struct sdhci_host *host, u32 intmask) +{ + u32 command; + + if (of_find_compatible_node(NULL, NULL, + "fsl,p2020-esdhc")) { + command = SDHCI_GET_CMD(sdhci_readw(host, + SDHCI_COMMAND)); + if (command == MMC_WRITE_MULTIPLE_BLOCK && + sdhci_readw(host, SDHCI_BLOCK_COUNT) + != 0) + intmask &= ~SDHCI_INT_DATA_END; + } + return intmask; +} + #ifdef CONFIG_PM_SLEEP static u32 esdhc_proctl; static int esdhc_of_suspend(struct device *dev) @@ -914,6 +931,7 @@ static SIMPLE_DEV_PM_OPS(esdhc_of_dev_pm_ops, .set_bus_width = esdhc_pltfm_set_bus_width, .reset = esdhc_reset, .set_uhs_signaling = esdhc_set_uhs_signaling, + .irq = esdhc_irq, }; static const struct sdhci_ops sdhci_esdhc_le_ops = { @@ -931,6 +949,7 @@ static SIMPLE_DEV_PM_OPS(esdhc_of_dev_pm_ops, .set_bus_width = esdhc_pltfm_set_bus_width, .reset = esdhc_reset, .set_uhs_signaling = esdhc_set_uhs_signaling, + .irq = esdhc_irq, }; static const struct sdhci_pltfm_data sdhci_esdhc_be_pdata = {