Re: [PATCH] spi/omap2_mcspi: Verify TX reg is empty after TX only xfer with DMA

2010-10-20 Thread Grant Likely
On Wed, Oct 20, 2010 at 09:23:57AM -0700, Tony Lindgren wrote:
> * Ilkka Koskinen  [101019 06:55]:
> > In case of TX only with DMA, the driver assumes that the data
> > has been transferred once DMA callback in invoked. However,
> > SPI's shift register may still contain data. Thus, the driver
> > is supposed to verify that the register is empty and the end of
> > the SPI transfer has been reached.
> > 
> > Signed-off-by: Ilkka Koskinen 
> > Tested-by: Tuomas Katila 
> 
> Grant, can you please queue this one?
> 
> Acked-by: Tony Lindgren 

Applied, thanks.

g.

> 
> 
> > ---
> >  drivers/spi/omap2_mcspi.c |   39 ++-
> >  1 files changed, 26 insertions(+), 13 deletions(-)
> > 
> > diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
> > index b3a94ca..a2e053c 100644
> > --- a/drivers/spi/omap2_mcspi.c
> > +++ b/drivers/spi/omap2_mcspi.c
> > @@ -296,6 +296,19 @@ static int omap2_mcspi_enable_clocks(struct 
> > omap2_mcspi *mcspi)
> > return 0;
> >  }
> >  
> > +static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
> > +{
> > +   unsigned long timeout;
> > +
> > +   timeout = jiffies + msecs_to_jiffies(1000);
> > +   while (!(__raw_readl(reg) & bit)) {
> > +   if (time_after(jiffies, timeout))
> > +   return -1;
> > +   cpu_relax();
> > +   }
> > +   return 0;
> > +}
> > +
> >  static unsigned
> >  omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
> >  {
> > @@ -309,11 +322,14 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct 
> > spi_transfer *xfer)
> > u32 l;
> > u8  * rx;
> > const u8* tx;
> > +   void __iomem*chstat_reg;
> >  
> > mcspi = spi_master_get_devdata(spi->master);
> > mcspi_dma = &mcspi->dma_channels[spi->chip_select];
> > l = mcspi_cached_chconf0(spi);
> >  
> > +   chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
> > +
> > count = xfer->len;
> > c = count;
> > word_len = cs->word_len;
> > @@ -382,6 +398,16 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct 
> > spi_transfer *xfer)
> > if (tx != NULL) {
> > wait_for_completion(&mcspi_dma->dma_tx_completion);
> > dma_unmap_single(NULL, xfer->tx_dma, count, DMA_TO_DEVICE);
> > +
> > +   /* for TX_ONLY mode, be sure all words have shifted out */
> > +   if (rx == NULL) {
> > +   if (mcspi_wait_for_reg_bit(chstat_reg,
> > +   OMAP2_MCSPI_CHSTAT_TXS) < 0)
> > +   dev_err(&spi->dev, "TXS timed out\n");
> > +   else if (mcspi_wait_for_reg_bit(chstat_reg,
> > +   OMAP2_MCSPI_CHSTAT_EOT) < 0)
> > +   dev_err(&spi->dev, "EOT timed out\n");
> > +   }
> > }
> >  
> > if (rx != NULL) {
> > @@ -435,19 +461,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct 
> > spi_transfer *xfer)
> > return count;
> >  }
> >  
> > -static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
> > -{
> > -   unsigned long timeout;
> > -
> > -   timeout = jiffies + msecs_to_jiffies(1000);
> > -   while (!(__raw_readl(reg) & bit)) {
> > -   if (time_after(jiffies, timeout))
> > -   return -1;
> > -   cpu_relax();
> > -   }
> > -   return 0;
> > -}
> > -
> >  static unsigned
> >  omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
> >  {
> > -- 
> > 1.6.0.4
> > 
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] spi/omap2_mcspi: Verify TX reg is empty after TX only xfer with DMA

2010-10-20 Thread Tony Lindgren
* Ilkka Koskinen  [101019 06:55]:
> In case of TX only with DMA, the driver assumes that the data
> has been transferred once DMA callback in invoked. However,
> SPI's shift register may still contain data. Thus, the driver
> is supposed to verify that the register is empty and the end of
> the SPI transfer has been reached.
> 
> Signed-off-by: Ilkka Koskinen 
> Tested-by: Tuomas Katila 

Grant, can you please queue this one?

Acked-by: Tony Lindgren 


