Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1232987 > unrolled thread

[PATCH v2 0/8] Improvements for SPI IMX driver for Freescale IMX53 and IMX6 families

Started byAnton Bondarenko <anton_bondarenko@mentor.com>
First post2015-09-25 20:00 +0200
Last post2015-10-01 02:20 +0200
Articles 5 — 2 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v2 0/8] Improvements for SPI IMX driver for Freescale IMX53 and IMX6 families Anton Bondarenko <anton_bondarenko@mentor.com> - 2015-09-25 20:00 +0200
    [PATCH v2 2/8] spi: imx: replace fixed timeout with calculated one Anton Bondarenko <anton_bondarenko@mentor.com> - 2015-09-25 20:10 +0200
      Re: [PATCH v2 2/8] spi: imx: replace fixed timeout with calculated  one "Bondarenko, Anton" <Anton_Bondarenko@mentor.com> - 2015-10-01 02:20 +0200
    [PATCH v2 5/8] spi: imx: Add support for loopback for ECSPI controllers Anton Bondarenko <anton_bondarenko@mentor.com> - 2015-09-25 20:10 +0200
      Re: [PATCH v2 5/8] spi: imx: Add support for loopback for ECSPI  controllers "Bondarenko, Anton" <Anton_Bondarenko@mentor.com> - 2015-10-01 02:20 +0200

#1232987 — [PATCH v2 0/8] Improvements for SPI IMX driver for Freescale IMX53 and IMX6 families

FromAnton Bondarenko <anton_bondarenko@mentor.com>
Date2015-09-25 20:00 +0200
Subject[PATCH v2 0/8] Improvements for SPI IMX driver for Freescale IMX53 and IMX6 families
Message-ID<qcFrQ-8B-9@gated-at.bofh.it>
A number of patches to impove or add the implementation
for the spi-imx driver related to Freescale IMX53 and IMX6.
It would also possible some of patches can be applied for other
Freescale controllers using spi-imx driver but could not be tested
due to lack of hardware.

Anton Bondarenko (8):
  spi: imx: Fix DMA transfer
  spi: imx: replace fixed timeout with calculated one
  spi: imx: add support for all SPI word width for DMA transfer
  spi: imx: add selection for iMX53 and iMX6 controller type
  spi: imx: Add support for loopback for ECSPI controllers
  spi: imx: return error from dma channel request
  spi: imx: defer spi initialization, if DMA engine is pending
  spi: imx: Add support for SPI Slave mode for imx53 and imx6 chips

 .../devicetree/bindings/spi/fsl-imx-cspi.txt       |   3 +
 drivers/spi/spi-imx.c                              | 486 ++++++++++++++++-----
 2 files changed, 388 insertions(+), 101 deletions(-)

-- 
2.5.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1232990 — [PATCH v2 2/8] spi: imx: replace fixed timeout with calculated one

FromAnton Bondarenko <anton_bondarenko@mentor.com>
Date2015-09-25 20:10 +0200
Subject[PATCH v2 2/8] spi: imx: replace fixed timeout with calculated one
Message-ID<qcFBv-zc-3@gated-at.bofh.it>
In reply to#1232987
Fixed timeout value can fire while transaction is ongoing. This may happen
because there are no strict requirements on SPI transaction duration.
Dynamic timeout value is generated based on SCLK and transaction size.

There is also 4 * SCLK delay between TX bursts related to CS change.

Signed-off-by: Anton Bondarenko <anton_bondarenko@mentor.com>
---
 drivers/spi/spi-imx.c | 49 +++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 41 insertions(+), 8 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 165bc2c..6c98eda 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -59,7 +59,6 @@
 
 /* The maximum  bytes that a sdma BD can transfer.*/
 #define MAX_SDMA_BD_BYTES  (1 << 15)
-#define IMX_DMA_TIMEOUT (msecs_to_jiffies(3000))
 struct spi_imx_config {
 	unsigned int speed_hz;
 	unsigned int bpw;
@@ -95,6 +94,7 @@ struct spi_imx_data {
 	struct clk *clk_per;
 	struct clk *clk_ipg;
 	unsigned long spi_clk;
+	unsigned int spi_bus_clk;
 
 	unsigned int count;
 	void (*tx)(struct spi_imx_data *);
@@ -317,8 +317,7 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
 {
 	u32 ctrl = MX51_ECSPI_CTRL_ENABLE, dma = 0;
 	u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
-
-	u32 clk = config->speed_hz, delay;
+	u32 delay;
 
 	/*
 	 * The hardware seems to have a race condition when changing modes. The
@@ -330,7 +329,9 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
 	ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
 
 	/* set clock speed */
-	ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz, &clk);
+	spi_imx->spi_bus_clk = config->speed_hz;
+	ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz,
+				  &spi_imx->spi_bus_clk);
 
 	/* set chip select to use */
 	ctrl |= MX51_ECSPI_CTRL_CS(config->cs);
@@ -363,7 +364,7 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
 	 * the SPI communication as the device on the other end would consider
 	 * the change of SCLK polarity as a clock tick already.
 	 */
-	delay = (2 * 1000000) / clk;
+	delay = (2 * USEC_PER_SEC) / spi_imx->spi_bus_clk;
 	if (likely(delay < 10))	/* SCLK is faster than 100 kHz */
 		udelay(delay);
 	else			/* SCLK is _very_ slow */
@@ -889,12 +890,40 @@ static void spi_imx_dma_tx_callback(void *cookie)
 	complete(&spi_imx->dma_tx_completion);
 }
 
