RE: TI AM33x/AM43x SPI DRIVER

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Franklin,

> So the only time your missing the last byte is when a timeout occurs?

Yes, the bit OMAP2_MCSPI_CHSTAT_RXS was not always set.
So the received telegram was not completed --> without last byte.
This was the case with very low baudrate (1465 bit/s).
I hadn't any problem with other SPI device ( with 1,7 Mbit/s).

Regards,
Walter

-----Original Message-----
From: Franklin S Cooper Jr [mailto:fcooper@xxxxxx] 
Sent: Freitag, 10. Februar 2017 21:39
To: Tony Lindgren <tony@xxxxxxxxxxx>; Walter Wagner <walter.wagner@xxxxxxxxxx>
Cc: linux-omap@xxxxxxxxxxxxxxx; Peter Ujfalusi <peter.ujfalusi@xxxxxx>; Michael Welling <mwelling@xxxxxxxx>
Subject: Re: TI AM33x/AM43x SPI DRIVER

Hi Walter

On 02/09/2017 04:59 PM, Tony Lindgren wrote:
> Hi,
> 
> * Walter Wagner <walter.wagner@xxxxxxxxxx> [170209 00:40]:
>> Dear Tony Lindgren,
>>
>> I hope I'm right here and You are responsible for drivers/spi/spi-omap2-mcspi.c too.
> 
> Well I don't know much about the spi-omap2-mcspi.c driver.. But as 
> Franklin, Peter and Micheal have been patching it, they might have a 
> better idea what's going on. I've added them to Cc.
> 
>> To the history:
>>
>> We use TI AM33xx/AM43xx SOCs, especially SPI interface under kernel 4.1.20.
>> Testing a device with very low baudrate (1,5 KHz) I made following experience:
>>
>> 1.       The last byte was not always sure received --> sometimes I got timeout