> ---
>  drivers/spi/omap2_mcspi.c |   39 ++-
>  1 files changed, 26 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
> index b3a94ca..a2e053c 100644
> --- a/drivers/spi/omap2_mcspi.c
> +++ b/drivers/spi/omap2_mcspi.c
> @@ -296,6 +296,19 @@ static int omap2_mcspi_enable_clocks(struct omap2_mcspi 
> *mcspi)
>   return 0;
>  }
>  
> +static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
> +{
> + unsigned long timeout;
> +
> + timeout = jiffies + msecs_to_jiffies(1000);
> + while (!(__raw_readl(reg) & bit)) {
> + if (time_after(jiffies, timeout))
> + return -1;
> + cpu_relax();
> + }
> + return 0;
> +}
> +
>  static unsigned
>  omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
>  {
> @@ -309,11 +322,14 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct 
> spi_transfer *xfer)
>   u32 l;
>   u8  * rx;
>   const u8* tx;
> + void __iomem*chstat_reg;
>  
>   mcspi = spi_master_get_devdata(spi->master);
>   mcspi_dma = &mcspi->dma_channels[spi->chip_select];
>   l = mcspi_cached_chconf0(spi);
>  
> + chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
> +
>   count = xfer->len;
>   c = count;
>   word_len = cs->word_len;
> @@ -382,6 +398,16 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct 
> spi_transfer *xfer)
>   if (tx != NULL) {
>   wait_for_completion(&mcspi_dma->dma_tx_completion);
>   dma_unmap_single(NULL, xfer->tx_dma, count, DMA_TO_DEVICE);
> +
> + /* for TX_ONLY mode, be sure all words have shifted out */
> + if (rx == NULL) {
> + if (mcspi_wait_for_reg_bit(chstat_reg,
> + OMAP2_MCSPI_CHSTAT_TXS) < 0)
> + dev_err(&spi->dev, "TXS timed out\n");
> + else if (mcspi_wait_for_reg_bit(chstat_reg,
> + OMAP2_MCSPI_CHSTAT_EOT) < 0)
> + dev_err(&spi->dev, "EOT timed out\n");
> + }
>   }
>  
>   if (rx != NULL) {
> @@ -435,19 +461,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct 
> spi_transfer *xfer)
>   return count;
>  }
>  
> -static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
> -{
> - unsigned long timeout;
> -
> - timeout = jiffies + msecs_to_jiffies(1000);
> - while (!(__raw_readl(reg) & bit)) {
> - if (time_after(jiffies, timeout))
> - return -1;
> - cpu_relax();
> - }
> - return 0;
> -}
> -
>  static unsigned
>  omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
>  {
> -- 
> 1.6.0.4
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] spi/omap2_mcspi: Verify TX reg is empty after TX only xfer with DMA

2010-10-19 Thread Ilkka Koskinen
In case of TX only with DMA, the driver assumes that the data
has been transferred once DMA callback in invoked. However,
SPI's shift register may still contain data. Thus, the driver
is supposed to verify that the register is empty and the end of
the SPI transfer has been reached.

Signed-off-by: Ilkka Koskinen 
Tested-by: Tuomas Katila 
---
 drivers/spi/omap2_mcspi.c |   39 ++-
 1 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
index b3a94ca..a2e053c 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/omap2_mcspi.c
@@ -296,6 +296,19 @@ static int omap2_mcspi_enable_clocks(struct omap2_mcspi 
*mcspi)
return 0;
 }
 
+static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
+{
+   unsigned long timeout;
+
+   timeout = jiffies + msecs_to_jiffies(1000);
+   while (!(__raw_readl(reg) & bit)) {
+   if (time_after(jiffies, timeout))
+   return -1;
+   cpu_relax();
+   }
+   return 0;
+}
+
 static unsigned
 omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
 {
@@ -309,11 +322,14 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct 
spi_transfer *xfer)
u32 l;
u8  * rx;
const u8* tx;
+   void __iomem*chstat_reg;
 
mcspi = spi_master_get_devdata(spi->master);
mcspi_dma = &mcspi->dma_channels[spi->chip_select];
l = mcspi_cached_chconf0(spi);
 
+   chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
+
count = xfer->len;
c = count;
word_len = cs->word_len;
@@ -382,6 +398,16 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct 
spi_transfer *xfer)
if (tx != NULL) {
wait_for_completion(&mcspi_dma->dma_tx_completion);
dma_unmap_single(NULL, xfer->tx_dma, count, DMA_TO_DEVICE);
+
+   /* for TX_ONLY mode, be sure all words have shifted out */
+   if (rx == NULL) {
+   if (mcspi_wait_for_reg_bit(chstat_reg,
+   OMAP2_MCSPI_CHSTAT_TXS) < 0)
+   dev_err(&spi->dev, "TXS timed out\n");
+   else if (mcspi_wait_for_reg_bit(chstat_reg,
+   OMAP2_MCSPI_CHSTAT_EOT) < 0)
+   dev_err(&spi->dev, "EOT timed out\n");
+   }
}
 
if (rx != NULL) {
@@ -435,19 +461,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct 
spi_transfer *xfer)
return count;
 }
 
-static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
-{
-   unsigned long timeout;
-
-   timeout = jiffies + msecs_to_jiffies(1000);
-   while (!(__raw_readl(reg) & bit)) {
-   if (time_after(jiffies, timeout))
-   return -1;
-   cpu_relax();
-   }
-   return 0;
-}
-
 static unsigned
 omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
 {
-- 
1.6.0.4

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