+static int spi_imx_calculate_timeout(struct spi_imx_data *spi_imx, int size)
+{
+	unsigned long coef1 = 1;
+	unsigned long coef2 = MSEC_PER_SEC;
+	unsigned long timeout = 0;
+
+	/* Swap coeficients to avoid div by 0 */
+	if (spi_imx->spi_bus_clk < MSEC_PER_SEC) {
+		coef1 = MSEC_PER_SEC;
+		coef2 = 1;
+	}
+
+	/* Time with actual data transfer */
+	timeout += DIV_ROUND_UP(8 * size * coef1,
+				spi_imx->spi_bus_clk / coef2);
+
+	/* Take CS change delay related to HW */
+	timeout += DIV_ROUND_UP((size - 1) * 4 * coef1,
+				spi_imx->spi_bus_clk / coef2);
+
+	/* Add extra second for scheduler related activities */
+	timeout += MSEC_PER_SEC;
+
+	/* Double calculated timeout */
+	return msecs_to_jiffies(2 * timeout);
+}
+
 static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 				struct spi_transfer *transfer)
 {
 	struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL;
 	int ret;
 	unsigned long timeout;
+	unsigned long transfer_timeout;
 	const int left = transfer->len % spi_imx->wml;
 	struct spi_master *master = spi_imx->bitbang.master;
 	struct sg_table *tx = &transfer->tx_sg, *rx = &transfer->rx_sg;
@@ -947,9 +976,11 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 	dma_async_issue_pending(master->dma_tx);
 	spi_imx->devtype_data->trigger(spi_imx);
 
+	transfer_timeout = spi_imx_calculate_timeout(spi_imx, transfer->len);
+
 	/* Wait SDMA to finish the data transfer.*/
 	timeout = wait_for_completion_timeout(&spi_imx->dma_tx_completion,
-						IMX_DMA_TIMEOUT);
+						transfer_timeout);
 	if (!timeout) {
 		pr_warn("%s %s: I/O Error in DMA TX\n",
 			dev_driver_string(&master->dev),
@@ -957,8 +988,10 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 		dmaengine_terminate_all(master->dma_tx);
 		dmaengine_terminate_all(master->dma_rx);
 	} else {
+		transfer_timeout = spi_imx_calculate_timeout(spi_imx,
+							     spi_imx->wml * 2);
 		timeout = wait_for_completion_timeout(
-				&spi_imx->dma_rx_completion, IMX_DMA_TIMEOUT);
+				&spi_imx->dma_rx_completion, transfer_timeout);
 		if (!timeout) {
 			pr_warn("%s %s: I/O Error in DMA RX\n",
 				dev_driver_string(&master->dev),
@@ -980,7 +1013,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 			spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TCEN);
 
 			timeout = wait_for_completion_timeout(
-					&spi_imx->xfer_done, IMX_DMA_TIMEOUT);
+					&spi_imx->xfer_done, transfer_timeout);
 			if (!timeout) {
 				pr_warn("%s %s: I/O Error in RX tail\n",
 					dev_driver_string(&master->dev),
-- 
2.5.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1236869 — Re: [PATCH v2 2/8] spi: imx: replace fixed timeout with calculated one

From"Bondarenko, Anton" <Anton_Bondarenko@mentor.com>
Date2015-10-01 02:20 +0200
SubjectRe: [PATCH v2 2/8] spi: imx: replace fixed timeout with calculated one
Message-ID<qezLk-44g-15@gated-at.bofh.it>
In reply to#1232990
On 30.09.2015 10:31, Robin Gong wrote:
> On Fri, Sep 25, 2015 at 07:57:09PM +0200, Anton Bondarenko wrote:
>> @@ -957,8 +988,10 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
>>  		dmaengine_terminate_all(master->dma_tx);
>>  		dmaengine_terminate_all(master->dma_rx);
>>  	} else {
>> +		transfer_timeout = spi_imx_calculate_timeout(spi_imx,
>> +							     spi_imx->wml * 2);
> *2 again here? Although spi_imx_calculate_timeout has double it.
WIll be fixed in V3
>>  		timeout = wait_for_completion_timeout(
>> -				&spi_imx->dma_rx_completion, IMX_DMA_TIMEOUT);
>> +				&spi_imx->dma_rx_completion, transfer_timeout);
>>  		if (!timeout) {
>>  			pr_warn("%s %s: I/O Error in DMA RX\n",
>>  				dev_driver_string(&master->dev),
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1232995 — [PATCH v2 5/8] spi: imx: Add support for loopback for ECSPI controllers

FromAnton Bondarenko <anton_bondarenko@mentor.com>
Date2015-09-25 20:10 +0200
Subject[PATCH v2 5/8] spi: imx: Add support for loopback for ECSPI controllers
Message-ID<qcFBw-zc-13@gated-at.bofh.it>
In reply to#1232987
Support for ECSPI loopback for IMX51,IMX53 and IMX6Q using TEST register.

Signed-off-by: Mohsin Kazmi <mohsin_kazmi@mentor.com>
Signed-off-by: Anton Bondarenko <anton_bondarenko@mentor.com>
---
 drivers/spi/spi-imx.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 41c9cef..4b3c16e 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -265,6 +265,9 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
 #define MX51_ECSPI_STAT		0x18
 #define MX51_ECSPI_STAT_RR		(1 <<  3)
 
+#define MX51_ECSPI_TEST			0x20
+#define MX51_ECSPI_LOOP			BIT(31)
+
 /* MX51 eCSPI */
 static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi,
 				      unsigned int *fres)
@@ -338,6 +341,7 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
 	u32 ctrl = MX51_ECSPI_CTRL_ENABLE, dma = 0;
 	u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
 	u32 delay;
+	u32 lpb = 0;
 
 	/*
 	 * The hardware seems to have a race condition when changing modes. The
@@ -370,8 +374,12 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
 	if (config->mode & SPI_CS_HIGH)
 		cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs);
 
+	if (config->mode & SPI_LOOP)
+		lpb |= MX51_ECSPI_LOOP;
+
 	writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
 	writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
+	writel(lpb, spi_imx->base + MX51_ECSPI_TEST);
 
 	/*
 	 * Wait until the changes in the configuration register CONFIGREG
@@ -1252,6 +1260,9 @@ static int spi_imx_probe(struct platform_device *pdev)
 	spi_imx = spi_master_get_devdata(master);
 	spi_imx->bitbang.master = master;
 
+	spi_imx->devtype_data = of_id ? of_id->data :
+		(struct spi_imx_devtype_data *)pdev->id_entry->driver_data;
+
 	for (i = 0; i < master->num_chipselect; i++) {
 		int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
 		if (!gpio_is_valid(cs_gpio) && mxc_platform_info)
@@ -1276,12 +1287,13 @@ static int spi_imx_probe(struct platform_device *pdev)
 	spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
 	spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message;
 	spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
-	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA |
+				SPI_CS_HIGH;
 
-	init_completion(&spi_imx->xfer_done);
+	if (is_imx5x_ecspi(spi_imx))
+		spi_imx->bitbang.master->mode_bits |= SPI_LOOP;
 
-	spi_imx->devtype_data = of_id ? of_id->data :
-		(struct spi_imx_devtype_data *) pdev->id_entry->driver_data;
+	init_completion(&spi_imx->xfer_done);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	spi_imx->base = devm_ioremap_resource(&pdev->dev, res);
-- 
2.5.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1236871 — Re: [PATCH v2 5/8] spi: imx: Add support for loopback for ECSPI controllers

From"Bondarenko, Anton" <Anton_Bondarenko@mentor.com>
Date2015-10-01 02:20 +0200
SubjectRe: [PATCH v2 5/8] spi: imx: Add support for loopback for ECSPI controllers
Message-ID<qezLk-44g-23@gated-at.bofh.it>
In reply to#1232995
On 30.09.2015 10:42, Robin Gong wrote:
> On Fri, Sep 25, 2015 at 07:57:12PM +0200, Anton Bondarenko wrote:
>> @@ -370,8 +374,12 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
>>  	if (config->mode & SPI_CS_HIGH)
>>  		cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs);
>>  
>> +	if (config->mode & SPI_LOOP)
>> +		lpb |= MX51_ECSPI_LOOP;
>> +
>>  	writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
>>  	writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
>> +	writel(lpb, spi_imx->base + MX51_ECSPI_TEST);
> It's better write this MX51_ECSPI_TEST only in LOOP mode.
LOOP mode can be set dynamically. This mean we should be able to set and clear the flag.
Currently only LOOP flag is used. I did not find any problems with writing 0 in the rest
fields of TEST register.
>>  
>>  	/*
>>  	 * Wait until the changes in the configuration register CONFIGREG
>> @@ -1276,12 +1287,13 @@ static int spi_imx_probe(struct platform_device *pdev)
>>  	spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
>>  	spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message;
>>  	spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
>> -	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
>> +	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA |
>> +				SPI_CS_HIGH;
> Any change?
Will be fixed in V3
>>  
>> -	init_completion(&spi_imx->xfer_done);
>> +	if (is_imx5x_ecspi(spi_imx))
>> +		spi_imx->bitbang.master->mode_bits |= SPI_LOOP;
>>  
>> -	spi_imx->devtype_data = of_id ? of_id->data :
>> -		(struct spi_imx_devtype_data *) pdev->id_entry->driver_data;
>> +	init_completion(&spi_imx->xfer_done);
>>  
>>  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>  	spi_imx->base = devm_ioremap_resource(&pdev->dev, res);
>> -- 
>> 2.5.2
>>

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web