So the only time your missing the last byte is when a timeout occurs?
>>
>> 2.       The telegrams we have contain < 160 bytes, but we need DMA mode and not PIO (because CPU load)
>>
>> Therefore I've changed the driver.
>> I hope these changes help other developer.
>>
>> I've attached the patch and the files itself for simple comparing.
> 
> Please check Documentation/SubmittingPatches and CodingStyle etc, also 
> note that with git you can easily generate patches :)
> 
> I've attached your diff below for easier reading.
> 
> Regards,
> 
> Tony
> 
> 8< --------------------
> --- a/drivers/spi/spi-omap2-mcspi.c	2016-03-17 19:11:03.000000000 +0100
> +++ b/drivers/spi/spi-omap2-mcspi.c	2017-02-06 10:35:02.518061500 +0100
> @@ -116,6 +116,11 @@
>   */
>  #define DMA_MIN_BYTES			160
>  
> +/* Default value of delay at waiting for a bit in a register.
> + * Needed to avoid latency at waiting.
> + */
> +#define BUSY_WAIT_DELAY			1	/* in ms */
> +
>  
>  /*
>   * Used for context save and restore, structure members to be updated 
> whenever @@ -138,6 +143,8 @@
>  	struct omap2_mcspi_regs ctx;
>  	int			fifo_depth;
>  	unsigned int		pin_dir:1;
> +	unsigned long		dma_min_bytes;
> +	unsigned long		busy_wait_delay;

Can't you calculate a value for this based on the SPI transaction speed instead of making this user select able?
>  };
>  
>  struct omap2_mcspi_cs {
> @@ -363,6 +370,23 @@
>  	return 0;
>  }
>  
> +static int mcspi_wait_for_reg_bit_interruptible(void __iomem *reg, 
> +unsigned long bit, unsigned long delay) {
> +	unsigned long timeout;
> +
> +	timeout = jiffies + msecs_to_jiffies(1000);
> +	while (!(readl_relaxed(reg) & bit)) {
> +		if (time_after(jiffies, timeout)) {
> +			if (!(readl_relaxed(reg) & bit))
> +				return -ETIMEDOUT;
> +			else
> +				return 0;
> +		}
> +		msleep_interruptible(delay);
> +	}
> +	return 0;
> +}
> +
>  static void omap2_mcspi_rx_callback(void *data)  {
>  	struct spi_device *spi = data;
> @@ -496,8 +520,9 @@
>  	if (l & OMAP2_MCSPI_CHCONF_TURBO) {
>  		elements--;
>  
> -		if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0)
> -				   & OMAP2_MCSPI_CHSTAT_RXS)) {
> +		if (mcspi_wait_for_reg_bit_interruptible(cs->base + OMAP2_MCSPI_CHSTAT0,
> +				OMAP2_MCSPI_CHSTAT_RXS, mcspi->busy_wait_delay) == 0) {
> +			/* reading completed */
>  			u32 w;
>  
>  			w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0); @@ -508,6 +533,7 @@
>  			else /* word_len <= 32 */
>  				((u32 *)xfer->rx_buf)[elements++] = w;
>  		} else {
> +			/* timeout */
>  			int bytes_per_word = mcspi_bytes_per_word(word_len);
>  			dev_err(&spi->dev, "DMA RX penultimate word empty\n");
>  			count -= (bytes_per_word << 1);
> @@ -515,8 +541,9 @@
>  			return count;
>  		}
>  	}
> -	if (likely(q(spi, OMAP2_MCSPI_CHSTAT0)
> -				& OMAP2_MCSPI_CHSTAT_RXS)) {
> +	if (mcspi_wait_for_reg_bit_interruptible(cs->base + OMAP2_MCSPI_CHSTAT0,
> +			OMAP2_MCSPI_CHSTAT_RXS, mcspi->busy_wait_delay) == 0) {
> +		/* reading completed */
>  		u32 w;
>  
>  		w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0); @@ -527,6 +554,7 @@
>  		else /* word_len <= 32 */
>  			((u32 *)xfer->rx_buf)[elements] = w;
>  	} else {
> +		/* timeout */
>  		dev_err(&spi->dev, "DMA RX last word empty\n");
>  		count -= mcspi_bytes_per_word(word_len);
>  	}
> @@ -1141,7 +1169,7 @@
>  			unsigned	count;
>  
>  			if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
> -			    (m->is_dma_mapped || t->len >= DMA_MIN_BYTES))
> +			    (m->is_dma_mapped || t->len >= mcspi->dma_min_bytes))
>  				omap2_mcspi_set_fifo(spi, t, 1);
>  
>  			omap2_mcspi_set_enable(spi, 1);
> @@ -1152,7 +1180,7 @@
>  						+ OMAP2_MCSPI_TX0);
>  
>  			if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
> -			    (m->is_dma_mapped || t->len >= DMA_MIN_BYTES))
> +			    (m->is_dma_mapped || t->len >= mcspi->dma_min_bytes))
>  				count = omap2_mcspi_txrx_dma(spi, t);
>  			else
>  				count = omap2_mcspi_txrx_pio(spi, t); @@ -1234,7 +1262,7 @@
>  			goto out;
>  		}
>  
> -		if (m->is_dma_mapped || len < DMA_MIN_BYTES)
> +		if (m->is_dma_mapped || len < mcspi->dma_min_bytes)
>  			continue;
>  
>  		if (mcspi_dma->dma_tx && tx_buf != NULL) { @@ -1375,6 +1403,11 @@
>  			master->bus_num = pdev->id;
>  		mcspi->pin_dir = pdata->pin_dir;
>  	}
> +	mcspi->dma_min_bytes = DMA_MIN_BYTES; /* default value */
> +	of_property_read_u32(node, "ti,dma-min-bytes", &mcspi->dma_min_bytes);
> +	mcspi->busy_wait_delay = BUSY_WAIT_DELAY; /* default value */
> +	of_property_read_u32(node, "ti,busy-wait-delay", 
> +&mcspi->busy_wait_delay);
> +
>  	regs_offset = pdata->regs_offset;
>  
>  	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux