[PATCH] staging: octeon-usb: use correct function for hcd cleanup

2017-05-08 Thread Anton Bondarenko
Use usb_put_hdc to release hdc allocated by usb_create_hcd.
This is needed to handle sub-allocations and HCD sharing correctly.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/staging/octeon-usb/octeon-hcd.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/octeon-usb/octeon-hcd.c 
b/drivers/staging/octeon-usb/octeon-hcd.c
index 9a7858a300fd..068aece25d37 100644
--- a/drivers/staging/octeon-usb/octeon-hcd.c
+++ b/drivers/staging/octeon-usb/octeon-hcd.c
@@ -3659,14 +3659,14 @@ static int octeon_usb_probe(struct platform_device 
*pdev)
status = cvmx_usb_initialize(dev, usb);
if (status) {
dev_dbg(dev, "USB initialization failed with %d\n", status);
-   kfree(hcd);
+   usb_put_hcd(hcd);
return -1;
}
 
status = usb_add_hcd(hcd, irq, 0);
if (status) {
dev_dbg(dev, "USB add HCD failed with %d\n", status);
-   kfree(hcd);
+   usb_put_hcd(hcd);
return -1;
}
device_wakeup_enable(hcd->self.controller);
@@ -3691,7 +3691,7 @@ static int octeon_usb_remove(struct platform_device *pdev)
if (status)
dev_dbg(dev, "USB shutdown failed with %d\n", status);
 
-   kfree(hcd);
+   usb_put_hcd(hcd);
 
return 0;
 }
-- 
2.11.0



[PATCH] staging: octeon-usb: use correct function for hcd cleanup

2017-05-08 Thread Anton Bondarenko
Use usb_put_hdc to release hdc allocated by usb_create_hcd.
This is needed to handle sub-allocations and HCD sharing correctly.

Signed-off-by: Anton Bondarenko 
---
 drivers/staging/octeon-usb/octeon-hcd.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/octeon-usb/octeon-hcd.c 
b/drivers/staging/octeon-usb/octeon-hcd.c
index 9a7858a300fd..068aece25d37 100644
--- a/drivers/staging/octeon-usb/octeon-hcd.c
+++ b/drivers/staging/octeon-usb/octeon-hcd.c
@@ -3659,14 +3659,14 @@ static int octeon_usb_probe(struct platform_device 
*pdev)
status = cvmx_usb_initialize(dev, usb);
if (status) {
dev_dbg(dev, "USB initialization failed with %d\n", status);
-   kfree(hcd);
+   usb_put_hcd(hcd);
return -1;
}
 
status = usb_add_hcd(hcd, irq, 0);
if (status) {
dev_dbg(dev, "USB add HCD failed with %d\n", status);
-   kfree(hcd);
+   usb_put_hcd(hcd);
return -1;
}
device_wakeup_enable(hcd->self.controller);
@@ -3691,7 +3691,7 @@ static int octeon_usb_remove(struct platform_device *pdev)
if (status)
dev_dbg(dev, "USB shutdown failed with %d\n", status);
 
-   kfree(hcd);
+   usb_put_hcd(hcd);
 
return 0;
 }
-- 
2.11.0



[PATCH v6 3/8] spi: imx: return error from dma channel request

2015-12-07 Thread Anton Bondarenko
On SDMA initialization return exactly the same error, which is
reported by dma_request_slave_channel_reason(), it is a preceding
change to defer SPI DMA initialization, if SDMA module is not yet
available.

Signed-off-by: Vladimir Zapolskiy 
Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 27 ---
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 17a90dc..c123060 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -848,10 +848,11 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2;
 
/* Prepare for TX DMA: */
-   master->dma_tx = dma_request_slave_channel(dev, "tx");
-   if (!master->dma_tx) {
-   dev_err(dev, "cannot get the TX DMA channel!\n");
-   ret = -EINVAL;
+   master->dma_tx = dma_request_slave_channel_reason(dev, "tx");
+   if (IS_ERR(master->dma_tx)) {
+   ret = PTR_ERR(master->dma_tx);
+   dev_dbg(dev, "can't get the TX DMA channel, error %d!\n", ret);
+   master->dma_tx = NULL;
goto err;
}
 
@@ -866,10 +867,11 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
}
 
/* Prepare for RX : */
-   master->dma_rx = dma_request_slave_channel(dev, "rx");
-   if (!master->dma_rx) {
-   dev_dbg(dev, "cannot get the DMA channel.\n");
-   ret = -EINVAL;
+   master->dma_rx = dma_request_slave_channel_reason(dev, "rx");
+   if (IS_ERR(master->dma_rx)) {
+   ret = PTR_ERR(master->dma_rx);
+   dev_dbg(dev, "can't get the RX DMA channel, error %d\n", ret);
+   master->dma_rx = NULL;
goto err;
}
 
@@ -1218,9 +1220,12 @@ static int spi_imx_probe(struct platform_device *pdev)
 * Only validated on i.mx6 now, can remove the constrain if validated on
 * other chips.
 */
-   if (is_imx51_ecspi(spi_imx) &&
-   spi_imx_sdma_init(>dev, spi_imx, master, res))
-   dev_err(>dev, "dma setup error,use pio instead\n");
+   if (is_imx51_ecspi(spi_imx)) {
+   ret = spi_imx_sdma_init(>dev, spi_imx, master, res);
+   if (ret < 0)
+   dev_err(>dev, "dma setup error %d, use pio\n",
+   ret);
+   }
 
spi_imx->devtype_data->reset(spi_imx);
 
-- 
2.6.3

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


[PATCH v6 1/8] spi: imx: fix loopback mode setup after controller reset

2015-12-07 Thread Anton Bondarenko
If controller hold in reset it's not possible to write any
register except CTRL. So all other registers must be updated
only after controller bring out from reset.

Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 410522f..3aa33c8 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -356,6 +356,9 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
else
cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(config->cs);
 
+   /* CTRL register always go first to bring out controller from reset */
+   writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
+
reg = readl(spi_imx->base + MX51_ECSPI_TESTREG);
if (config->mode & SPI_LOOP)
reg |= MX51_ECSPI_TESTREG_LBC;
@@ -363,7 +366,6 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
reg &= ~MX51_ECSPI_TESTREG_LBC;
writel(reg, spi_imx->base + MX51_ECSPI_TESTREG);
 
-   writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
 
/*
-- 
2.6.3

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


[PATCH v6 4/8] spi: imx: defer spi initialization, if DMA engine is

2015-12-07 Thread Anton Bondarenko
If SPI device supports DMA mode, but DMA controller is not yet
available due to e.g. a delay in the corresponding kernel module
initialization, retry to initialize SPI driver later on instead of
falling back into PIO only mode.

Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index c123060..d98c33c 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -1222,6 +1222,9 @@ static int spi_imx_probe(struct platform_device *pdev)
 */
if (is_imx51_ecspi(spi_imx)) {
ret = spi_imx_sdma_init(>dev, spi_imx, master, res);
+   if (ret == -EPROBE_DEFER)
+   goto out_clk_put;
+
if (ret < 0)
dev_err(>dev, "dma setup error %d, use pio\n",
ret);
-- 
2.6.3

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


[PATCH v6 5/8] spi: imx: allow only WML aligned transfers to use DMA

2015-12-07 Thread Anton Bondarenko
RX DMA tail data handling doesn't work correctly in many cases with current
implementation. It happens because SPI core was setup to generates both RX
and RX TAIL events. And RX TAIL event does not work correctly.
This can be easily verified by sending SPI transaction with size modulus
WML(32 in our case) not equal 0.

Also removing change introduced in f6ee9b582d2db652497b73c1f117591dfb6d3a90
since this change only fix usecases with transfer size from 33 to 128 bytes
and doesn't fix 129 bytes and bigger.

This is output from transaction with len 138 bytes in loopback mode at 10Mhz:
TX: a3 97 a2 55 53 be f1 fc f9 79 6b 52 14 13 e9 e2
TX0010: 2d 51 8e 1f 56 08 57 27 a7 05 d4 d0 52 82 77 75
TX0020: 1b 99 4a ed 58 3d 6a 52 36 d5 24 4a 68 8e ad 95
TX0030: 5f 3c 35 b5 c4 8c dd 6c 11 32 3d e2 b4 b4 59 cf
TX0040: ce 23 3d 27 df a7 f9 96 fc 1e e0 66 2c 0e 7b 8c
TX0050: ca 30 42 8f bc 9f 7b ce d1 b8 b1 87 ec 8a d6 bb
TX0060: 2e 15 63 0e 3c dc a4 3a 7a 06 20 a7 93 1b 34 dd
TX0070: 4c f5 ec 88 96 68 d6 68 a0 09 6f 8e 93 47 c9 41
TX0080: db ac cf 97 89 f3 51 05 79 71

RX: a3 97 a2 55 53 be f1 fc f9 79 6b 52 14 13 e9 e2
RX0010: 2d 51 8e 1f 56 08 57 27 a7 05 d4 d0 52 82 77 75
RX0020: 1b 99 4a ed 58 3d 6a 52 36 d5 24 4a 68 8e ad 95
RX0030: 5f 3c 35 00 00 b5 00 00 00 c4 00 00 8c 00 00 dd
RX0040: 6c 11 32 3d e2 b4 b4 59 cf ce 23 3d 27 df a7 f9
RX0050: 96 fc 1e e0 66 2c 0e 7b 8c ca 30 42 8f 1f 1f bc
RX0060: 9f 7b ce d1 b8 b1 87 ec 8a d6 bb 2e 15 63 0e ed
RX0070: ed 3c 58 58 58 dc 3d 3d a4 6a 6a 3a 52 52 7a 36
RX0080: 06 20 a7 93 1b 34 dd 4c f5 ec

Zeros at offset 33 and 34 caused by reading empty RX FIFO which not possible
if DMA RX read was triggered by RX event. This mean DMA was triggered
by RX TAIL event.

Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index d98c33c..50e0a79 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -204,8 +204,8 @@ static bool spi_imx_can_dma(struct spi_master *master, 
struct spi_device *spi,
 {
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
 
-   if (spi_imx->dma_is_inited &&
-   transfer->len > spi_imx->wml * sizeof(u32))
+   if (spi_imx->dma_is_inited && transfer->len >= spi_imx->wml &&
+   (transfer->len % spi_imx->wml) == 0)
return true;
return false;
 }
-- 
2.6.3

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


[PATCH v6 8/8] spi: imx: add support for all SPI word width for DMA

2015-12-07 Thread Anton Bondarenko
DMA transfer for SPI was limited to up to 8 bits word size until now.
Sync in SPI burst size and DMA bus width is necessary to correctly
support 16 and 32 BPW.

Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 121 +++---
 1 file changed, 95 insertions(+), 26 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index d74d809..750001c 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -88,11 +88,15 @@ struct spi_imx_data {
 
struct completion xfer_done;
void __iomem *base;
+   unsigned long base_phys;
+
struct clk *clk_per;
struct clk *clk_ipg;
unsigned long spi_clk;
unsigned int spi_bus_clk;
 
+   unsigned int bytes_per_word;
+
unsigned int count;
void (*tx)(struct spi_imx_data *);
void (*rx)(struct spi_imx_data *);
@@ -199,13 +203,32 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
return 7;
 }
 
+static int spi_imx_get_bytes_per_word(const int bpw)
+{
+   return DIV_ROUND_UP(bpw, BITS_PER_BYTE);
+}
+
 static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
 struct spi_transfer *transfer)
 {
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+   unsigned int bpw = transfer->bits_per_word;
+
+   if (!bpw)
+   bpw = spi->bits_per_word;
 
-   if (spi_imx->dma_is_inited && transfer->len >= spi_imx->wml &&
-   (transfer->len % spi_imx->wml) == 0)
+   bpw = spi_imx_get_bytes_per_word(bpw);
+
+   /*
+* We need to use SPI word size in calculation to decide
+* if we want to go with DMA or PIO mode. Just a short example:
+* We need to transfer 24 SPI words with BPW == 32. This will take
+* 24 PIO writes to FIFO (and same for reads). But transfer->len will
+* be 24*4=96 bytes. WML is 32 SPI words. The decision will be incorrect
+* if we do not take into account SPI bits per word.
+*/
+   if (spi_imx->dma_is_inited && transfer->len >= (spi_imx->wml * bpw) &&
+   (transfer->len % (spi_imx->wml * bpw)) == 0)
return true;
return false;
 }
@@ -785,11 +808,60 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id)
return IRQ_HANDLED;
 }
 
+static int spi_imx_sdma_configure(struct spi_master *master)
+{
+   int ret;
+   enum dma_slave_buswidth dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE;
+   struct dma_slave_config slave_config = {};
+   struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+
+   switch (spi_imx->bytes_per_word) {
+   case 4:
+   dsb_default = DMA_SLAVE_BUSWIDTH_4_BYTES;
+   break;
+   case 2:
+   dsb_default = DMA_SLAVE_BUSWIDTH_2_BYTES;
+   break;
+   case 1:
+   dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE;
+   break;
+   default:
+   pr_err("Not supported word size %d\n", spi_imx->bytes_per_word);
+   ret = -EINVAL;
+   goto err;
+   }
+
+   slave_config.direction = DMA_MEM_TO_DEV;
+   slave_config.dst_addr = spi_imx->base_phys + MXC_CSPITXDATA;
+   slave_config.dst_addr_width = dsb_default;
+   slave_config.dst_maxburst = spi_imx->wml;
+   ret = dmaengine_slave_config(master->dma_tx, _config);
+   if (ret) {
+   pr_err("error in TX dma configuration.\n");
+   goto err;
+   }
+
+   memset(_config, 0, sizeof(slave_config));
+
+   slave_config.direction = DMA_DEV_TO_MEM;
+   slave_config.src_addr = spi_imx->base_phys + MXC_CSPIRXDATA;
+   slave_config.src_addr_width = dsb_default;
+   slave_config.src_maxburst = spi_imx->wml;
+   ret = dmaengine_slave_config(master->dma_rx, _config);
+   if (ret)
+   pr_err("error in RX dma configuration.\n");
+
+err:
+   return ret;
+}
+
 static int spi_imx_setupxfer(struct spi_device *spi,
 struct spi_transfer *t)
 {
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
struct spi_imx_config config;
+   unsigned int new_bytes_per_word;
+   int ret = 0;
 
config.bpw = t ? t->bits_per_word : spi->bits_per_word;
config.speed_hz  = t ? t->speed_hz : spi->max_speed_hz;
@@ -813,9 +885,19 @@ static int spi_imx_setupxfer(struct spi_device *spi,
spi_imx->tx = spi_imx_buf_tx_u32;
}
 
-   spi_imx->devtype_data->config(spi_imx, );
+   new_bytes_per_word = spi_imx_get_bytes_per_word(config.bpw);
+   if (spi_imx->dma_is_inited &&
+   spi_imx->bytes_per_word != new_bytes_per_word) {
+   spi_imx->bytes_per_word = new_byt

[PATCH v6 0/8] Improvements for SPI IMX driver for Freescale ECSPI controller, continuation

2015-12-07 Thread Anton Bondarenko
This series is to complement commits already applied to topic/imx branch

Changes since V5:
 * Fix for commit "spi: imx: Add loopback mode support"
 * Addressed some comments from Sascha Hauer for DMA initialization error report
 * Fixed 32 bytes transaction. It will be DMA now.

Anton Bondarenko (8):
  spi: imx: fix loopback mode setup after controller reset
  spi: imx: enable loopback only for ECSPI controller family
  spi: imx: return error from dma channel request
  spi: imx: defer spi initialization, if DMA engine is
  spi: imx: allow only WML aligned transfers to use DMA
  spi: imx: remove dead RX DMA tail handling code
  spi: imx: replace fixed timeout with calculated
  spi: imx: add support for all SPI word width for DMA

 drivers/spi/spi-imx.c | 203 +++---
 1 file changed, 145 insertions(+), 58 deletions(-)

-- 
2.6.3

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


[PATCH v6 7/8] spi: imx: replace fixed timeout with calculated

2015-12-07 Thread Anton Bondarenko
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 HW internal CS change.

Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 26 +++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 08492d6..d74d809 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -56,7 +56,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;
@@ -92,6 +91,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 *);
@@ -331,6 +331,7 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
 
/* set clock speed */
ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz, );
+   spi_imx->spi_bus_clk = clk;
 
/* set chip select to use */
ctrl |= MX51_ECSPI_CTRL_CS(config->cs);
@@ -913,11 +914,26 @@ static void spi_imx_dma_tx_callback(void *cookie)
complete(_imx->dma_tx_completion);
 }
 
+static int spi_imx_calculate_timeout(struct spi_imx_data *spi_imx, int size)
+{
+   unsigned long timeout = 0;
+
+   /* Time with actual data transfer and CS change delay related to HW */
+   timeout = (8 + 4) * size / spi_imx->spi_bus_clk;
+
+   /* Add extra second for scheduler related activities */
+   timeout += 1;
+
+   /* Double calculated timeout */
+   return msecs_to_jiffies(2 * timeout * MSEC_PER_SEC);
+}
+
 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 transfer_timeout;
unsigned long timeout;
struct spi_master *master = spi_imx->bitbang.master;
struct sg_table *tx = >tx_sg, *rx = >rx_sg;
@@ -964,9 +980,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(_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(>dev),
@@ -974,8 +992,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);
timeout = wait_for_completion_timeout(
-   _imx->dma_rx_completion, IMX_DMA_TIMEOUT);
+   _imx->dma_rx_completion, transfer_timeout);
if (!timeout) {
pr_warn("%s %s: I/O Error in DMA RX\n",
dev_driver_string(>dev),
-- 
2.6.3

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


[PATCH v6 2/8] spi: imx: enable loopback only for ECSPI controller family

2015-12-07 Thread Anton Bondarenko
Limit SPI_LOOP mode to ECSPI controller (iMX.51, iMX53 and i.MX6) only since
there is no support in other families specific code for now.

Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 3aa33c8..17a90dc 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -1140,6 +1140,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)
@@ -1164,14 +1167,12 @@ 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_LOOP;
+   spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+   if (is_imx51_ecspi(spi_imx))
+   spi_imx->bitbang.master->mode_bits |= SPI_LOOP;
 
init_completion(_imx->xfer_done);
 
-   spi_imx->devtype_data = of_id ? of_id->data :
-   (struct spi_imx_devtype_data *) pdev->id_entry->driver_data;
-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
spi_imx->base = devm_ioremap_resource(>dev, res);
if (IS_ERR(spi_imx->base)) {
-- 
2.6.3

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


[PATCH v6 6/8] spi: imx: remove dead RX DMA tail handling code

2015-12-07 Thread Anton Bondarenko
transfer->len % wml for DMA capable transactions will always be 0
due to recent change in can_dma checks. So it's safe to remove dead code
in processing DMA.

Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 13 -
 1 file changed, 13 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 50e0a79..08492d6 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -919,8 +919,6 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL;
int ret;
unsigned long timeout;
-   u32 dma;
-   int left;
struct spi_master *master = spi_imx->bitbang.master;
struct sg_table *tx = >tx_sg, *rx = >rx_sg;
 
@@ -954,13 +952,6 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
/* Trigger the cspi module. */
spi_imx->dma_finished = 0;
 
-   dma = readl(spi_imx->base + MX51_ECSPI_DMA);
-   dma = dma & (~MX51_ECSPI_DMA_RXT_WML_MASK);
-   /* Change RX_DMA_LENGTH trigger dma fetch tail data */
-   left = transfer->len % spi_imx->wml;
-   if (left)
-   writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET),
-   spi_imx->base + MX51_ECSPI_DMA);
/*
 * Set these order to avoid potential RX overflow. The overflow may
 * happen if we enable SPI HW before starting RX DMA due to rescheduling
@@ -992,10 +983,6 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
spi_imx->devtype_data->reset(spi_imx);
dmaengine_terminate_all(master->dma_rx);
}
-   dma &= ~MX51_ECSPI_DMA_RXT_WML_MASK;
-   writel(dma |
-  spi_imx->wml << MX51_ECSPI_DMA_RXT_WML_OFFSET,
-  spi_imx->base + MX51_ECSPI_DMA);
}
 
spi_imx->dma_finished = 1;
-- 
2.6.3

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


Re: [PATCH v5 08/11] spi: imx: allow only WML aligned transfers to use DMA

2015-12-07 Thread Anton Bondarenko



On 2015-12-07 10:42, Sascha Hauer wrote:

On Sat, Dec 05, 2015 at 05:57:06PM +0100, Anton Bondarenko wrote:

RX DMA tail data handling doesn't work correctly in many cases with current
implementation. It happens because SPI core was setup to generates both RX
and RX TAIL events. And RX TAIL event does not work correctly.
This can be easily verified by sending SPI transaction with size modulus
WML(32 in our case) not equal 0.

Also removing change introduced in f6ee9b582d2db652497b73c1f117591dfb6d3a90
since this change only fix usecases with transfer size from 33 to 128 bytes
and does not fix 129 bytes etc.

This is output from transaction with len 138 bytes in loopback mode at 10Mhz:
TX: a3 97 a2 55 53 be f1 fc f9 79 6b 52 14 13 e9 e2
TX0010: 2d 51 8e 1f 56 08 57 27 a7 05 d4 d0 52 82 77 75
TX0020: 1b 99 4a ed 58 3d 6a 52 36 d5 24 4a 68 8e ad 95
TX0030: 5f 3c 35 b5 c4 8c dd 6c 11 32 3d e2 b4 b4 59 cf
TX0040: ce 23 3d 27 df a7 f9 96 fc 1e e0 66 2c 0e 7b 8c
TX0050: ca 30 42 8f bc 9f 7b ce d1 b8 b1 87 ec 8a d6 bb
TX0060: 2e 15 63 0e 3c dc a4 3a 7a 06 20 a7 93 1b 34 dd
TX0070: 4c f5 ec 88 96 68 d6 68 a0 09 6f 8e 93 47 c9 41
TX0080: db ac cf 97 89 f3 51 05 79 71

RX: a3 97 a2 55 53 be f1 fc f9 79 6b 52 14 13 e9 e2
RX0010: 2d 51 8e 1f 56 08 57 27 a7 05 d4 d0 52 82 77 75
RX0020: 1b 99 4a ed 58 3d 6a 52 36 d5 24 4a 68 8e ad 95
RX0030: 5f 3c 35 00 00 b5 00 00 00 c4 00 00 8c 00 00 dd
RX0040: 6c 11 32 3d e2 b4 b4 59 cf ce 23 3d 27 df a7 f9
RX0050: 96 fc 1e e0 66 2c 0e 7b 8c ca 30 42 8f 1f 1f bc
RX0060: 9f 7b ce d1 b8 b1 87 ec 8a d6 bb 2e 15 63 0e ed
RX0070: ed 3c 58 58 58 dc 3d 3d a4 6a 6a 3a 52 52 7a 36
RX0080: 06 20 a7 93 1b 34 dd 4c f5 ec

Zeros at offset 33 and 34 caused by reading empty RX FIFO which not possible
if DMA RX read was triggered by RX event. This mean DMA was triggered
by RX TAIL event.

Signed-off-by: Anton Bondarenko 
---
  drivers/spi/spi-imx.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index fa24637..7a68c62 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -204,8 +204,8 @@ static bool spi_imx_can_dma(struct spi_master *master, 
struct spi_device *spi,
  {
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);

-   if (spi_imx->dma_is_inited &&
-   transfer->len > spi_imx->wml * sizeof(u32))
+   if (spi_imx->dma_is_inited && transfer->len > spi_imx->wml &&
+   (transfer->len % spi_imx->wml) == 0)
return true;


Must transfer->len really be bigger than spi_imx->wml? I would assume it
should be >= instead. And where is the * sizeof(u32) gone? If that's
unnecessary I heven't understood why.

Sascha




Agree on '>='. Will be in V6.
As for missing sizeof(u32).
According to SoC specification it's possible to operate with 8- or 16 
bits word directly by setting proper value in word_width field in CFG 
register. I do not know the what exactly is fixed by f6ee9b582d, but I 
could suspect such scenario:
Some SPI client (spi-nor?) trying to perform SPI transaction with len 
mod 32 not equal zero. It could be any value between 33 and 127, 
excluding 64. But since DMA RX tail functionality does not work 
correctly RX contains some garbage.


But since this commit make can_dma more strict there is no need in old 
fix anymore.


I'll double check with oscilloscope to be sure SPI stream looks good.

Sascha, if you still thinks we need to have sizeof(32) please provide 
the use case or example so I can work on it.


BTW, we need to multiply WML by word size to correctly support 16- and 
32-bits words, but this is done in following commit.


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


Re: [PATCH v5 06/11] spi: imx: return error from dma channel request

2015-12-07 Thread Anton Bondarenko



On 2015-12-07 10:32, Sascha Hauer wrote:

On Sat, Dec 05, 2015 at 05:57:04PM +0100, Anton Bondarenko wrote:

On SDMA initialization return exactly the same error, which is
reported by dma_request_slave_channel_reason(), it is a preceding
change to defer SPI DMA initialization, if SDMA module is not yet
available.

Signed-off-by: Vladimir Zapolskiy 
Signed-off-by: Anton Bondarenko 
---
  drivers/spi/spi-imx.c | 27 ---
  1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 3525616..277dd75 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -846,10 +846,11 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2;

/* Prepare for TX DMA: */
-   master->dma_tx = dma_request_slave_channel(dev, "tx");
-   if (!master->dma_tx) {
-   dev_err(dev, "cannot get the TX DMA channel!\n");
-   ret = -EINVAL;
+   master->dma_tx = dma_request_slave_channel_reason(dev, "tx");
+   if (IS_ERR(master->dma_tx)) {
+   dev_info(dev, "cannot get the TX DMA channel!\n");


When changing it can you add the error code to the message? That's
usually the next thing one wants to know when reading it. Also, isn't
dev_dbg enough here? Otherwise the driver gets really verbose when it
actually defers probe.

Sascha



Agreed. But the error from spi_imx_sdma_init printed in probe. Anyway, 
I've changed the code as requested in upcoming series V6.


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


Re: [PATCH v5 05/11] spi: imx: Add support for loopback for ECSPI controllers

2015-12-07 Thread Anton Bondarenko



On 2015-12-07 10:27, Sascha Hauer wrote:

On Sat, Dec 05, 2015 at 05:57:03PM +0100, Anton Bondarenko wrote:

Support for ECSPI loopback for IMX51, IMX53 and IMX6Q using TEST register.

Signed-off-by: Mohsin Kazmi 
Signed-off-by: Anton Bondarenko 
---
  drivers/spi/spi-imx.c | 19 ---
  1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 363276d..3525616 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -246,6 +246,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_TEST0x20
+#define MX51_ECSPI_LOOPBIT(31)
+
  /* MX51 eCSPI */
  static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi,
  unsigned int *fres)
@@ -316,6 +319,7 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0;
u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg;
u32 clk = config->speed_hz, delay;
+   u32 lpb = 0;

/*
 * The hardware seems to have a race condition when changing modes. The
@@ -356,6 +360,12 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);

+   if (config->mode & SPI_LOOP)
+   lpb |= MX51_ECSPI_LOOP;
+
+   if ((readl(spi_imx->base + MX51_ECSPI_TEST) & MX51_ECSPI_LOOP) != lpb)
+   writel(lpb, spi_imx->base + MX51_ECSPI_TEST);
+
/*
 * Wait until the changes in the configuration register CONFIGREG
 * propagate into the hardware. It takes exactly one tick of the
@@ -1128,6 +1138,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)
@@ -1154,10 +1167,10 @@ static int spi_imx_probe(struct platform_device *pdev)
spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;

-   init_completion(_imx->xfer_done);
+   if (is_imx51_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(_imx->xfer_done);


Some unrelated lines are moved in these two hunks. Is this necessary or
just some leftover from development?

Sascha



Sascha,

This is necessary because is_imx51_ecspi function is base on content of 
spi_imx->devtype_data (see previous commit PATCH v5 04/11). I could try 
to move SPI_LOOP mode bit set to avoid change for completion initialization.


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


[PATCH v6 8/8] spi: imx: add support for all SPI word width for DMA

2015-12-07 Thread Anton Bondarenko
DMA transfer for SPI was limited to up to 8 bits word size until now.
Sync in SPI burst size and DMA bus width is necessary to correctly
support 16 and 32 BPW.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 121 +++---
 1 file changed, 95 insertions(+), 26 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index d74d809..750001c 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -88,11 +88,15 @@ struct spi_imx_data {
 
struct completion xfer_done;
void __iomem *base;
+   unsigned long base_phys;
+
struct clk *clk_per;
struct clk *clk_ipg;
unsigned long spi_clk;
unsigned int spi_bus_clk;
 
+   unsigned int bytes_per_word;
+
unsigned int count;
void (*tx)(struct spi_imx_data *);
void (*rx)(struct spi_imx_data *);
@@ -199,13 +203,32 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
return 7;
 }
 
+static int spi_imx_get_bytes_per_word(const int bpw)
+{
+   return DIV_ROUND_UP(bpw, BITS_PER_BYTE);
+}
+
 static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
 struct spi_transfer *transfer)
 {
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+   unsigned int bpw = transfer->bits_per_word;
+
+   if (!bpw)
+   bpw = spi->bits_per_word;
 
-   if (spi_imx->dma_is_inited && transfer->len >= spi_imx->wml &&
-   (transfer->len % spi_imx->wml) == 0)
+   bpw = spi_imx_get_bytes_per_word(bpw);
+
+   /*
+* We need to use SPI word size in calculation to decide
+* if we want to go with DMA or PIO mode. Just a short example:
+* We need to transfer 24 SPI words with BPW == 32. This will take
+* 24 PIO writes to FIFO (and same for reads). But transfer->len will
+* be 24*4=96 bytes. WML is 32 SPI words. The decision will be incorrect
+* if we do not take into account SPI bits per word.
+*/
+   if (spi_imx->dma_is_inited && transfer->len >= (spi_imx->wml * bpw) &&
+   (transfer->len % (spi_imx->wml * bpw)) == 0)
return true;
return false;
 }
@@ -785,11 +808,60 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id)
return IRQ_HANDLED;
 }
 
+static int spi_imx_sdma_configure(struct spi_master *master)
+{
+   int ret;
+   enum dma_slave_buswidth dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE;
+   struct dma_slave_config slave_config = {};
+   struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+
+   switch (spi_imx->bytes_per_word) {
+   case 4:
+   dsb_default = DMA_SLAVE_BUSWIDTH_4_BYTES;
+   break;
+   case 2:
+   dsb_default = DMA_SLAVE_BUSWIDTH_2_BYTES;
+   break;
+   case 1:
+   dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE;
+   break;
+   default:
+   pr_err("Not supported word size %d\n", spi_imx->bytes_per_word);
+   ret = -EINVAL;
+   goto err;
+   }
+
+   slave_config.direction = DMA_MEM_TO_DEV;
+   slave_config.dst_addr = spi_imx->base_phys + MXC_CSPITXDATA;
+   slave_config.dst_addr_width = dsb_default;
+   slave_config.dst_maxburst = spi_imx->wml;
+   ret = dmaengine_slave_config(master->dma_tx, _config);
+   if (ret) {
+   pr_err("error in TX dma configuration.\n");
+   goto err;
+   }
+
+   memset(_config, 0, sizeof(slave_config));
+
+   slave_config.direction = DMA_DEV_TO_MEM;
+   slave_config.src_addr = spi_imx->base_phys + MXC_CSPIRXDATA;
+   slave_config.src_addr_width = dsb_default;
+   slave_config.src_maxburst = spi_imx->wml;
+   ret = dmaengine_slave_config(master->dma_rx, _config);
+   if (ret)
+   pr_err("error in RX dma configuration.\n");
+
+err:
+   return ret;
+}
+
 static int spi_imx_setupxfer(struct spi_device *spi,
 struct spi_transfer *t)
 {
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
struct spi_imx_config config;
+   unsigned int new_bytes_per_word;
+   int ret = 0;
 
config.bpw = t ? t->bits_per_word : spi->bits_per_word;
config.speed_hz  = t ? t->speed_hz : spi->max_speed_hz;
@@ -813,9 +885,19 @@ static int spi_imx_setupxfer(struct spi_device *spi,
spi_imx->tx = spi_imx_buf_tx_u32;
}
 
-   spi_imx->devtype_data->config(spi_imx, );
+   new_bytes_per_word = spi_imx_get_bytes_per_word(config.bpw);
+   if (spi_imx->dma_is_inited &&
+   spi_imx->bytes_per_word != new_bytes_per_word) {
+   spi_imx->bytes_p

[PATCH v6 2/8] spi: imx: enable loopback only for ECSPI controller family

2015-12-07 Thread Anton Bondarenko
Limit SPI_LOOP mode to ECSPI controller (iMX.51, iMX53 and i.MX6) only since
there is no support in other families specific code for now.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 3aa33c8..17a90dc 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -1140,6 +1140,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)
@@ -1164,14 +1167,12 @@ 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_LOOP;
+   spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+   if (is_imx51_ecspi(spi_imx))
+   spi_imx->bitbang.master->mode_bits |= SPI_LOOP;
 
init_completion(_imx->xfer_done);
 
-   spi_imx->devtype_data = of_id ? of_id->data :
-   (struct spi_imx_devtype_data *) pdev->id_entry->driver_data;
-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
spi_imx->base = devm_ioremap_resource(>dev, res);
if (IS_ERR(spi_imx->base)) {
-- 
2.6.3

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


[PATCH v6 0/8] Improvements for SPI IMX driver for Freescale ECSPI controller, continuation

2015-12-07 Thread Anton Bondarenko
This series is to complement commits already applied to topic/imx branch

Changes since V5:
 * Fix for commit "spi: imx: Add loopback mode support"
 * Addressed some comments from Sascha Hauer for DMA initialization error report
 * Fixed 32 bytes transaction. It will be DMA now.

Anton Bondarenko (8):
  spi: imx: fix loopback mode setup after controller reset
  spi: imx: enable loopback only for ECSPI controller family
  spi: imx: return error from dma channel request
  spi: imx: defer spi initialization, if DMA engine is
  spi: imx: allow only WML aligned transfers to use DMA
  spi: imx: remove dead RX DMA tail handling code
  spi: imx: replace fixed timeout with calculated
  spi: imx: add support for all SPI word width for DMA

 drivers/spi/spi-imx.c | 203 +++---
 1 file changed, 145 insertions(+), 58 deletions(-)

-- 
2.6.3

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


[PATCH v6 6/8] spi: imx: remove dead RX DMA tail handling code

2015-12-07 Thread Anton Bondarenko
transfer->len % wml for DMA capable transactions will always be 0
due to recent change in can_dma checks. So it's safe to remove dead code
in processing DMA.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 13 -
 1 file changed, 13 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 50e0a79..08492d6 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -919,8 +919,6 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL;
int ret;
unsigned long timeout;
-   u32 dma;
-   int left;
struct spi_master *master = spi_imx->bitbang.master;
struct sg_table *tx = >tx_sg, *rx = >rx_sg;
 
@@ -954,13 +952,6 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
/* Trigger the cspi module. */
spi_imx->dma_finished = 0;
 
-   dma = readl(spi_imx->base + MX51_ECSPI_DMA);
-   dma = dma & (~MX51_ECSPI_DMA_RXT_WML_MASK);
-   /* Change RX_DMA_LENGTH trigger dma fetch tail data */
-   left = transfer->len % spi_imx->wml;
-   if (left)
-   writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET),
-   spi_imx->base + MX51_ECSPI_DMA);
/*
 * Set these order to avoid potential RX overflow. The overflow may
 * happen if we enable SPI HW before starting RX DMA due to rescheduling
@@ -992,10 +983,6 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
spi_imx->devtype_data->reset(spi_imx);
dmaengine_terminate_all(master->dma_rx);
}
-   dma &= ~MX51_ECSPI_DMA_RXT_WML_MASK;
-   writel(dma |
-  spi_imx->wml << MX51_ECSPI_DMA_RXT_WML_OFFSET,
-  spi_imx->base + MX51_ECSPI_DMA);
}
 
spi_imx->dma_finished = 1;
-- 
2.6.3

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


[PATCH v6 4/8] spi: imx: defer spi initialization, if DMA engine is

2015-12-07 Thread Anton Bondarenko
If SPI device supports DMA mode, but DMA controller is not yet
available due to e.g. a delay in the corresponding kernel module
initialization, retry to initialize SPI driver later on instead of
falling back into PIO only mode.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index c123060..d98c33c 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -1222,6 +1222,9 @@ static int spi_imx_probe(struct platform_device *pdev)
 */
if (is_imx51_ecspi(spi_imx)) {
ret = spi_imx_sdma_init(>dev, spi_imx, master, res);
+   if (ret == -EPROBE_DEFER)
+   goto out_clk_put;
+
if (ret < 0)
dev_err(>dev, "dma setup error %d, use pio\n",
ret);
-- 
2.6.3

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


[PATCH v6 5/8] spi: imx: allow only WML aligned transfers to use DMA

2015-12-07 Thread Anton Bondarenko
RX DMA tail data handling doesn't work correctly in many cases with current
implementation. It happens because SPI core was setup to generates both RX
and RX TAIL events. And RX TAIL event does not work correctly.
This can be easily verified by sending SPI transaction with size modulus
WML(32 in our case) not equal 0.

Also removing change introduced in f6ee9b582d2db652497b73c1f117591dfb6d3a90
since this change only fix usecases with transfer size from 33 to 128 bytes
and doesn't fix 129 bytes and bigger.

This is output from transaction with len 138 bytes in loopback mode at 10Mhz:
TX: a3 97 a2 55 53 be f1 fc f9 79 6b 52 14 13 e9 e2
TX0010: 2d 51 8e 1f 56 08 57 27 a7 05 d4 d0 52 82 77 75
TX0020: 1b 99 4a ed 58 3d 6a 52 36 d5 24 4a 68 8e ad 95
TX0030: 5f 3c 35 b5 c4 8c dd 6c 11 32 3d e2 b4 b4 59 cf
TX0040: ce 23 3d 27 df a7 f9 96 fc 1e e0 66 2c 0e 7b 8c
TX0050: ca 30 42 8f bc 9f 7b ce d1 b8 b1 87 ec 8a d6 bb
TX0060: 2e 15 63 0e 3c dc a4 3a 7a 06 20 a7 93 1b 34 dd
TX0070: 4c f5 ec 88 96 68 d6 68 a0 09 6f 8e 93 47 c9 41
TX0080: db ac cf 97 89 f3 51 05 79 71

RX: a3 97 a2 55 53 be f1 fc f9 79 6b 52 14 13 e9 e2
RX0010: 2d 51 8e 1f 56 08 57 27 a7 05 d4 d0 52 82 77 75
RX0020: 1b 99 4a ed 58 3d 6a 52 36 d5 24 4a 68 8e ad 95
RX0030: 5f 3c 35 00 00 b5 00 00 00 c4 00 00 8c 00 00 dd
RX0040: 6c 11 32 3d e2 b4 b4 59 cf ce 23 3d 27 df a7 f9
RX0050: 96 fc 1e e0 66 2c 0e 7b 8c ca 30 42 8f 1f 1f bc
RX0060: 9f 7b ce d1 b8 b1 87 ec 8a d6 bb 2e 15 63 0e ed
RX0070: ed 3c 58 58 58 dc 3d 3d a4 6a 6a 3a 52 52 7a 36
RX0080: 06 20 a7 93 1b 34 dd 4c f5 ec

Zeros at offset 33 and 34 caused by reading empty RX FIFO which not possible
if DMA RX read was triggered by RX event. This mean DMA was triggered
by RX TAIL event.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index d98c33c..50e0a79 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -204,8 +204,8 @@ static bool spi_imx_can_dma(struct spi_master *master, 
struct spi_device *spi,
 {
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
 
-   if (spi_imx->dma_is_inited &&
-   transfer->len > spi_imx->wml * sizeof(u32))
+   if (spi_imx->dma_is_inited && transfer->len >= spi_imx->wml &&
+   (transfer->len % spi_imx->wml) == 0)
return true;
return false;
 }
-- 
2.6.3

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


[PATCH v6 3/8] spi: imx: return error from dma channel request

2015-12-07 Thread Anton Bondarenko
On SDMA initialization return exactly the same error, which is
reported by dma_request_slave_channel_reason(), it is a preceding
change to defer SPI DMA initialization, if SDMA module is not yet
available.

Signed-off-by: Vladimir Zapolskiy <vladimir_zapols...@mentor.com>
Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 27 ---
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 17a90dc..c123060 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -848,10 +848,11 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2;
 
/* Prepare for TX DMA: */
-   master->dma_tx = dma_request_slave_channel(dev, "tx");
-   if (!master->dma_tx) {
-   dev_err(dev, "cannot get the TX DMA channel!\n");
-   ret = -EINVAL;
+   master->dma_tx = dma_request_slave_channel_reason(dev, "tx");
+   if (IS_ERR(master->dma_tx)) {
+   ret = PTR_ERR(master->dma_tx);
+   dev_dbg(dev, "can't get the TX DMA channel, error %d!\n", ret);
+   master->dma_tx = NULL;
goto err;
}
 
@@ -866,10 +867,11 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
}
 
/* Prepare for RX : */
-   master->dma_rx = dma_request_slave_channel(dev, "rx");
-   if (!master->dma_rx) {
-   dev_dbg(dev, "cannot get the DMA channel.\n");
-   ret = -EINVAL;
+   master->dma_rx = dma_request_slave_channel_reason(dev, "rx");
+   if (IS_ERR(master->dma_rx)) {
+   ret = PTR_ERR(master->dma_rx);
+   dev_dbg(dev, "can't get the RX DMA channel, error %d\n", ret);
+   master->dma_rx = NULL;
goto err;
}
 
@@ -1218,9 +1220,12 @@ static int spi_imx_probe(struct platform_device *pdev)
 * Only validated on i.mx6 now, can remove the constrain if validated on
 * other chips.
 */
-   if (is_imx51_ecspi(spi_imx) &&
-   spi_imx_sdma_init(>dev, spi_imx, master, res))
-   dev_err(>dev, "dma setup error,use pio instead\n");
+   if (is_imx51_ecspi(spi_imx)) {
+   ret = spi_imx_sdma_init(>dev, spi_imx, master, res);
+   if (ret < 0)
+   dev_err(>dev, "dma setup error %d, use pio\n",
+   ret);
+   }
 
spi_imx->devtype_data->reset(spi_imx);
 
-- 
2.6.3

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


[PATCH v6 1/8] spi: imx: fix loopback mode setup after controller reset

2015-12-07 Thread Anton Bondarenko
If controller hold in reset it's not possible to write any
register except CTRL. So all other registers must be updated
only after controller bring out from reset.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 410522f..3aa33c8 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -356,6 +356,9 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
else
cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(config->cs);
 
+   /* CTRL register always go first to bring out controller from reset */
+   writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
+
reg = readl(spi_imx->base + MX51_ECSPI_TESTREG);
if (config->mode & SPI_LOOP)
reg |= MX51_ECSPI_TESTREG_LBC;
@@ -363,7 +366,6 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
reg &= ~MX51_ECSPI_TESTREG_LBC;
writel(reg, spi_imx->base + MX51_ECSPI_TESTREG);
 
-   writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
 
/*
-- 
2.6.3

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


[PATCH v6 7/8] spi: imx: replace fixed timeout with calculated

2015-12-07 Thread Anton Bondarenko
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 HW internal CS change.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 26 +++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 08492d6..d74d809 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -56,7 +56,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;
@@ -92,6 +91,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 *);
@@ -331,6 +331,7 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
 
/* set clock speed */
ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz, );
+   spi_imx->spi_bus_clk = clk;
 
/* set chip select to use */
ctrl |= MX51_ECSPI_CTRL_CS(config->cs);
@@ -913,11 +914,26 @@ static void spi_imx_dma_tx_callback(void *cookie)
complete(_imx->dma_tx_completion);
 }
 
+static int spi_imx_calculate_timeout(struct spi_imx_data *spi_imx, int size)
+{
+   unsigned long timeout = 0;
+
+   /* Time with actual data transfer and CS change delay related to HW */
+   timeout = (8 + 4) * size / spi_imx->spi_bus_clk;
+
+   /* Add extra second for scheduler related activities */
+   timeout += 1;
+
+   /* Double calculated timeout */
+   return msecs_to_jiffies(2 * timeout * MSEC_PER_SEC);
+}
+
 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 transfer_timeout;
unsigned long timeout;
struct spi_master *master = spi_imx->bitbang.master;
struct sg_table *tx = >tx_sg, *rx = >rx_sg;
@@ -964,9 +980,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(_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(>dev),
@@ -974,8 +992,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);
timeout = wait_for_completion_timeout(
-   _imx->dma_rx_completion, IMX_DMA_TIMEOUT);
+   _imx->dma_rx_completion, transfer_timeout);
if (!timeout) {
pr_warn("%s %s: I/O Error in DMA RX\n",
dev_driver_string(>dev),
-- 
2.6.3

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


Re: [PATCH v5 05/11] spi: imx: Add support for loopback for ECSPI controllers

2015-12-07 Thread Anton Bondarenko



On 2015-12-07 10:27, Sascha Hauer wrote:

On Sat, Dec 05, 2015 at 05:57:03PM +0100, Anton Bondarenko wrote:

Support for ECSPI loopback for IMX51, IMX53 and IMX6Q using TEST register.

Signed-off-by: Mohsin Kazmi <mohsin_ka...@mentor.com>
Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
  drivers/spi/spi-imx.c | 19 ---
  1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 363276d..3525616 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -246,6 +246,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_TEST0x20
+#define MX51_ECSPI_LOOPBIT(31)
+
  /* MX51 eCSPI */
  static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi,
  unsigned int *fres)
@@ -316,6 +319,7 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0;
u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg;
u32 clk = config->speed_hz, delay;
+   u32 lpb = 0;

/*
 * The hardware seems to have a race condition when changing modes. The
@@ -356,6 +360,12 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);

+   if (config->mode & SPI_LOOP)
+   lpb |= MX51_ECSPI_LOOP;
+
+   if ((readl(spi_imx->base + MX51_ECSPI_TEST) & MX51_ECSPI_LOOP) != lpb)
+   writel(lpb, spi_imx->base + MX51_ECSPI_TEST);
+
/*
 * Wait until the changes in the configuration register CONFIGREG
 * propagate into the hardware. It takes exactly one tick of the
@@ -1128,6 +1138,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)
@@ -1154,10 +1167,10 @@ static int spi_imx_probe(struct platform_device *pdev)
spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;

-   init_completion(_imx->xfer_done);
+   if (is_imx51_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(_imx->xfer_done);


Some unrelated lines are moved in these two hunks. Is this necessary or
just some leftover from development?

Sascha



Sascha,

This is necessary because is_imx51_ecspi function is base on content of 
spi_imx->devtype_data (see previous commit PATCH v5 04/11). I could try 
to move SPI_LOOP mode bit set to avoid change for completion initialization.


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


Re: [PATCH v5 06/11] spi: imx: return error from dma channel request

2015-12-07 Thread Anton Bondarenko



On 2015-12-07 10:32, Sascha Hauer wrote:

On Sat, Dec 05, 2015 at 05:57:04PM +0100, Anton Bondarenko wrote:

On SDMA initialization return exactly the same error, which is
reported by dma_request_slave_channel_reason(), it is a preceding
change to defer SPI DMA initialization, if SDMA module is not yet
available.

Signed-off-by: Vladimir Zapolskiy <vladimir_zapols...@mentor.com>
Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
  drivers/spi/spi-imx.c | 27 ---
  1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 3525616..277dd75 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -846,10 +846,11 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2;

/* Prepare for TX DMA: */
-   master->dma_tx = dma_request_slave_channel(dev, "tx");
-   if (!master->dma_tx) {
-   dev_err(dev, "cannot get the TX DMA channel!\n");
-   ret = -EINVAL;
+   master->dma_tx = dma_request_slave_channel_reason(dev, "tx");
+   if (IS_ERR(master->dma_tx)) {
+   dev_info(dev, "cannot get the TX DMA channel!\n");


When changing it can you add the error code to the message? That's
usually the next thing one wants to know when reading it. Also, isn't
dev_dbg enough here? Otherwise the driver gets really verbose when it
actually defers probe.

Sascha



Agreed. But the error from spi_imx_sdma_init printed in probe. Anyway, 
I've changed the code as requested in upcoming series V6.


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


Re: [PATCH v5 08/11] spi: imx: allow only WML aligned transfers to use DMA

2015-12-07 Thread Anton Bondarenko



On 2015-12-07 10:42, Sascha Hauer wrote:

On Sat, Dec 05, 2015 at 05:57:06PM +0100, Anton Bondarenko wrote:

RX DMA tail data handling doesn't work correctly in many cases with current
implementation. It happens because SPI core was setup to generates both RX
and RX TAIL events. And RX TAIL event does not work correctly.
This can be easily verified by sending SPI transaction with size modulus
WML(32 in our case) not equal 0.

Also removing change introduced in f6ee9b582d2db652497b73c1f117591dfb6d3a90
since this change only fix usecases with transfer size from 33 to 128 bytes
and does not fix 129 bytes etc.

This is output from transaction with len 138 bytes in loopback mode at 10Mhz:
TX: a3 97 a2 55 53 be f1 fc f9 79 6b 52 14 13 e9 e2
TX0010: 2d 51 8e 1f 56 08 57 27 a7 05 d4 d0 52 82 77 75
TX0020: 1b 99 4a ed 58 3d 6a 52 36 d5 24 4a 68 8e ad 95
TX0030: 5f 3c 35 b5 c4 8c dd 6c 11 32 3d e2 b4 b4 59 cf
TX0040: ce 23 3d 27 df a7 f9 96 fc 1e e0 66 2c 0e 7b 8c
TX0050: ca 30 42 8f bc 9f 7b ce d1 b8 b1 87 ec 8a d6 bb
TX0060: 2e 15 63 0e 3c dc a4 3a 7a 06 20 a7 93 1b 34 dd
TX0070: 4c f5 ec 88 96 68 d6 68 a0 09 6f 8e 93 47 c9 41
TX0080: db ac cf 97 89 f3 51 05 79 71

RX: a3 97 a2 55 53 be f1 fc f9 79 6b 52 14 13 e9 e2
RX0010: 2d 51 8e 1f 56 08 57 27 a7 05 d4 d0 52 82 77 75
RX0020: 1b 99 4a ed 58 3d 6a 52 36 d5 24 4a 68 8e ad 95
RX0030: 5f 3c 35 00 00 b5 00 00 00 c4 00 00 8c 00 00 dd
RX0040: 6c 11 32 3d e2 b4 b4 59 cf ce 23 3d 27 df a7 f9
RX0050: 96 fc 1e e0 66 2c 0e 7b 8c ca 30 42 8f 1f 1f bc
RX0060: 9f 7b ce d1 b8 b1 87 ec 8a d6 bb 2e 15 63 0e ed
RX0070: ed 3c 58 58 58 dc 3d 3d a4 6a 6a 3a 52 52 7a 36
RX0080: 06 20 a7 93 1b 34 dd 4c f5 ec

Zeros at offset 33 and 34 caused by reading empty RX FIFO which not possible
if DMA RX read was triggered by RX event. This mean DMA was triggered
by RX TAIL event.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
  drivers/spi/spi-imx.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index fa24637..7a68c62 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -204,8 +204,8 @@ static bool spi_imx_can_dma(struct spi_master *master, 
struct spi_device *spi,
  {
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);

-   if (spi_imx->dma_is_inited &&
-   transfer->len > spi_imx->wml * sizeof(u32))
+   if (spi_imx->dma_is_inited && transfer->len > spi_imx->wml &&
+   (transfer->len % spi_imx->wml) == 0)
return true;


Must transfer->len really be bigger than spi_imx->wml? I would assume it
should be >= instead. And where is the * sizeof(u32) gone? If that's
unnecessary I heven't understood why.

Sascha




Agree on '>='. Will be in V6.
As for missing sizeof(u32).
According to SoC specification it's possible to operate with 8- or 16 
bits word directly by setting proper value in word_width field in CFG 
register. I do not know the what exactly is fixed by f6ee9b582d, but I 
could suspect such scenario:
Some SPI client (spi-nor?) trying to perform SPI transaction with len 
mod 32 not equal zero. It could be any value between 33 and 127, 
excluding 64. But since DMA RX tail functionality does not work 
correctly RX contains some garbage.


But since this commit make can_dma more strict there is no need in old 
fix anymore.


I'll double check with oscilloscope to be sure SPI stream looks good.

Sascha, if you still thinks we need to have sizeof(32) please provide 
the use case or example so I can work on it.


BTW, we need to multiply WML by word size to correctly support 16- and 
32-bits words, but this is done in following commit.


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


[PATCH v5 01/11] spi: imx: terminate RX DMA transaction in case of TX DMA timeout

2015-12-05 Thread Anton Bondarenko
Not only TX DMA should be terminated, but RX DMA also. It's required
to avoid accidential DMA memory writes from RX DMA channel and properly
terminate transaction.

Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 0e5723a..fb3bcc4 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -958,6 +958,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
dev_driver_string(>dev),
dev_name(>dev));
dmaengine_terminate_all(master->dma_tx);
+   dmaengine_terminate_all(master->dma_rx);
} else {
timeout = wait_for_completion_timeout(
_imx->dma_rx_completion, IMX_DMA_TIMEOUT);
-- 
2.6.3

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


[PATCH v5 00/11] Improvements for SPI IMX driver for Freescale IMX51, IMX53 and IMX6

2015-12-05 Thread Anton Bondarenko
A number of patches to impove or add the implementation
for the spi-imx driver related to Freescale IMX51, 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.

Changes since V4:
 * Split [PATCH v4 01] into several smaller commits
 * Change [PATCH v4 01] into workaround to disable DMA for transfer which len 
mod WML
not equal 0
 * Rework some patches to isolate changes in one place

Anton Bondarenko (11):
  spi: imx: terminate RX DMA transaction in case of TX DMA timeout
  spi: imx: reorder HW operations enable order to avoid possible RX data
loss
  spi: imx: replace multiple watermarks with single for RX, TX and RXT
  spi: imx: add function to check for IMX51 family controller
  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
  spi: imx: allow only WML aligned transfers to use DMA
  spi: imx: remove dead RX DMA tail handling code
  spi: imx: replace fixed timeout with calculated
  spi: imx: add support for all SPI word width for DMA

 drivers/spi/spi-imx.c | 249 --
 1 file changed, 179 insertions(+), 70 deletions(-)

-- 
2.6.3

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


[PATCH v5 03/11] spi: imx: replace multiple watermarks with single for RX, TX and RXT

2015-12-05 Thread Anton Bondarenko
There is no need to have different watermarks levels since they are the same.
Merge them into one WML parameter.

Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 29 +
 1 file changed, 13 insertions(+), 16 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 17e8f9e..f811f68 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -104,9 +104,7 @@ struct spi_imx_data {
unsigned int dma_is_inited;
unsigned int dma_finished;
bool usedma;
-   u32 rx_wml;
-   u32 tx_wml;
-   u32 rxt_wml;
+   u32 wml;
struct completion dma_rx_completion;
struct completion dma_tx_completion;
 
@@ -201,9 +199,8 @@ static bool spi_imx_can_dma(struct spi_master *master, 
struct spi_device *spi,
 {
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
 
-   if (spi_imx->dma_is_inited
-   && transfer->len > spi_imx->rx_wml * sizeof(u32)
-   && transfer->len > spi_imx->tx_wml * sizeof(u32))
+   if (spi_imx->dma_is_inited &&
+   transfer->len > spi_imx->wml * sizeof(u32))
return true;
return false;
 }
@@ -378,10 +375,9 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
if (spi_imx->dma_is_inited) {
dma = readl(spi_imx->base + MX51_ECSPI_DMA);
 
-   spi_imx->rxt_wml = spi_imx_get_fifosize(spi_imx) / 2;
-   rx_wml_cfg = spi_imx->rx_wml << MX51_ECSPI_DMA_RX_WML_OFFSET;
-   tx_wml_cfg = spi_imx->tx_wml << MX51_ECSPI_DMA_TX_WML_OFFSET;
-   rxt_wml_cfg = spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET;
+   rx_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_RX_WML_OFFSET;
+   tx_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_TX_WML_OFFSET;
+   rxt_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_RXT_WML_OFFSET;
dma = (dma & ~MX51_ECSPI_DMA_TX_WML_MASK
   & ~MX51_ECSPI_DMA_RX_WML_MASK
   & ~MX51_ECSPI_DMA_RXT_WML_MASK)
@@ -832,6 +828,8 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
if (of_machine_is_compatible("fsl,imx6dl"))
return 0;
 
+   spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2;
+
/* Prepare for TX DMA: */
master->dma_tx = dma_request_slave_channel(dev, "tx");
if (!master->dma_tx) {
@@ -843,7 +841,7 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
slave_config.direction = DMA_MEM_TO_DEV;
slave_config.dst_addr = res->start + MXC_CSPITXDATA;
slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-   slave_config.dst_maxburst = spi_imx_get_fifosize(spi_imx) / 2;
+   slave_config.dst_maxburst = spi_imx->wml;
ret = dmaengine_slave_config(master->dma_tx, _config);
if (ret) {
dev_err(dev, "error in TX dma configuration.\n");
@@ -861,7 +859,7 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
slave_config.direction = DMA_DEV_TO_MEM;
slave_config.src_addr = res->start + MXC_CSPIRXDATA;
slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-   slave_config.src_maxburst = spi_imx_get_fifosize(spi_imx) / 2;
+   slave_config.src_maxburst = spi_imx->wml;
ret = dmaengine_slave_config(master->dma_rx, _config);
if (ret) {
dev_err(dev, "error in RX dma configuration.\n");
@@ -874,8 +872,6 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
master->max_dma_len = MAX_SDMA_BD_BYTES;
spi_imx->bitbang.master->flags = SPI_MASTER_MUST_RX |
 SPI_MASTER_MUST_TX;
-   spi_imx->tx_wml = spi_imx_get_fifosize(spi_imx) / 2;
-   spi_imx->rx_wml = spi_imx_get_fifosize(spi_imx) / 2;
spi_imx->dma_is_inited = 1;
 
return 0;
@@ -942,7 +938,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
dma = readl(spi_imx->base + MX51_ECSPI_DMA);
dma = dma & (~MX51_ECSPI_DMA_RXT_WML_MASK);
/* Change RX_DMA_LENGTH trigger dma fetch tail data */
-   left = transfer->len % spi_imx->rxt_wml;
+   left = transfer->len % spi_imx->wml;
if (left)
writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET),
spi_imx->base + MX51_ECSPI_DMA);
@@ -977,8 +973,9 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
spi_imx->devtype_data->reset(spi_imx);
dmaengine_terminate_all(master->dma_rx);
}
+   

[PATCH v5 07/11] spi: imx: defer spi initialization, if DMA engine is

2015-12-05 Thread Anton Bondarenko
If SPI device supports DMA mode, but DMA controller is not yet
available due to e.g. a delay in the corresponding kernel module
initialization, retry to initialize SPI driver later on instead of
falling back into PIO only mode.

Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 277dd75..fa24637 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -1221,6 +1221,9 @@ static int spi_imx_probe(struct platform_device *pdev)
 */
if (is_imx51_ecspi(spi_imx)) {
ret = spi_imx_sdma_init(>dev, spi_imx, master, res);
+   if (ret == -EPROBE_DEFER)
+   goto out_clk_put;
+
if (ret < 0)
dev_err(>dev, "dma setup error %d, use pio\n",
ret);
-- 
2.6.3

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


[PATCH v5 05/11] spi: imx: Add support for loopback for ECSPI controllers

2015-12-05 Thread Anton Bondarenko
Support for ECSPI loopback for IMX51, IMX53 and IMX6Q using TEST register.

Signed-off-by: Mohsin Kazmi 
Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 363276d..3525616 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -246,6 +246,9 @@ static bool spi_imx_can_dma(struct spi_master *master, 
struct spi_device *spi,
 #define MX51_ECSPI_STAT0x18
 #define MX51_ECSPI_STAT_RR (1 <<  3)
 
+#define MX51_ECSPI_TEST0x20
+#define MX51_ECSPI_LOOPBIT(31)
+
 /* MX51 eCSPI */
 static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi,
  unsigned int *fres)
@@ -316,6 +319,7 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0;
u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg;
u32 clk = config->speed_hz, delay;
+   u32 lpb = 0;
 
/*
 * The hardware seems to have a race condition when changing modes. The
@@ -356,6 +360,12 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
 
+   if (config->mode & SPI_LOOP)
+   lpb |= MX51_ECSPI_LOOP;
+
+   if ((readl(spi_imx->base + MX51_ECSPI_TEST) & MX51_ECSPI_LOOP) != lpb)
+   writel(lpb, spi_imx->base + MX51_ECSPI_TEST);
+
/*
 * Wait until the changes in the configuration register CONFIGREG
 * propagate into the hardware. It takes exactly one tick of the
@@ -1128,6 +1138,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)
@@ -1154,10 +1167,10 @@ static int spi_imx_probe(struct platform_device *pdev)
spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 
-   init_completion(_imx->xfer_done);
+   if (is_imx51_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(_imx->xfer_done);
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
spi_imx->base = devm_ioremap_resource(>dev, res);
-- 
2.6.3

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


[PATCH v5 10/11] spi: imx: replace fixed timeout with calculated

2015-12-05 Thread Anton Bondarenko
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 HW internal CS change.

Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 33 +++--
 1 file changed, 27 insertions(+), 6 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index adfa9cf..f7ee288 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -56,7 +56,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;
@@ -92,6 +91,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 *);
@@ -318,7 +318,7 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
 {
u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0;
u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg;
-   u32 clk = config->speed_hz, delay;
+   u32 delay;
u32 lpb = 0;
 
/*
@@ -331,7 +331,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, );
+   spi_imx->spi_bus_clk = config->speed_hz;
+   ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz,
+ _imx->spi_bus_clk);
 
/* set chip select to use */
ctrl |= MX51_ECSPI_CTRL_CS(config->cs);
@@ -377,7 +379,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 * 100) / 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 */
@@ -911,11 +913,26 @@ static void spi_imx_dma_tx_callback(void *cookie)
complete(_imx->dma_tx_completion);
 }
 
+static int spi_imx_calculate_timeout(struct spi_imx_data *spi_imx, int size)
+{
+   unsigned long timeout = 0;
+
+   /* Time with actual data transfer and CS change delay related to HW */
+   timeout = (8 + 4) * size / spi_imx->spi_bus_clk;
+
+   /* Add extra second for scheduler related activities */
+   timeout += 1;
+
+   /* Double calculated timeout */
+   return msecs_to_jiffies(2 * timeout * MSEC_PER_SEC);
+}
+
 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 transfer_timeout;
unsigned long timeout;
struct spi_master *master = spi_imx->bitbang.master;
struct sg_table *tx = >tx_sg, *rx = >rx_sg;
@@ -962,9 +979,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(_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(>dev),
@@ -972,8 +991,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);
timeout = wait_for_completion_timeout(
-   _imx->dma_rx_completion, IMX_DMA_TIMEOUT);
+   _imx->dma_rx_completion, transfer_timeout);
if (!timeout) {
pr_warn("%s %s: I/O Error in DMA RX\n",
dev_driver_string(>dev),
-- 
2.6.3

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


[PATCH v5 02/11] spi: imx: reorder HW operations enable order to avoid possible RX data loss

2015-12-05 Thread Anton Bondarenko
The overflow may happen due to rescheduling for another task and/or interrupt
if we enable SPI HW before starting RX DMA. So RX DMA enabled first to make
sure data would be read out from FIFO ASAP. TX DMA enabled next to start
filling TX FIFO with new data. And finaly SPI HW enabled to start actual
data transfer.

The risk rise in case of heavy system load and high SPI clock.

Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index fb3bcc4..17e8f9e 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -946,10 +946,18 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
if (left)
writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET),
spi_imx->base + MX51_ECSPI_DMA);
+   /*
+* Set these order to avoid potential RX overflow. The overflow may
+* happen if we enable SPI HW before starting RX DMA due to rescheduling
+* for another task and/or interrupt.
+* So RX DMA enabled first to make sure data would be read out from FIFO
+* ASAP. TX DMA enabled next to start filling TX FIFO with new data.
+* And finaly SPI HW enabled to start actual data transfer.
+*/
+   dma_async_issue_pending(master->dma_rx);
+   dma_async_issue_pending(master->dma_tx);
spi_imx->devtype_data->trigger(spi_imx);
 
-   dma_async_issue_pending(master->dma_tx);
-   dma_async_issue_pending(master->dma_rx);
/* Wait SDMA to finish the data transfer.*/
timeout = wait_for_completion_timeout(_imx->dma_tx_completion,
IMX_DMA_TIMEOUT);
-- 
2.6.3

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


[PATCH v5 08/11] spi: imx: allow only WML aligned transfers to use DMA

2015-12-05 Thread Anton Bondarenko
RX DMA tail data handling doesn't work correctly in many cases with current
implementation. It happens because SPI core was setup to generates both RX
and RX TAIL events. And RX TAIL event does not work correctly.
This can be easily verified by sending SPI transaction with size modulus
WML(32 in our case) not equal 0.

Also removing change introduced in f6ee9b582d2db652497b73c1f117591dfb6d3a90
since this change only fix usecases with transfer size from 33 to 128 bytes
and does not fix 129 bytes etc.

This is output from transaction with len 138 bytes in loopback mode at 10Mhz:
TX: a3 97 a2 55 53 be f1 fc f9 79 6b 52 14 13 e9 e2
TX0010: 2d 51 8e 1f 56 08 57 27 a7 05 d4 d0 52 82 77 75
TX0020: 1b 99 4a ed 58 3d 6a 52 36 d5 24 4a 68 8e ad 95
TX0030: 5f 3c 35 b5 c4 8c dd 6c 11 32 3d e2 b4 b4 59 cf
TX0040: ce 23 3d 27 df a7 f9 96 fc 1e e0 66 2c 0e 7b 8c
TX0050: ca 30 42 8f bc 9f 7b ce d1 b8 b1 87 ec 8a d6 bb
TX0060: 2e 15 63 0e 3c dc a4 3a 7a 06 20 a7 93 1b 34 dd
TX0070: 4c f5 ec 88 96 68 d6 68 a0 09 6f 8e 93 47 c9 41
TX0080: db ac cf 97 89 f3 51 05 79 71

RX: a3 97 a2 55 53 be f1 fc f9 79 6b 52 14 13 e9 e2
RX0010: 2d 51 8e 1f 56 08 57 27 a7 05 d4 d0 52 82 77 75
RX0020: 1b 99 4a ed 58 3d 6a 52 36 d5 24 4a 68 8e ad 95
RX0030: 5f 3c 35 00 00 b5 00 00 00 c4 00 00 8c 00 00 dd
RX0040: 6c 11 32 3d e2 b4 b4 59 cf ce 23 3d 27 df a7 f9
RX0050: 96 fc 1e e0 66 2c 0e 7b 8c ca 30 42 8f 1f 1f bc
RX0060: 9f 7b ce d1 b8 b1 87 ec 8a d6 bb 2e 15 63 0e ed
RX0070: ed 3c 58 58 58 dc 3d 3d a4 6a 6a 3a 52 52 7a 36
RX0080: 06 20 a7 93 1b 34 dd 4c f5 ec

Zeros at offset 33 and 34 caused by reading empty RX FIFO which not possible
if DMA RX read was triggered by RX event. This mean DMA was triggered
by RX TAIL event.

Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index fa24637..7a68c62 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -204,8 +204,8 @@ static bool spi_imx_can_dma(struct spi_master *master, 
struct spi_device *spi,
 {
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
 
-   if (spi_imx->dma_is_inited &&
-   transfer->len > spi_imx->wml * sizeof(u32))
+   if (spi_imx->dma_is_inited && transfer->len > spi_imx->wml &&
+   (transfer->len % spi_imx->wml) == 0)
return true;
return false;
 }
-- 
2.6.3

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


[PATCH v5 06/11] spi: imx: return error from dma channel request

2015-12-05 Thread Anton Bondarenko
On SDMA initialization return exactly the same error, which is
reported by dma_request_slave_channel_reason(), it is a preceding
change to defer SPI DMA initialization, if SDMA module is not yet
available.

Signed-off-by: Vladimir Zapolskiy 
Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 27 ---
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 3525616..277dd75 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -846,10 +846,11 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2;
 
/* Prepare for TX DMA: */
-   master->dma_tx = dma_request_slave_channel(dev, "tx");
-   if (!master->dma_tx) {
-   dev_err(dev, "cannot get the TX DMA channel!\n");
-   ret = -EINVAL;
+   master->dma_tx = dma_request_slave_channel_reason(dev, "tx");
+   if (IS_ERR(master->dma_tx)) {
+   dev_info(dev, "cannot get the TX DMA channel!\n");
+   ret = PTR_ERR(master->dma_tx);
+   master->dma_tx = NULL;
goto err;
}
 
@@ -864,10 +865,11 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
}
 
/* Prepare for RX : */
-   master->dma_rx = dma_request_slave_channel(dev, "rx");
-   if (!master->dma_rx) {
-   dev_dbg(dev, "cannot get the DMA channel.\n");
-   ret = -EINVAL;
+   master->dma_rx = dma_request_slave_channel_reason(dev, "rx");
+   if (IS_ERR(master->dma_rx)) {
+   dev_info(dev, "cannot get the DMA channel.\n");
+   ret = PTR_ERR(master->dma_rx);
+   master->dma_rx = NULL;
goto err;
}
 
@@ -1217,9 +1219,12 @@ static int spi_imx_probe(struct platform_device *pdev)
 * Only validated on i.mx6 now, can remove the constrain if validated on
 * other chips.
 */
-   if (is_imx51_ecspi(spi_imx) &&
-   spi_imx_sdma_init(>dev, spi_imx, master, res))
-   dev_err(>dev, "dma setup error,use pio instead\n");
+   if (is_imx51_ecspi(spi_imx)) {
+   ret = spi_imx_sdma_init(>dev, spi_imx, master, res);
+   if (ret < 0)
+   dev_err(>dev, "dma setup error %d, use pio\n",
+   ret);
+   }
 
spi_imx->devtype_data->reset(spi_imx);
 
-- 
2.6.3

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


[PATCH v5 09/11] spi: imx: remove dead RX DMA tail handling code

2015-12-05 Thread Anton Bondarenko
transfer->len % wml for DMA capable transactions will always be 0
due to recent change in can_dma checks. So it's safe to remove dead code
in processing DMA.

Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 13 -
 1 file changed, 13 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 7a68c62..adfa9cf 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -917,8 +917,6 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL;
int ret;
unsigned long timeout;
-   u32 dma;
-   int left;
struct spi_master *master = spi_imx->bitbang.master;
struct sg_table *tx = >tx_sg, *rx = >rx_sg;
 
@@ -952,13 +950,6 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
/* Trigger the cspi module. */
spi_imx->dma_finished = 0;
 
-   dma = readl(spi_imx->base + MX51_ECSPI_DMA);
-   dma = dma & (~MX51_ECSPI_DMA_RXT_WML_MASK);
-   /* Change RX_DMA_LENGTH trigger dma fetch tail data */
-   left = transfer->len % spi_imx->wml;
-   if (left)
-   writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET),
-   spi_imx->base + MX51_ECSPI_DMA);
/*
 * Set these order to avoid potential RX overflow. The overflow may
 * happen if we enable SPI HW before starting RX DMA due to rescheduling
@@ -990,10 +981,6 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
spi_imx->devtype_data->reset(spi_imx);
dmaengine_terminate_all(master->dma_rx);
}
-   dma &= ~MX51_ECSPI_DMA_RXT_WML_MASK;
-   writel(dma |
-  spi_imx->wml << MX51_ECSPI_DMA_RXT_WML_OFFSET,
-  spi_imx->base + MX51_ECSPI_DMA);
}
 
spi_imx->dma_finished = 1;
-- 
2.6.3

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


[PATCH v5 11/11] spi: imx: add support for all SPI word width for DMA

2015-12-05 Thread Anton Bondarenko
DMA transfer for SPI was limited to up to 8 bits word size until now.
Sync in SPI burst size and DMA bus width is necessary to correctly
support 16 and 32 BPW.

Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 121 +++---
 1 file changed, 95 insertions(+), 26 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index f7ee288..d1b9903 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -88,11 +88,15 @@ struct spi_imx_data {
 
struct completion xfer_done;
void __iomem *base;
+   unsigned long base_phys;
+
struct clk *clk_per;
struct clk *clk_ipg;
unsigned long spi_clk;
unsigned int spi_bus_clk;
 
+   unsigned int bytes_per_word;
+
unsigned int count;
void (*tx)(struct spi_imx_data *);
void (*rx)(struct spi_imx_data *);
@@ -199,13 +203,32 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
return 7;
 }
 
+static int spi_imx_get_bytes_per_word(const int bpw)
+{
+   return DIV_ROUND_UP(bpw, BITS_PER_BYTE);
+}
+
 static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
 struct spi_transfer *transfer)
 {
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+   unsigned int bpw = transfer->bits_per_word;
+
+   if (!bpw)
+   bpw = spi->bits_per_word;
 
-   if (spi_imx->dma_is_inited && transfer->len > spi_imx->wml &&
-   (transfer->len % spi_imx->wml) == 0)
+   bpw = spi_imx_get_bytes_per_word(bpw);
+
+   /*
+* We need to use SPI word size in calculation to decide
+* if we want to go with DMA or PIO mode. Just a short example:
+* We need to transfer 24 SPI words with BPW == 32. This will take
+* 24 PIO writes to FIFO (and same for reads). But transfer->len will
+* be 24*4=96 bytes. WML is 32 SPI words. The decision will be incorrect
+* if we do not take into account SPI bits per word.
+*/
+   if (spi_imx->dma_is_inited && transfer->len > (spi_imx->wml * bpw) &&
+   (transfer->len % (spi_imx->wml * bpw)) == 0)
return true;
return false;
 }
@@ -784,11 +807,60 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id)
return IRQ_HANDLED;
 }
 
+static int spi_imx_sdma_configure(struct spi_master *master)
+{
+   int ret;
+   enum dma_slave_buswidth dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE;
+   struct dma_slave_config slave_config = {};
+   struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+
+   switch (spi_imx->bytes_per_word) {
+   case 4:
+   dsb_default = DMA_SLAVE_BUSWIDTH_4_BYTES;
+   break;
+   case 2:
+   dsb_default = DMA_SLAVE_BUSWIDTH_2_BYTES;
+   break;
+   case 1:
+   dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE;
+   break;
+   default:
+   pr_err("Not supported word size %d\n", spi_imx->bytes_per_word);
+   ret = -EINVAL;
+   goto err;
+   }
+
+   slave_config.direction = DMA_MEM_TO_DEV;
+   slave_config.dst_addr = spi_imx->base_phys + MXC_CSPITXDATA;
+   slave_config.dst_addr_width = dsb_default;
+   slave_config.dst_maxburst = spi_imx->wml;
+   ret = dmaengine_slave_config(master->dma_tx, _config);
+   if (ret) {
+   pr_err("error in TX dma configuration.\n");
+   goto err;
+   }
+
+   memset(_config, 0, sizeof(slave_config));
+
+   slave_config.direction = DMA_DEV_TO_MEM;
+   slave_config.src_addr = spi_imx->base_phys + MXC_CSPIRXDATA;
+   slave_config.src_addr_width = dsb_default;
+   slave_config.src_maxburst = spi_imx->wml;
+   ret = dmaengine_slave_config(master->dma_rx, _config);
+   if (ret)
+   pr_err("error in RX dma configuration.\n");
+
+err:
+   return ret;
+}
+
 static int spi_imx_setupxfer(struct spi_device *spi,
 struct spi_transfer *t)
 {
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
struct spi_imx_config config;
+   unsigned int new_bytes_per_word;
+   int ret = 0;
 
config.bpw = t ? t->bits_per_word : spi->bits_per_word;
config.speed_hz  = t ? t->speed_hz : spi->max_speed_hz;
@@ -812,9 +884,19 @@ static int spi_imx_setupxfer(struct spi_device *spi,
spi_imx->tx = spi_imx_buf_tx_u32;
}
 
-   spi_imx->devtype_data->config(spi_imx, );
+   new_bytes_per_word = spi_imx_get_bytes_per_word(config.bpw);
+   if (spi_imx->dma_is_inited &&
+   spi_imx->bytes_per_word != new_bytes_per_word) {
+   spi_imx->bytes_per_word = new_byt

[PATCH v5 04/11] spi: imx: add function to check for IMX51 family controller

2015-12-05 Thread Anton Bondarenko
Similar to other controller type checks add check function for
IMX51. It includes IMX53 and IMX6.

Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index f811f68..363276d 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -122,9 +122,14 @@ static inline int is_imx35_cspi(struct spi_imx_data *d)
return d->devtype_data->devtype == IMX35_CSPI;
 }
 
+static inline int is_imx51_ecspi(struct spi_imx_data *d)
+{
+   return d->devtype_data->devtype == IMX51_ECSPI;
+}
+
 static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d)
 {
-   return (d->devtype_data->devtype == IMX51_ECSPI) ? 64 : 8;
+   return is_imx51_ecspi(d) ? 64 : 8;
 }
 
 #define MXC_SPI_BUF_RX(type)   \
@@ -1199,8 +1204,8 @@ static int spi_imx_probe(struct platform_device *pdev)
 * Only validated on i.mx6 now, can remove the constrain if validated on
 * other chips.
 */
-   if (spi_imx->devtype_data == _ecspi_devtype_data
-   && spi_imx_sdma_init(>dev, spi_imx, master, res))
+   if (is_imx51_ecspi(spi_imx) &&
+   spi_imx_sdma_init(>dev, spi_imx, master, res))
dev_err(>dev, "dma setup error,use pio instead\n");
 
spi_imx->devtype_data->reset(spi_imx);
-- 
2.6.3

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


[PATCH v5 10/11] spi: imx: replace fixed timeout with calculated

2015-12-05 Thread Anton Bondarenko
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 HW internal CS change.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 33 +++--
 1 file changed, 27 insertions(+), 6 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index adfa9cf..f7ee288 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -56,7 +56,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;
@@ -92,6 +91,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 *);
@@ -318,7 +318,7 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
 {
u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0;
u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg;
-   u32 clk = config->speed_hz, delay;
+   u32 delay;
u32 lpb = 0;
 
/*
@@ -331,7 +331,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, );
+   spi_imx->spi_bus_clk = config->speed_hz;
+   ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz,
+ _imx->spi_bus_clk);
 
/* set chip select to use */
ctrl |= MX51_ECSPI_CTRL_CS(config->cs);
@@ -377,7 +379,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 * 100) / 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 */
@@ -911,11 +913,26 @@ static void spi_imx_dma_tx_callback(void *cookie)
complete(_imx->dma_tx_completion);
 }
 
+static int spi_imx_calculate_timeout(struct spi_imx_data *spi_imx, int size)
+{
+   unsigned long timeout = 0;
+
+   /* Time with actual data transfer and CS change delay related to HW */
+   timeout = (8 + 4) * size / spi_imx->spi_bus_clk;
+
+   /* Add extra second for scheduler related activities */
+   timeout += 1;
+
+   /* Double calculated timeout */
+   return msecs_to_jiffies(2 * timeout * MSEC_PER_SEC);
+}
+
 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 transfer_timeout;
unsigned long timeout;
struct spi_master *master = spi_imx->bitbang.master;
struct sg_table *tx = >tx_sg, *rx = >rx_sg;
@@ -962,9 +979,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(_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(>dev),
@@ -972,8 +991,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);
timeout = wait_for_completion_timeout(
-   _imx->dma_rx_completion, IMX_DMA_TIMEOUT);
+   _imx->dma_rx_completion, transfer_timeout);
if (!timeout) {
pr_warn("%s %s: I/O Error in DMA RX\n",
dev_driver_string(>dev),
-- 
2.6.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a messag

[PATCH v5 07/11] spi: imx: defer spi initialization, if DMA engine is

2015-12-05 Thread Anton Bondarenko
If SPI device supports DMA mode, but DMA controller is not yet
available due to e.g. a delay in the corresponding kernel module
initialization, retry to initialize SPI driver later on instead of
falling back into PIO only mode.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 277dd75..fa24637 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -1221,6 +1221,9 @@ static int spi_imx_probe(struct platform_device *pdev)
 */
if (is_imx51_ecspi(spi_imx)) {
ret = spi_imx_sdma_init(>dev, spi_imx, master, res);
+   if (ret == -EPROBE_DEFER)
+   goto out_clk_put;
+
if (ret < 0)
dev_err(>dev, "dma setup error %d, use pio\n",
ret);
-- 
2.6.3

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


[PATCH v5 01/11] spi: imx: terminate RX DMA transaction in case of TX DMA timeout

2015-12-05 Thread Anton Bondarenko
Not only TX DMA should be terminated, but RX DMA also. It's required
to avoid accidential DMA memory writes from RX DMA channel and properly
terminate transaction.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 0e5723a..fb3bcc4 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -958,6 +958,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
dev_driver_string(>dev),
dev_name(>dev));
dmaengine_terminate_all(master->dma_tx);
+   dmaengine_terminate_all(master->dma_rx);
} else {
timeout = wait_for_completion_timeout(
_imx->dma_rx_completion, IMX_DMA_TIMEOUT);
-- 
2.6.3

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


[PATCH v5 00/11] Improvements for SPI IMX driver for Freescale IMX51, IMX53 and IMX6

2015-12-05 Thread Anton Bondarenko
A number of patches to impove or add the implementation
for the spi-imx driver related to Freescale IMX51, 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.

Changes since V4:
 * Split [PATCH v4 01] into several smaller commits
 * Change [PATCH v4 01] into workaround to disable DMA for transfer which len 
mod WML
not equal 0
 * Rework some patches to isolate changes in one place

Anton Bondarenko (11):
  spi: imx: terminate RX DMA transaction in case of TX DMA timeout
  spi: imx: reorder HW operations enable order to avoid possible RX data
loss
  spi: imx: replace multiple watermarks with single for RX, TX and RXT
  spi: imx: add function to check for IMX51 family controller
  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
  spi: imx: allow only WML aligned transfers to use DMA
  spi: imx: remove dead RX DMA tail handling code
  spi: imx: replace fixed timeout with calculated
  spi: imx: add support for all SPI word width for DMA

 drivers/spi/spi-imx.c | 249 --
 1 file changed, 179 insertions(+), 70 deletions(-)

-- 
2.6.3

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


[PATCH v5 03/11] spi: imx: replace multiple watermarks with single for RX, TX and RXT

2015-12-05 Thread Anton Bondarenko
There is no need to have different watermarks levels since they are the same.
Merge them into one WML parameter.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 29 +
 1 file changed, 13 insertions(+), 16 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 17e8f9e..f811f68 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -104,9 +104,7 @@ struct spi_imx_data {
unsigned int dma_is_inited;
unsigned int dma_finished;
bool usedma;
-   u32 rx_wml;
-   u32 tx_wml;
-   u32 rxt_wml;
+   u32 wml;
struct completion dma_rx_completion;
struct completion dma_tx_completion;
 
@@ -201,9 +199,8 @@ static bool spi_imx_can_dma(struct spi_master *master, 
struct spi_device *spi,
 {
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
 
-   if (spi_imx->dma_is_inited
-   && transfer->len > spi_imx->rx_wml * sizeof(u32)
-   && transfer->len > spi_imx->tx_wml * sizeof(u32))
+   if (spi_imx->dma_is_inited &&
+   transfer->len > spi_imx->wml * sizeof(u32))
return true;
return false;
 }
@@ -378,10 +375,9 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
if (spi_imx->dma_is_inited) {
dma = readl(spi_imx->base + MX51_ECSPI_DMA);
 
-   spi_imx->rxt_wml = spi_imx_get_fifosize(spi_imx) / 2;
-   rx_wml_cfg = spi_imx->rx_wml << MX51_ECSPI_DMA_RX_WML_OFFSET;
-   tx_wml_cfg = spi_imx->tx_wml << MX51_ECSPI_DMA_TX_WML_OFFSET;
-   rxt_wml_cfg = spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET;
+   rx_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_RX_WML_OFFSET;
+   tx_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_TX_WML_OFFSET;
+   rxt_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_RXT_WML_OFFSET;
dma = (dma & ~MX51_ECSPI_DMA_TX_WML_MASK
   & ~MX51_ECSPI_DMA_RX_WML_MASK
   & ~MX51_ECSPI_DMA_RXT_WML_MASK)
@@ -832,6 +828,8 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
if (of_machine_is_compatible("fsl,imx6dl"))
return 0;
 
+   spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2;
+
/* Prepare for TX DMA: */
master->dma_tx = dma_request_slave_channel(dev, "tx");
if (!master->dma_tx) {
@@ -843,7 +841,7 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
slave_config.direction = DMA_MEM_TO_DEV;
slave_config.dst_addr = res->start + MXC_CSPITXDATA;
slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-   slave_config.dst_maxburst = spi_imx_get_fifosize(spi_imx) / 2;
+   slave_config.dst_maxburst = spi_imx->wml;
ret = dmaengine_slave_config(master->dma_tx, _config);
if (ret) {
dev_err(dev, "error in TX dma configuration.\n");
@@ -861,7 +859,7 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
slave_config.direction = DMA_DEV_TO_MEM;
slave_config.src_addr = res->start + MXC_CSPIRXDATA;
slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-   slave_config.src_maxburst = spi_imx_get_fifosize(spi_imx) / 2;
+   slave_config.src_maxburst = spi_imx->wml;
ret = dmaengine_slave_config(master->dma_rx, _config);
if (ret) {
dev_err(dev, "error in RX dma configuration.\n");
@@ -874,8 +872,6 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
master->max_dma_len = MAX_SDMA_BD_BYTES;
spi_imx->bitbang.master->flags = SPI_MASTER_MUST_RX |
 SPI_MASTER_MUST_TX;
-   spi_imx->tx_wml = spi_imx_get_fifosize(spi_imx) / 2;
-   spi_imx->rx_wml = spi_imx_get_fifosize(spi_imx) / 2;
spi_imx->dma_is_inited = 1;
 
return 0;
@@ -942,7 +938,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
dma = readl(spi_imx->base + MX51_ECSPI_DMA);
dma = dma & (~MX51_ECSPI_DMA_RXT_WML_MASK);
/* Change RX_DMA_LENGTH trigger dma fetch tail data */
-   left = transfer->len % spi_imx->rxt_wml;
+   left = transfer->len % spi_imx->wml;
if (left)
writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET),
spi_imx->base + MX51_ECSPI_DMA);
@@ -977,8 +973,9 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
spi_imx->devtype_data->reset(spi_imx);
dmaengine_terminate_all(ma

[PATCH v5 04/11] spi: imx: add function to check for IMX51 family controller

2015-12-05 Thread Anton Bondarenko
Similar to other controller type checks add check function for
IMX51. It includes IMX53 and IMX6.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index f811f68..363276d 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -122,9 +122,14 @@ static inline int is_imx35_cspi(struct spi_imx_data *d)
return d->devtype_data->devtype == IMX35_CSPI;
 }
 
+static inline int is_imx51_ecspi(struct spi_imx_data *d)
+{
+   return d->devtype_data->devtype == IMX51_ECSPI;
+}
+
 static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d)
 {
-   return (d->devtype_data->devtype == IMX51_ECSPI) ? 64 : 8;
+   return is_imx51_ecspi(d) ? 64 : 8;
 }
 
 #define MXC_SPI_BUF_RX(type)   \
@@ -1199,8 +1204,8 @@ static int spi_imx_probe(struct platform_device *pdev)
 * Only validated on i.mx6 now, can remove the constrain if validated on
 * other chips.
 */
-   if (spi_imx->devtype_data == _ecspi_devtype_data
-   && spi_imx_sdma_init(>dev, spi_imx, master, res))
+   if (is_imx51_ecspi(spi_imx) &&
+   spi_imx_sdma_init(>dev, spi_imx, master, res))
dev_err(>dev, "dma setup error,use pio instead\n");
 
spi_imx->devtype_data->reset(spi_imx);
-- 
2.6.3

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


[PATCH v5 11/11] spi: imx: add support for all SPI word width for DMA

2015-12-05 Thread Anton Bondarenko
DMA transfer for SPI was limited to up to 8 bits word size until now.
Sync in SPI burst size and DMA bus width is necessary to correctly
support 16 and 32 BPW.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 121 +++---
 1 file changed, 95 insertions(+), 26 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index f7ee288..d1b9903 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -88,11 +88,15 @@ struct spi_imx_data {
 
struct completion xfer_done;
void __iomem *base;
+   unsigned long base_phys;
+
struct clk *clk_per;
struct clk *clk_ipg;
unsigned long spi_clk;
unsigned int spi_bus_clk;
 
+   unsigned int bytes_per_word;
+
unsigned int count;
void (*tx)(struct spi_imx_data *);
void (*rx)(struct spi_imx_data *);
@@ -199,13 +203,32 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
return 7;
 }
 
+static int spi_imx_get_bytes_per_word(const int bpw)
+{
+   return DIV_ROUND_UP(bpw, BITS_PER_BYTE);
+}
+
 static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
 struct spi_transfer *transfer)
 {
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+   unsigned int bpw = transfer->bits_per_word;
+
+   if (!bpw)
+   bpw = spi->bits_per_word;
 
-   if (spi_imx->dma_is_inited && transfer->len > spi_imx->wml &&
-   (transfer->len % spi_imx->wml) == 0)
+   bpw = spi_imx_get_bytes_per_word(bpw);
+
+   /*
+* We need to use SPI word size in calculation to decide
+* if we want to go with DMA or PIO mode. Just a short example:
+* We need to transfer 24 SPI words with BPW == 32. This will take
+* 24 PIO writes to FIFO (and same for reads). But transfer->len will
+* be 24*4=96 bytes. WML is 32 SPI words. The decision will be incorrect
+* if we do not take into account SPI bits per word.
+*/
+   if (spi_imx->dma_is_inited && transfer->len > (spi_imx->wml * bpw) &&
+   (transfer->len % (spi_imx->wml * bpw)) == 0)
return true;
return false;
 }
@@ -784,11 +807,60 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id)
return IRQ_HANDLED;
 }
 
+static int spi_imx_sdma_configure(struct spi_master *master)
+{
+   int ret;
+   enum dma_slave_buswidth dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE;
+   struct dma_slave_config slave_config = {};
+   struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+
+   switch (spi_imx->bytes_per_word) {
+   case 4:
+   dsb_default = DMA_SLAVE_BUSWIDTH_4_BYTES;
+   break;
+   case 2:
+   dsb_default = DMA_SLAVE_BUSWIDTH_2_BYTES;
+   break;
+   case 1:
+   dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE;
+   break;
+   default:
+   pr_err("Not supported word size %d\n", spi_imx->bytes_per_word);
+   ret = -EINVAL;
+   goto err;
+   }
+
+   slave_config.direction = DMA_MEM_TO_DEV;
+   slave_config.dst_addr = spi_imx->base_phys + MXC_CSPITXDATA;
+   slave_config.dst_addr_width = dsb_default;
+   slave_config.dst_maxburst = spi_imx->wml;
+   ret = dmaengine_slave_config(master->dma_tx, _config);
+   if (ret) {
+   pr_err("error in TX dma configuration.\n");
+   goto err;
+   }
+
+   memset(_config, 0, sizeof(slave_config));
+
+   slave_config.direction = DMA_DEV_TO_MEM;
+   slave_config.src_addr = spi_imx->base_phys + MXC_CSPIRXDATA;
+   slave_config.src_addr_width = dsb_default;
+   slave_config.src_maxburst = spi_imx->wml;
+   ret = dmaengine_slave_config(master->dma_rx, _config);
+   if (ret)
+   pr_err("error in RX dma configuration.\n");
+
+err:
+   return ret;
+}
+
 static int spi_imx_setupxfer(struct spi_device *spi,
 struct spi_transfer *t)
 {
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
struct spi_imx_config config;
+   unsigned int new_bytes_per_word;
+   int ret = 0;
 
config.bpw = t ? t->bits_per_word : spi->bits_per_word;
config.speed_hz  = t ? t->speed_hz : spi->max_speed_hz;
@@ -812,9 +884,19 @@ static int spi_imx_setupxfer(struct spi_device *spi,
spi_imx->tx = spi_imx_buf_tx_u32;
}
 
-   spi_imx->devtype_data->config(spi_imx, );
+   new_bytes_per_word = spi_imx_get_bytes_per_word(config.bpw);
+   if (spi_imx->dma_is_inited &&
+   spi_imx->bytes_per_word != new_bytes_per_word) {
+   spi_imx->bytes_per_

[PATCH v5 06/11] spi: imx: return error from dma channel request

2015-12-05 Thread Anton Bondarenko
On SDMA initialization return exactly the same error, which is
reported by dma_request_slave_channel_reason(), it is a preceding
change to defer SPI DMA initialization, if SDMA module is not yet
available.

Signed-off-by: Vladimir Zapolskiy <vladimir_zapols...@mentor.com>
Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 27 ---
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 3525616..277dd75 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -846,10 +846,11 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2;
 
/* Prepare for TX DMA: */
-   master->dma_tx = dma_request_slave_channel(dev, "tx");
-   if (!master->dma_tx) {
-   dev_err(dev, "cannot get the TX DMA channel!\n");
-   ret = -EINVAL;
+   master->dma_tx = dma_request_slave_channel_reason(dev, "tx");
+   if (IS_ERR(master->dma_tx)) {
+   dev_info(dev, "cannot get the TX DMA channel!\n");
+   ret = PTR_ERR(master->dma_tx);
+   master->dma_tx = NULL;
goto err;
}
 
@@ -864,10 +865,11 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
}
 
/* Prepare for RX : */
-   master->dma_rx = dma_request_slave_channel(dev, "rx");
-   if (!master->dma_rx) {
-   dev_dbg(dev, "cannot get the DMA channel.\n");
-   ret = -EINVAL;
+   master->dma_rx = dma_request_slave_channel_reason(dev, "rx");
+   if (IS_ERR(master->dma_rx)) {
+   dev_info(dev, "cannot get the DMA channel.\n");
+   ret = PTR_ERR(master->dma_rx);
+   master->dma_rx = NULL;
goto err;
}
 
@@ -1217,9 +1219,12 @@ static int spi_imx_probe(struct platform_device *pdev)
 * Only validated on i.mx6 now, can remove the constrain if validated on
 * other chips.
 */
-   if (is_imx51_ecspi(spi_imx) &&
-   spi_imx_sdma_init(>dev, spi_imx, master, res))
-   dev_err(>dev, "dma setup error,use pio instead\n");
+   if (is_imx51_ecspi(spi_imx)) {
+   ret = spi_imx_sdma_init(>dev, spi_imx, master, res);
+   if (ret < 0)
+   dev_err(>dev, "dma setup error %d, use pio\n",
+   ret);
+   }
 
spi_imx->devtype_data->reset(spi_imx);
 
-- 
2.6.3

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


[PATCH v5 09/11] spi: imx: remove dead RX DMA tail handling code

2015-12-05 Thread Anton Bondarenko
transfer->len % wml for DMA capable transactions will always be 0
due to recent change in can_dma checks. So it's safe to remove dead code
in processing DMA.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 13 -
 1 file changed, 13 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 7a68c62..adfa9cf 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -917,8 +917,6 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL;
int ret;
unsigned long timeout;
-   u32 dma;
-   int left;
struct spi_master *master = spi_imx->bitbang.master;
struct sg_table *tx = >tx_sg, *rx = >rx_sg;
 
@@ -952,13 +950,6 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
/* Trigger the cspi module. */
spi_imx->dma_finished = 0;
 
-   dma = readl(spi_imx->base + MX51_ECSPI_DMA);
-   dma = dma & (~MX51_ECSPI_DMA_RXT_WML_MASK);
-   /* Change RX_DMA_LENGTH trigger dma fetch tail data */
-   left = transfer->len % spi_imx->wml;
-   if (left)
-   writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET),
-   spi_imx->base + MX51_ECSPI_DMA);
/*
 * Set these order to avoid potential RX overflow. The overflow may
 * happen if we enable SPI HW before starting RX DMA due to rescheduling
@@ -990,10 +981,6 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
spi_imx->devtype_data->reset(spi_imx);
dmaengine_terminate_all(master->dma_rx);
}
-   dma &= ~MX51_ECSPI_DMA_RXT_WML_MASK;
-   writel(dma |
-  spi_imx->wml << MX51_ECSPI_DMA_RXT_WML_OFFSET,
-  spi_imx->base + MX51_ECSPI_DMA);
}
 
spi_imx->dma_finished = 1;
-- 
2.6.3

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


[PATCH v5 05/11] spi: imx: Add support for loopback for ECSPI controllers

2015-12-05 Thread Anton Bondarenko
Support for ECSPI loopback for IMX51, IMX53 and IMX6Q using TEST register.

Signed-off-by: Mohsin Kazmi <mohsin_ka...@mentor.com>
Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 363276d..3525616 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -246,6 +246,9 @@ static bool spi_imx_can_dma(struct spi_master *master, 
struct spi_device *spi,
 #define MX51_ECSPI_STAT0x18
 #define MX51_ECSPI_STAT_RR (1 <<  3)
 
+#define MX51_ECSPI_TEST0x20
+#define MX51_ECSPI_LOOPBIT(31)
+
 /* MX51 eCSPI */
 static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi,
  unsigned int *fres)
@@ -316,6 +319,7 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0;
u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg;
u32 clk = config->speed_hz, delay;
+   u32 lpb = 0;
 
/*
 * The hardware seems to have a race condition when changing modes. The
@@ -356,6 +360,12 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
 
+   if (config->mode & SPI_LOOP)
+   lpb |= MX51_ECSPI_LOOP;
+
+   if ((readl(spi_imx->base + MX51_ECSPI_TEST) & MX51_ECSPI_LOOP) != lpb)
+   writel(lpb, spi_imx->base + MX51_ECSPI_TEST);
+
/*
 * Wait until the changes in the configuration register CONFIGREG
 * propagate into the hardware. It takes exactly one tick of the
@@ -1128,6 +1138,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)
@@ -1154,10 +1167,10 @@ static int spi_imx_probe(struct platform_device *pdev)
spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 
-   init_completion(_imx->xfer_done);
+   if (is_imx51_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(_imx->xfer_done);
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
spi_imx->base = devm_ioremap_resource(>dev, res);
-- 
2.6.3

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


[PATCH v5 02/11] spi: imx: reorder HW operations enable order to avoid possible RX data loss

2015-12-05 Thread Anton Bondarenko
The overflow may happen due to rescheduling for another task and/or interrupt
if we enable SPI HW before starting RX DMA. So RX DMA enabled first to make
sure data would be read out from FIFO ASAP. TX DMA enabled next to start
filling TX FIFO with new data. And finaly SPI HW enabled to start actual
data transfer.

The risk rise in case of heavy system load and high SPI clock.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index fb3bcc4..17e8f9e 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -946,10 +946,18 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
if (left)
writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET),
spi_imx->base + MX51_ECSPI_DMA);
+   /*
+* Set these order to avoid potential RX overflow. The overflow may
+* happen if we enable SPI HW before starting RX DMA due to rescheduling
+* for another task and/or interrupt.
+* So RX DMA enabled first to make sure data would be read out from FIFO
+* ASAP. TX DMA enabled next to start filling TX FIFO with new data.
+* And finaly SPI HW enabled to start actual data transfer.
+*/
+   dma_async_issue_pending(master->dma_rx);
+   dma_async_issue_pending(master->dma_tx);
spi_imx->devtype_data->trigger(spi_imx);
 
-   dma_async_issue_pending(master->dma_tx);
-   dma_async_issue_pending(master->dma_rx);
/* Wait SDMA to finish the data transfer.*/
timeout = wait_for_completion_timeout(_imx->dma_tx_completion,
IMX_DMA_TIMEOUT);
-- 
2.6.3

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


[PATCH v5 08/11] spi: imx: allow only WML aligned transfers to use DMA

2015-12-05 Thread Anton Bondarenko
RX DMA tail data handling doesn't work correctly in many cases with current
implementation. It happens because SPI core was setup to generates both RX
and RX TAIL events. And RX TAIL event does not work correctly.
This can be easily verified by sending SPI transaction with size modulus
WML(32 in our case) not equal 0.

Also removing change introduced in f6ee9b582d2db652497b73c1f117591dfb6d3a90
since this change only fix usecases with transfer size from 33 to 128 bytes
and does not fix 129 bytes etc.

This is output from transaction with len 138 bytes in loopback mode at 10Mhz:
TX: a3 97 a2 55 53 be f1 fc f9 79 6b 52 14 13 e9 e2
TX0010: 2d 51 8e 1f 56 08 57 27 a7 05 d4 d0 52 82 77 75
TX0020: 1b 99 4a ed 58 3d 6a 52 36 d5 24 4a 68 8e ad 95
TX0030: 5f 3c 35 b5 c4 8c dd 6c 11 32 3d e2 b4 b4 59 cf
TX0040: ce 23 3d 27 df a7 f9 96 fc 1e e0 66 2c 0e 7b 8c
TX0050: ca 30 42 8f bc 9f 7b ce d1 b8 b1 87 ec 8a d6 bb
TX0060: 2e 15 63 0e 3c dc a4 3a 7a 06 20 a7 93 1b 34 dd
TX0070: 4c f5 ec 88 96 68 d6 68 a0 09 6f 8e 93 47 c9 41
TX0080: db ac cf 97 89 f3 51 05 79 71

RX: a3 97 a2 55 53 be f1 fc f9 79 6b 52 14 13 e9 e2
RX0010: 2d 51 8e 1f 56 08 57 27 a7 05 d4 d0 52 82 77 75
RX0020: 1b 99 4a ed 58 3d 6a 52 36 d5 24 4a 68 8e ad 95
RX0030: 5f 3c 35 00 00 b5 00 00 00 c4 00 00 8c 00 00 dd
RX0040: 6c 11 32 3d e2 b4 b4 59 cf ce 23 3d 27 df a7 f9
RX0050: 96 fc 1e e0 66 2c 0e 7b 8c ca 30 42 8f 1f 1f bc
RX0060: 9f 7b ce d1 b8 b1 87 ec 8a d6 bb 2e 15 63 0e ed
RX0070: ed 3c 58 58 58 dc 3d 3d a4 6a 6a 3a 52 52 7a 36
RX0080: 06 20 a7 93 1b 34 dd 4c f5 ec

Zeros at offset 33 and 34 caused by reading empty RX FIFO which not possible
if DMA RX read was triggered by RX event. This mean DMA was triggered
by RX TAIL event.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index fa24637..7a68c62 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -204,8 +204,8 @@ static bool spi_imx_can_dma(struct spi_master *master, 
struct spi_device *spi,
 {
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
 
-   if (spi_imx->dma_is_inited &&
-   transfer->len > spi_imx->wml * sizeof(u32))
+   if (spi_imx->dma_is_inited && transfer->len > spi_imx->wml &&
+   (transfer->len % spi_imx->wml) == 0)
return true;
return false;
 }
-- 
2.6.3

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


Re: [PATCH v4 1/7] spi: imx: Fix DMA transfer

2015-11-30 Thread Anton Bondarenko


On 2015-11-30 09:29, Sascha Hauer wrote:

On Sat, Nov 28, 2015 at 12:15:59AM +0100, Anton Bondarenko wrote:

New implementation change handling of RX data tail. DMA is used to process
all TX data and only full chunks of RX data with size aligned to FIFO/2.
Driver is waiting until both TX and RX DMA transaction done and all
TX data are pushed out. At that moment there is only RX data tail in
the RX FIFO. This data read out using PIO.

Transfer triggering changed to avoid RX data loss.

Signed-off-by: Anton Bondarenko 


This patch doesn't make me feel very comfortable. It's quite big and I
think it contains multiple logical changes. It should be split up
further.


Agreed. I'm going to split patch according to suggestions

---
  drivers/spi/spi-imx.c | 115 +-
  1 file changed, 76 insertions(+), 39 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 0e5723a..bd7b721 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -53,6 +53,7 @@
  /* generic defines to abstract from the different register layouts */
  #define MXC_INT_RR(1 << 0) /* Receive data ready interrupt */
  #define MXC_INT_TE(1 << 1) /* Transmit FIFO empty interrupt */
+#define MXC_INT_TCEN   BIT(7)   /* Transfer complete */

  /* The maximum  bytes that a sdma BD can transfer.*/
  #define MAX_SDMA_BD_BYTES  (1 << 15)
@@ -104,9 +105,7 @@ struct spi_imx_data {
unsigned int dma_is_inited;
unsigned int dma_finished;
bool usedma;
-   u32 rx_wml;
-   u32 tx_wml;
-   u32 rxt_wml;
+   u32 wml;


One logical change is: Merge the different FIFO watermark level
variables into a single variable since they are all the same.


struct completion dma_rx_completion;
struct completion dma_tx_completion;

@@ -939,17 +944,18 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
/* Trigger the cspi module. */
spi_imx->dma_finished = 0;

-   dma = readl(spi_imx->base + MX51_ECSPI_DMA);
-   dma = dma & (~MX51_ECSPI_DMA_RXT_WML_MASK);
-   /* Change RX_DMA_LENGTH trigger dma fetch tail data */
-   left = transfer->len % spi_imx->rxt_wml;
-   if (left)
-   writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET),
-   spi_imx->base + MX51_ECSPI_DMA);
+   /*
+* Set these order to avoid potential RX overflow. The overflow may
+* happen if we enable SPI HW before starting RX DMA due to rescheduling
+* for another task and/or interrupt.
+* So RX DMA enabled first to make sure data would be read out from FIFO
+* ASAP. TX DMA enabled next to start filling TX FIFO with new data.
+* And finaly SPI HW enabled to start actual data transfer.
+*/
+   dma_async_issue_pending(master->dma_rx);
+   dma_async_issue_pending(master->dma_tx);
spi_imx->devtype_data->trigger(spi_imx);

-   dma_async_issue_pending(master->dma_tx);
-   dma_async_issue_pending(master->dma_rx);


Here you fix the order of the different step to start a transfer. This
could also be a separate patch, no?


Agreed.

/* Wait SDMA to finish the data transfer.*/
timeout = wait_for_completion_timeout(_imx->dma_tx_completion,
IMX_DMA_TIMEOUT);
@@ -958,6 +964,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
dev_driver_string(>dev),
dev_name(>dev));
dmaengine_terminate_all(master->dma_tx);
+   dmaengine_terminate_all(master->dma_rx);


This could also be a separate "Add missing dmaengine_terminate_all() for
rx dma" patch.


Agreed.

} else {
timeout = wait_for_completion_timeout(
_imx->dma_rx_completion, IMX_DMA_TIMEOUT);
@@ -967,10 +974,40 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
dev_name(>dev));
spi_imx->devtype_data->reset(spi_imx);
dmaengine_terminate_all(master->dma_rx);
+   } else if (left) {
+   void *pio_buffer = transfer->rx_buf
+   + (transfer->len - left);
+
+   dma_sync_sg_for_cpu(master->dma_rx->device->dev,
+   >sgl[rx->nents - 1], 1,
+   DMA_FROM_DEVICE);
+
+   spi_imx->rx_buf = pio_buffer;
+   spi_imx->txfifo = left;
+   reinit_completion(_imx->xfer_done);
+
+   spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TCEN);
+
+   timeout = wai

Re: [PATCH v4 1/7] spi: imx: Fix DMA transfer

2015-11-30 Thread Anton Bondarenko


On 2015-11-30 09:29, Sascha Hauer wrote:

On Sat, Nov 28, 2015 at 12:15:59AM +0100, Anton Bondarenko wrote:

New implementation change handling of RX data tail. DMA is used to process
all TX data and only full chunks of RX data with size aligned to FIFO/2.
Driver is waiting until both TX and RX DMA transaction done and all
TX data are pushed out. At that moment there is only RX data tail in
the RX FIFO. This data read out using PIO.

Transfer triggering changed to avoid RX data loss.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>


This patch doesn't make me feel very comfortable. It's quite big and I
think it contains multiple logical changes. It should be split up
further.


Agreed. I'm going to split patch according to suggestions

---
  drivers/spi/spi-imx.c | 115 +-
  1 file changed, 76 insertions(+), 39 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 0e5723a..bd7b721 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -53,6 +53,7 @@
  /* generic defines to abstract from the different register layouts */
  #define MXC_INT_RR(1 << 0) /* Receive data ready interrupt */
  #define MXC_INT_TE(1 << 1) /* Transmit FIFO empty interrupt */
+#define MXC_INT_TCEN   BIT(7)   /* Transfer complete */

  /* The maximum  bytes that a sdma BD can transfer.*/
  #define MAX_SDMA_BD_BYTES  (1 << 15)
@@ -104,9 +105,7 @@ struct spi_imx_data {
unsigned int dma_is_inited;
unsigned int dma_finished;
bool usedma;
-   u32 rx_wml;
-   u32 tx_wml;
-   u32 rxt_wml;
+   u32 wml;


One logical change is: Merge the different FIFO watermark level
variables into a single variable since they are all the same.


struct completion dma_rx_completion;
struct completion dma_tx_completion;

@@ -939,17 +944,18 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
/* Trigger the cspi module. */
spi_imx->dma_finished = 0;

-   dma = readl(spi_imx->base + MX51_ECSPI_DMA);
-   dma = dma & (~MX51_ECSPI_DMA_RXT_WML_MASK);
-   /* Change RX_DMA_LENGTH trigger dma fetch tail data */
-   left = transfer->len % spi_imx->rxt_wml;
-   if (left)
-   writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET),
-   spi_imx->base + MX51_ECSPI_DMA);
+   /*
+* Set these order to avoid potential RX overflow. The overflow may
+* happen if we enable SPI HW before starting RX DMA due to rescheduling
+* for another task and/or interrupt.
+* So RX DMA enabled first to make sure data would be read out from FIFO
+* ASAP. TX DMA enabled next to start filling TX FIFO with new data.
+* And finaly SPI HW enabled to start actual data transfer.
+*/
+   dma_async_issue_pending(master->dma_rx);
+   dma_async_issue_pending(master->dma_tx);
spi_imx->devtype_data->trigger(spi_imx);

-   dma_async_issue_pending(master->dma_tx);
-   dma_async_issue_pending(master->dma_rx);


Here you fix the order of the different step to start a transfer. This
could also be a separate patch, no?


Agreed.

/* Wait SDMA to finish the data transfer.*/
timeout = wait_for_completion_timeout(_imx->dma_tx_completion,
IMX_DMA_TIMEOUT);
@@ -958,6 +964,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
dev_driver_string(>dev),
dev_name(>dev));
dmaengine_terminate_all(master->dma_tx);
+   dmaengine_terminate_all(master->dma_rx);


This could also be a separate "Add missing dmaengine_terminate_all() for
rx dma" patch.


Agreed.

} else {
timeout = wait_for_completion_timeout(
_imx->dma_rx_completion, IMX_DMA_TIMEOUT);
@@ -967,10 +974,40 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
dev_name(>dev));
spi_imx->devtype_data->reset(spi_imx);
dmaengine_terminate_all(master->dma_rx);
+   } else if (left) {
+   void *pio_buffer = transfer->rx_buf
+   + (transfer->len - left);
+
+   dma_sync_sg_for_cpu(master->dma_rx->device->dev,
+   >sgl[rx->nents - 1], 1,
+   DMA_FROM_DEVICE);
+
+   spi_imx->rx_buf = pio_buffer;
+   spi_imx->txfifo = left;
+   reinit_completion(_imx->xfer_done);
+
+   spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TCEN);
+
+   timeout

[PATCH v4 1/7] spi: imx: Fix DMA transfer

2015-11-27 Thread Anton Bondarenko
RX DMA tail data handling doesn't work correctly in many cases with
current implementation. It happens because SPI core was setup
to generates both RX watermark level and RX DATA TAIL events
incorrectly. SPI transfer triggering for DMA also done in wrong way.

SPI client wants to transfer 70 words for example. The old DMA
implementation setup RX DATA TAIL equal 6 words. In this case
RX DMA event will be generated after 6 words read from RX FIFO.
The garbage can be read out from RX FIFO because SPI HW does
not receive all required words to trigger RX watermark event.

New implementation change handling of RX data tail. DMA is used to process
all TX data and only full chunks of RX data with size aligned to FIFO/2.
Driver is waiting until both TX and RX DMA transaction done and all
TX data are pushed out. At that moment there is only RX data tail in
the RX FIFO. This data read out using PIO.

Transfer triggering changed to avoid RX data loss.

Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 115 +-
 1 file changed, 76 insertions(+), 39 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 0e5723a..bd7b721 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -53,6 +53,7 @@
 /* generic defines to abstract from the different register layouts */
 #define MXC_INT_RR (1 << 0) /* Receive data ready interrupt */
 #define MXC_INT_TE (1 << 1) /* Transmit FIFO empty interrupt */
+#define MXC_INT_TCEN   BIT(7)   /* Transfer complete */
 
 /* The maximum  bytes that a sdma BD can transfer.*/
 #define MAX_SDMA_BD_BYTES  (1 << 15)
@@ -104,9 +105,7 @@ struct spi_imx_data {
unsigned int dma_is_inited;
unsigned int dma_finished;
bool usedma;
-   u32 rx_wml;
-   u32 tx_wml;
-   u32 rxt_wml;
+   u32 wml;
struct completion dma_rx_completion;
struct completion dma_tx_completion;
 
@@ -201,9 +200,7 @@ static bool spi_imx_can_dma(struct spi_master *master, 
struct spi_device *spi,
 {
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
 
-   if (spi_imx->dma_is_inited
-   && transfer->len > spi_imx->rx_wml * sizeof(u32)
-   && transfer->len > spi_imx->tx_wml * sizeof(u32))
+   if (spi_imx->dma_is_inited && transfer->len > spi_imx->wml)
return true;
return false;
 }
@@ -228,6 +225,7 @@ static bool spi_imx_can_dma(struct spi_master *master, 
struct spi_device *spi,
 #define MX51_ECSPI_INT 0x10
 #define MX51_ECSPI_INT_TEEN(1 <<  0)
 #define MX51_ECSPI_INT_RREN(1 <<  3)
+#define MX51_ECSPI_INT_TCENBIT(7)
 
 #define MX51_ECSPI_DMA  0x14
 #define MX51_ECSPI_DMA_TX_WML_OFFSET   0
@@ -292,6 +290,9 @@ static void __maybe_unused mx51_ecspi_intctrl(struct 
spi_imx_data *spi_imx, int
if (enable & MXC_INT_RR)
val |= MX51_ECSPI_INT_RREN;
 
+   if (enable & MXC_INT_TCEN)
+   val |= MX51_ECSPI_INT_TCEN;
+
writel(val, spi_imx->base + MX51_ECSPI_INT);
 }
 
@@ -311,8 +312,9 @@ static void __maybe_unused mx51_ecspi_trigger(struct 
spi_imx_data *spi_imx)
 static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
struct spi_imx_config *config)
 {
-   u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0;
-   u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg;
+   u32 ctrl = MX51_ECSPI_CTRL_ENABLE, dma = 0;
+   u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
+
u32 clk = config->speed_hz, delay;
 
/*
@@ -376,19 +378,9 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
 * and enable DMA request.
 */
if (spi_imx->dma_is_inited) {
-   dma = readl(spi_imx->base + MX51_ECSPI_DMA);
-
-   spi_imx->rxt_wml = spi_imx_get_fifosize(spi_imx) / 2;
-   rx_wml_cfg = spi_imx->rx_wml << MX51_ECSPI_DMA_RX_WML_OFFSET;
-   tx_wml_cfg = spi_imx->tx_wml << MX51_ECSPI_DMA_TX_WML_OFFSET;
-   rxt_wml_cfg = spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET;
-   dma = (dma & ~MX51_ECSPI_DMA_TX_WML_MASK
-  & ~MX51_ECSPI_DMA_RX_WML_MASK
-  & ~MX51_ECSPI_DMA_RXT_WML_MASK)
-  | rx_wml_cfg | tx_wml_cfg | rxt_wml_cfg
-  |(1 << MX51_ECSPI_DMA_TEDEN_OFFSET)
-  |(1 << MX51_ECSPI_DMA_RXDEN_OFFSET)
-  |(1 << MX51_ECSPI_DMA_RXTDEN_OFFSET);
+   dma = (spi_imx->wml - 1) << MX51_ECSPI_DMA_RX_WML_OFFSET
+ | (1 << MX51_ECSPI_DMA_TEDEN_OFFSET)
+ | (1 << MX51_ECSPI_DMA_RXDEN_OFFSET);
 
writel(dma, 

[PATCH v4 3/7] spi: imx: add support for all SPI word width for DMA transfer

2015-11-27 Thread Anton Bondarenko
DMA transfer for SPI was limited to up to 8 bits word size until now.
Sync in SPI burst size and DMA bus width is necessary to correctly
support other BPW supported by HW.

Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 133 ++
 1 file changed, 102 insertions(+), 31 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 4770d81..740583a 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -89,11 +89,15 @@ struct spi_imx_data {
 
struct completion xfer_done;
void __iomem *base;
+   unsigned long base_phys;
+
struct clk *clk_per;
struct clk *clk_ipg;
unsigned long spi_clk;
unsigned int spi_bus_clk;
 
+   unsigned int bytes_per_word;
+
unsigned int count;
void (*tx)(struct spi_imx_data *);
void (*rx)(struct spi_imx_data *);
@@ -195,12 +199,31 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
return 7;
 }
 
+static int spi_imx_get_bytes_per_word(const int bpw)
+{
+   return DIV_ROUND_UP(bpw, BITS_PER_BYTE);
+}
+
 static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
 struct spi_transfer *transfer)
 {
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+   unsigned int bpw = transfer->bits_per_word;
+
+   if (!bpw)
+   bpw = spi->bits_per_word;
 
-   if (spi_imx->dma_is_inited && transfer->len > spi_imx->wml)
+   bpw = spi_imx_get_bytes_per_word(bpw);
+
+   /*
+* We need to use SPI word size in calculation to decide
+* if we want to go with DMA or PIO mode. Just a short example:
+* We need to transfer 24 SPI words with BPW == 32. This will take
+* 24 PIO writes to FIFO (and same for reads). But transfer->len will
+* be 24*4=96 bytes. WML is 32 SPI words. The decision will be incorrect
+* if we do not take into account SPI bits per word.
+*/
+   if (spi_imx->dma_is_inited && (transfer->len > spi_imx->wml * bpw))
return true;
return false;
 }
@@ -764,11 +787,60 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id)
return IRQ_HANDLED;
 }
 
+static int spi_imx_sdma_configure(struct spi_master *master)
+{
+   int ret;
+   enum dma_slave_buswidth dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE;
+   struct dma_slave_config slave_config = {};
+   struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+
+   switch (spi_imx->bytes_per_word) {
+   case 4:
+   dsb_default = DMA_SLAVE_BUSWIDTH_4_BYTES;
+   break;
+   case 2:
+   dsb_default = DMA_SLAVE_BUSWIDTH_2_BYTES;
+   break;
+   case 1:
+   dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE;
+   break;
+   default:
+   pr_err("Not supported word size %d\n", spi_imx->bytes_per_word);
+   ret = -EINVAL;
+   goto err;
+   }
+
+   slave_config.direction = DMA_MEM_TO_DEV;
+   slave_config.dst_addr = spi_imx->base_phys + MXC_CSPITXDATA;
+   slave_config.dst_addr_width = dsb_default;
+   slave_config.dst_maxburst = spi_imx->wml;
+   ret = dmaengine_slave_config(master->dma_tx, _config);
+   if (ret) {
+   pr_err("error in TX dma configuration.\n");
+   goto err;
+   }
+
+   memset(_config, 0, sizeof(slave_config));
+
+   slave_config.direction = DMA_DEV_TO_MEM;
+   slave_config.src_addr = spi_imx->base_phys + MXC_CSPIRXDATA;
+   slave_config.src_addr_width = dsb_default;
+   slave_config.src_maxburst = spi_imx->wml;
+   ret = dmaengine_slave_config(master->dma_rx, _config);
+   if (ret)
+   pr_err("error in RX dma configuration.\n");
+
+err:
+   return ret;
+}
+
 static int spi_imx_setupxfer(struct spi_device *spi,
 struct spi_transfer *t)
 {
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
struct spi_imx_config config;
+   unsigned int new_bytes_per_word;
+   int ret = 0;
 
config.bpw = t ? t->bits_per_word : spi->bits_per_word;
config.speed_hz  = t ? t->speed_hz : spi->max_speed_hz;
@@ -792,9 +864,19 @@ static int spi_imx_setupxfer(struct spi_device *spi,
spi_imx->tx = spi_imx_buf_tx_u32;
}
 
-   spi_imx->devtype_data->config(spi_imx, );
+   new_bytes_per_word = spi_imx_get_bytes_per_word(config.bpw);
+   if (spi_imx->dma_is_inited &&
+   spi_imx->bytes_per_word != new_bytes_per_word) {
+   spi_imx->bytes_per_word = new_bytes_per_word;
+   ret = spi_imx_sdma_configure(spi->master);
+   if (ret != 0)
+   pr_err("C

[PATCH v4 0/7] Improvements for SPI IMX driver for Freescale IMX51, IMX53 and IMX6

2015-11-27 Thread Anton Bondarenko
A number of patches to impove or add the implementation
for the spi-imx driver related to Freescale IMX51, 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.

Changes since V3:
 Addressed comments from V3 review, simplified timeout calculation

Anton Bondarenko (7):
  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 function to check for IMX51 family controller
  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

 drivers/spi/spi-imx.c | 320 +-
 1 file changed, 237 insertions(+), 83 deletions(-)

-- 
2.6.3

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


[PATCH v4 4/7] spi: imx: add function to check for IMX51 family controller

2015-11-27 Thread Anton Bondarenko
Similar to other controller type checks add check function for
IMX51. This also includes IMX53 and IMX6.

Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 740583a..4cd8550 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -127,9 +127,14 @@ static inline int is_imx35_cspi(struct spi_imx_data *d)
return d->devtype_data->devtype == IMX35_CSPI;
 }
 
+static inline int is_imx51_ecspi(struct spi_imx_data *d)
+{
+   return d->devtype_data->devtype == IMX51_ECSPI;
+}
+
 static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d)
 {
-   return (d->devtype_data->devtype == IMX51_ECSPI) ? 64 : 8;
+   return is_imx51_ecspi(d) ? 64 : 8;
 }
 
 #define MXC_SPI_BUF_RX(type)   \
@@ -1321,7 +1326,7 @@ static int spi_imx_probe(struct platform_device *pdev)
 * Only validated on i.mx6 now, can remove the constrain if validated on
 * other chips.
 */
-   if (spi_imx->devtype_data == _ecspi_devtype_data &&
+   if (is_imx51_ecspi(spi_imx) &&
spi_imx_sdma_init(>dev, spi_imx, master))
dev_err(>dev, "dma setup error,use pio instead\n");
 
-- 
2.6.3

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


[PATCH v4 2/7] spi: imx: replace fixed timeout with calculated one

2015-11-27 Thread Anton Bondarenko
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 
---
 drivers/spi/spi-imx.c | 36 
 1 file changed, 28 insertions(+), 8 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index bd7b721..4770d81 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -57,7 +57,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;
@@ -93,6 +92,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 *);
@@ -314,8 +314,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
@@ -327,7 +326,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, );
+   spi_imx->spi_bus_clk = config->speed_hz;
+   ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz,
+ _imx->spi_bus_clk);
 
/* set chip select to use */
ctrl |= MX51_ECSPI_CTRL_CS(config->cs);
@@ -367,7 +368,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 * 100) / 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 */
@@ -890,12 +891,27 @@ static void spi_imx_dma_tx_callback(void *cookie)
complete(_imx->dma_tx_completion);
 }
 
+static int spi_imx_calculate_timeout(struct spi_imx_data *spi_imx, int size)
+{
+   unsigned long timeout = 0;
+
+   /* Time with actual data transfer and CS change delay related to HW */
+   timeout = (8 + 4) * size / spi_imx->spi_bus_clk;
+
+   /* Add extra second for scheduler related activities */
+   timeout += 1;
+
+   /* Double calculated timeout */
+   return msecs_to_jiffies(2 * timeout * MSEC_PER_SEC);
+}
+
 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 = >tx_sg, *rx = >rx_sg;
@@ -956,9 +972,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(_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(>dev),
@@ -966,8 +984,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);
timeout = wait_for_completion_timeout(
-   _imx->dma_rx_completion, IMX_DMA_TIMEOUT);
+   _imx->dma_rx_completion, transfer_timeout);
if (!timeout) {
pr_warn("%s %s: I/O Error in DMA RX\n",
dev_driver_string(>dev),
@@ -989,7 +1009,7 @@ static int spi_imx_d

[PATCH v4 7/7] spi: imx: defer spi initialization, if DMA engine is pending

2015-11-27 Thread Anton Bondarenko
If SPI device supports DMA mode, but DMA controller is not yet
available due to e.g. a delay in the corresponding kernel module
initialization, retry to initialize SPI driver later on instead of
falling back into PIO only mode.

Signed-off-by: Vladimir Zapolskiy 
Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index aaa32c2..c2edd0f 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -1341,9 +1341,15 @@ static int spi_imx_probe(struct platform_device *pdev)
 * Only validated on i.mx6 now, can remove the constrain if validated on
 * other chips.
 */
-   if (is_imx51_ecspi(spi_imx) &&
-   spi_imx_sdma_init(>dev, spi_imx, master))
-   dev_err(>dev, "dma setup error,use pio instead\n");
+   if (is_imx51_ecspi(spi_imx)) {
+   ret = spi_imx_sdma_init(>dev, spi_imx, master);
+   if (ret == -EPROBE_DEFER)
+   goto out_clk_put;
+
+   if (ret < 0)
+   dev_err(>dev, "dma setup error %d, use pio\n",
+   ret);
+   }
 
spi_imx->devtype_data->reset(spi_imx);
 
-- 
2.6.3

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


[PATCH v4 6/7] spi: imx: return error from dma channel request

2015-11-27 Thread Anton Bondarenko
On SDMA initialization return exactly the same error, which is
reported by dma_request_slave_channel_reason(), it is a preceding
change to defer SPI DMA initialization, if SDMA module is not yet
available.

Signed-off-by: Vladimir Zapolskiy 
Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 18 ++
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index f556eaa..aaa32c2 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -923,18 +923,20 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2;
 
/* Prepare for TX DMA: */
-   master->dma_tx = dma_request_slave_channel(dev, "tx");
-   if (!master->dma_tx) {
-   dev_err(dev, "cannot get the TX DMA channel!\n");
-   ret = -EINVAL;
+   master->dma_tx = dma_request_slave_channel_reason(dev, "tx");
+   if (IS_ERR(master->dma_tx)) {
+   dev_info(dev, "cannot get the TX DMA channel!\n");
+   ret = PTR_ERR(master->dma_tx);
+   master->dma_tx = NULL;
goto err;
}
 
/* Prepare for RX : */
-   master->dma_rx = dma_request_slave_channel(dev, "rx");
-   if (!master->dma_rx) {
-   dev_dbg(dev, "cannot get the DMA channel.\n");
-   ret = -EINVAL;
+   master->dma_rx = dma_request_slave_channel_reason(dev, "rx");
+   if (IS_ERR(master->dma_rx)) {
+   dev_info(dev, "cannot get the DMA channel.\n");
+   ret = PTR_ERR(master->dma_rx);
+   master->dma_rx = NULL;
goto err;
}
 
-- 
2.6.3

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


[PATCH v4 5/7] spi: imx: Add support for loopback for ECSPI controllers

2015-11-27 Thread Anton Bondarenko
Support for ECSPI loopback for IMX51,IMX53 and IMX6Q using TEST register.

Signed-off-by: Mohsin Kazmi 
Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 4cd8550..f556eaa 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -270,6 +270,9 @@ static bool spi_imx_can_dma(struct spi_master *master, 
struct spi_device *spi,
 #define MX51_ECSPI_STAT0x18
 #define MX51_ECSPI_STAT_RR (1 <<  3)
 
+#define MX51_ECSPI_TEST0x20
+#define MX51_ECSPI_LOOPBIT(31)
+
 /* MX51 eCSPI */
 static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi,
  unsigned int *fres)
@@ -343,6 +346,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
@@ -385,6 +389,12 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
 
+   if (config->mode & SPI_LOOP)
+   lpb |= MX51_ECSPI_LOOP;
+
+   if ((readl(spi_imx->base + MX51_ECSPI_TEST) & MX51_ECSPI_LOOP) != lpb)
+   writel(lpb, spi_imx->base + MX51_ECSPI_TEST);
+
/*
 * Wait until the changes in the configuration register CONFIGREG
 * propagate into the hardware. It takes exactly one tick of the
@@ -1249,6 +1259,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)
@@ -1275,10 +1288,10 @@ static int spi_imx_probe(struct platform_device *pdev)
spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 
-   init_completion(_imx->xfer_done);
+   if (is_imx51_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(_imx->xfer_done);
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
spi_imx->base = devm_ioremap_resource(>dev, res);
-- 
2.6.3

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


[PATCH v4 3/7] spi: imx: add support for all SPI word width for DMA transfer

2015-11-27 Thread Anton Bondarenko
DMA transfer for SPI was limited to up to 8 bits word size until now.
Sync in SPI burst size and DMA bus width is necessary to correctly
support other BPW supported by HW.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 133 ++
 1 file changed, 102 insertions(+), 31 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 4770d81..740583a 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -89,11 +89,15 @@ struct spi_imx_data {
 
struct completion xfer_done;
void __iomem *base;
+   unsigned long base_phys;
+
struct clk *clk_per;
struct clk *clk_ipg;
unsigned long spi_clk;
unsigned int spi_bus_clk;
 
+   unsigned int bytes_per_word;
+
unsigned int count;
void (*tx)(struct spi_imx_data *);
void (*rx)(struct spi_imx_data *);
@@ -195,12 +199,31 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
return 7;
 }
 
+static int spi_imx_get_bytes_per_word(const int bpw)
+{
+   return DIV_ROUND_UP(bpw, BITS_PER_BYTE);
+}
+
 static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
 struct spi_transfer *transfer)
 {
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+   unsigned int bpw = transfer->bits_per_word;
+
+   if (!bpw)
+   bpw = spi->bits_per_word;
 
-   if (spi_imx->dma_is_inited && transfer->len > spi_imx->wml)
+   bpw = spi_imx_get_bytes_per_word(bpw);
+
+   /*
+* We need to use SPI word size in calculation to decide
+* if we want to go with DMA or PIO mode. Just a short example:
+* We need to transfer 24 SPI words with BPW == 32. This will take
+* 24 PIO writes to FIFO (and same for reads). But transfer->len will
+* be 24*4=96 bytes. WML is 32 SPI words. The decision will be incorrect
+* if we do not take into account SPI bits per word.
+*/
+   if (spi_imx->dma_is_inited && (transfer->len > spi_imx->wml * bpw))
return true;
return false;
 }
@@ -764,11 +787,60 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id)
return IRQ_HANDLED;
 }
 
+static int spi_imx_sdma_configure(struct spi_master *master)
+{
+   int ret;
+   enum dma_slave_buswidth dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE;
+   struct dma_slave_config slave_config = {};
+   struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+
+   switch (spi_imx->bytes_per_word) {
+   case 4:
+   dsb_default = DMA_SLAVE_BUSWIDTH_4_BYTES;
+   break;
+   case 2:
+   dsb_default = DMA_SLAVE_BUSWIDTH_2_BYTES;
+   break;
+   case 1:
+   dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE;
+   break;
+   default:
+   pr_err("Not supported word size %d\n", spi_imx->bytes_per_word);
+   ret = -EINVAL;
+   goto err;
+   }
+
+   slave_config.direction = DMA_MEM_TO_DEV;
+   slave_config.dst_addr = spi_imx->base_phys + MXC_CSPITXDATA;
+   slave_config.dst_addr_width = dsb_default;
+   slave_config.dst_maxburst = spi_imx->wml;
+   ret = dmaengine_slave_config(master->dma_tx, _config);
+   if (ret) {
+   pr_err("error in TX dma configuration.\n");
+   goto err;
+   }
+
+   memset(_config, 0, sizeof(slave_config));
+
+   slave_config.direction = DMA_DEV_TO_MEM;
+   slave_config.src_addr = spi_imx->base_phys + MXC_CSPIRXDATA;
+   slave_config.src_addr_width = dsb_default;
+   slave_config.src_maxburst = spi_imx->wml;
+   ret = dmaengine_slave_config(master->dma_rx, _config);
+   if (ret)
+   pr_err("error in RX dma configuration.\n");
+
+err:
+   return ret;
+}
+
 static int spi_imx_setupxfer(struct spi_device *spi,
 struct spi_transfer *t)
 {
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
struct spi_imx_config config;
+   unsigned int new_bytes_per_word;
+   int ret = 0;
 
config.bpw = t ? t->bits_per_word : spi->bits_per_word;
config.speed_hz  = t ? t->speed_hz : spi->max_speed_hz;
@@ -792,9 +864,19 @@ static int spi_imx_setupxfer(struct spi_device *spi,
spi_imx->tx = spi_imx_buf_tx_u32;
}
 
-   spi_imx->devtype_data->config(spi_imx, );
+   new_bytes_per_word = spi_imx_get_bytes_per_word(config.bpw);
+   if (spi_imx->dma_is_inited &&
+   spi_imx->bytes_per_word != new_bytes_per_word) {
+   spi_imx->bytes_per_word = new_bytes_per_word;
+   ret = spi_imx_sdma_configure(spi->master);
+   if (ret != 0)
+

[PATCH v4 1/7] spi: imx: Fix DMA transfer

2015-11-27 Thread Anton Bondarenko
RX DMA tail data handling doesn't work correctly in many cases with
current implementation. It happens because SPI core was setup
to generates both RX watermark level and RX DATA TAIL events
incorrectly. SPI transfer triggering for DMA also done in wrong way.

SPI client wants to transfer 70 words for example. The old DMA
implementation setup RX DATA TAIL equal 6 words. In this case
RX DMA event will be generated after 6 words read from RX FIFO.
The garbage can be read out from RX FIFO because SPI HW does
not receive all required words to trigger RX watermark event.

New implementation change handling of RX data tail. DMA is used to process
all TX data and only full chunks of RX data with size aligned to FIFO/2.
Driver is waiting until both TX and RX DMA transaction done and all
TX data are pushed out. At that moment there is only RX data tail in
the RX FIFO. This data read out using PIO.

Transfer triggering changed to avoid RX data loss.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 115 +-
 1 file changed, 76 insertions(+), 39 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 0e5723a..bd7b721 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -53,6 +53,7 @@
 /* generic defines to abstract from the different register layouts */
 #define MXC_INT_RR (1 << 0) /* Receive data ready interrupt */
 #define MXC_INT_TE (1 << 1) /* Transmit FIFO empty interrupt */
+#define MXC_INT_TCEN   BIT(7)   /* Transfer complete */
 
 /* The maximum  bytes that a sdma BD can transfer.*/
 #define MAX_SDMA_BD_BYTES  (1 << 15)
@@ -104,9 +105,7 @@ struct spi_imx_data {
unsigned int dma_is_inited;
unsigned int dma_finished;
bool usedma;
-   u32 rx_wml;
-   u32 tx_wml;
-   u32 rxt_wml;
+   u32 wml;
struct completion dma_rx_completion;
struct completion dma_tx_completion;
 
@@ -201,9 +200,7 @@ static bool spi_imx_can_dma(struct spi_master *master, 
struct spi_device *spi,
 {
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
 
-   if (spi_imx->dma_is_inited
-   && transfer->len > spi_imx->rx_wml * sizeof(u32)
-   && transfer->len > spi_imx->tx_wml * sizeof(u32))
+   if (spi_imx->dma_is_inited && transfer->len > spi_imx->wml)
return true;
return false;
 }
@@ -228,6 +225,7 @@ static bool spi_imx_can_dma(struct spi_master *master, 
struct spi_device *spi,
 #define MX51_ECSPI_INT 0x10
 #define MX51_ECSPI_INT_TEEN(1 <<  0)
 #define MX51_ECSPI_INT_RREN(1 <<  3)
+#define MX51_ECSPI_INT_TCENBIT(7)
 
 #define MX51_ECSPI_DMA  0x14
 #define MX51_ECSPI_DMA_TX_WML_OFFSET   0
@@ -292,6 +290,9 @@ static void __maybe_unused mx51_ecspi_intctrl(struct 
spi_imx_data *spi_imx, int
if (enable & MXC_INT_RR)
val |= MX51_ECSPI_INT_RREN;
 
+   if (enable & MXC_INT_TCEN)
+   val |= MX51_ECSPI_INT_TCEN;
+
writel(val, spi_imx->base + MX51_ECSPI_INT);
 }
 
@@ -311,8 +312,9 @@ static void __maybe_unused mx51_ecspi_trigger(struct 
spi_imx_data *spi_imx)
 static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
struct spi_imx_config *config)
 {
-   u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0;
-   u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg;
+   u32 ctrl = MX51_ECSPI_CTRL_ENABLE, dma = 0;
+   u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
+
u32 clk = config->speed_hz, delay;
 
/*
@@ -376,19 +378,9 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
 * and enable DMA request.
 */
if (spi_imx->dma_is_inited) {
-   dma = readl(spi_imx->base + MX51_ECSPI_DMA);
-
-   spi_imx->rxt_wml = spi_imx_get_fifosize(spi_imx) / 2;
-   rx_wml_cfg = spi_imx->rx_wml << MX51_ECSPI_DMA_RX_WML_OFFSET;
-   tx_wml_cfg = spi_imx->tx_wml << MX51_ECSPI_DMA_TX_WML_OFFSET;
-   rxt_wml_cfg = spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET;
-   dma = (dma & ~MX51_ECSPI_DMA_TX_WML_MASK
-  & ~MX51_ECSPI_DMA_RX_WML_MASK
-  & ~MX51_ECSPI_DMA_RXT_WML_MASK)
-  | rx_wml_cfg | tx_wml_cfg | rxt_wml_cfg
-  |(1 << MX51_ECSPI_DMA_TEDEN_OFFSET)
-  |(1 << MX51_ECSPI_DMA_RXDEN_OFFSET)
-  |(1 << MX51_ECSPI_DMA_RXTDEN_OFFSET);
+   dma = (spi_imx->wml - 1) << MX51_ECSPI_DMA_RX_WML_OFFSET
+ | (1 << MX51_ECSPI_DMA_TEDEN_OFFSET)
+ | (1 << MX51

[PATCH v4 0/7] Improvements for SPI IMX driver for Freescale IMX51, IMX53 and IMX6

2015-11-27 Thread Anton Bondarenko
A number of patches to impove or add the implementation
for the spi-imx driver related to Freescale IMX51, 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.

Changes since V3:
 Addressed comments from V3 review, simplified timeout calculation

Anton Bondarenko (7):
  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 function to check for IMX51 family controller
  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

 drivers/spi/spi-imx.c | 320 +-
 1 file changed, 237 insertions(+), 83 deletions(-)

-- 
2.6.3

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


[PATCH v4 4/7] spi: imx: add function to check for IMX51 family controller

2015-11-27 Thread Anton Bondarenko
Similar to other controller type checks add check function for
IMX51. This also includes IMX53 and IMX6.

Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 740583a..4cd8550 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -127,9 +127,14 @@ static inline int is_imx35_cspi(struct spi_imx_data *d)
return d->devtype_data->devtype == IMX35_CSPI;
 }
 
+static inline int is_imx51_ecspi(struct spi_imx_data *d)
+{
+   return d->devtype_data->devtype == IMX51_ECSPI;
+}
+
 static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d)
 {
-   return (d->devtype_data->devtype == IMX51_ECSPI) ? 64 : 8;
+   return is_imx51_ecspi(d) ? 64 : 8;
 }
 
 #define MXC_SPI_BUF_RX(type)   \
@@ -1321,7 +1326,7 @@ static int spi_imx_probe(struct platform_device *pdev)
 * Only validated on i.mx6 now, can remove the constrain if validated on
 * other chips.
 */
-   if (spi_imx->devtype_data == _ecspi_devtype_data &&
+   if (is_imx51_ecspi(spi_imx) &&
spi_imx_sdma_init(>dev, spi_imx, master))
dev_err(>dev, "dma setup error,use pio instead\n");
 
-- 
2.6.3

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


[PATCH v4 2/7] spi: imx: replace fixed timeout with calculated one

2015-11-27 Thread Anton Bondarenko
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.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 36 
 1 file changed, 28 insertions(+), 8 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index bd7b721..4770d81 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -57,7 +57,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;
@@ -93,6 +92,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 *);
@@ -314,8 +314,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
@@ -327,7 +326,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, );
+   spi_imx->spi_bus_clk = config->speed_hz;
+   ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz,
+ _imx->spi_bus_clk);
 
/* set chip select to use */
ctrl |= MX51_ECSPI_CTRL_CS(config->cs);
@@ -367,7 +368,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 * 100) / 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 */
@@ -890,12 +891,27 @@ static void spi_imx_dma_tx_callback(void *cookie)
complete(_imx->dma_tx_completion);
 }
 
+static int spi_imx_calculate_timeout(struct spi_imx_data *spi_imx, int size)
+{
+   unsigned long timeout = 0;
+
+   /* Time with actual data transfer and CS change delay related to HW */
+   timeout = (8 + 4) * size / spi_imx->spi_bus_clk;
+
+   /* Add extra second for scheduler related activities */
+   timeout += 1;
+
+   /* Double calculated timeout */
+   return msecs_to_jiffies(2 * timeout * MSEC_PER_SEC);
+}
+
 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 = >tx_sg, *rx = >rx_sg;
@@ -956,9 +972,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(_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(>dev),
@@ -966,8 +984,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);
timeout = wait_for_completion_timeout(
-   _imx->dma_rx_completion, IMX_DMA_TIMEOUT);
+   _imx->dma_rx_completion, transfer_timeout);
if (!timeout) {
pr_warn("%s %s: I/O Error in DMA RX\n",
dev_driver_string(>dev),
@@ -

[PATCH v4 5/7] spi: imx: Add support for loopback for ECSPI controllers

2015-11-27 Thread Anton Bondarenko
Support for ECSPI loopback for IMX51,IMX53 and IMX6Q using TEST register.

Signed-off-by: Mohsin Kazmi <mohsin_ka...@mentor.com>
Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 4cd8550..f556eaa 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -270,6 +270,9 @@ static bool spi_imx_can_dma(struct spi_master *master, 
struct spi_device *spi,
 #define MX51_ECSPI_STAT0x18
 #define MX51_ECSPI_STAT_RR (1 <<  3)
 
+#define MX51_ECSPI_TEST0x20
+#define MX51_ECSPI_LOOPBIT(31)
+
 /* MX51 eCSPI */
 static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi,
  unsigned int *fres)
@@ -343,6 +346,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
@@ -385,6 +389,12 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
 
+   if (config->mode & SPI_LOOP)
+   lpb |= MX51_ECSPI_LOOP;
+
+   if ((readl(spi_imx->base + MX51_ECSPI_TEST) & MX51_ECSPI_LOOP) != lpb)
+   writel(lpb, spi_imx->base + MX51_ECSPI_TEST);
+
/*
 * Wait until the changes in the configuration register CONFIGREG
 * propagate into the hardware. It takes exactly one tick of the
@@ -1249,6 +1259,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)
@@ -1275,10 +1288,10 @@ static int spi_imx_probe(struct platform_device *pdev)
spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 
-   init_completion(_imx->xfer_done);
+   if (is_imx51_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(_imx->xfer_done);
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
spi_imx->base = devm_ioremap_resource(>dev, res);
-- 
2.6.3

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


[PATCH v4 7/7] spi: imx: defer spi initialization, if DMA engine is pending

2015-11-27 Thread Anton Bondarenko
If SPI device supports DMA mode, but DMA controller is not yet
available due to e.g. a delay in the corresponding kernel module
initialization, retry to initialize SPI driver later on instead of
falling back into PIO only mode.

Signed-off-by: Vladimir Zapolskiy <vladimir_zapols...@mentor.com>
Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index aaa32c2..c2edd0f 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -1341,9 +1341,15 @@ static int spi_imx_probe(struct platform_device *pdev)
 * Only validated on i.mx6 now, can remove the constrain if validated on
 * other chips.
 */
-   if (is_imx51_ecspi(spi_imx) &&
-   spi_imx_sdma_init(>dev, spi_imx, master))
-   dev_err(>dev, "dma setup error,use pio instead\n");
+   if (is_imx51_ecspi(spi_imx)) {
+   ret = spi_imx_sdma_init(>dev, spi_imx, master);
+   if (ret == -EPROBE_DEFER)
+   goto out_clk_put;
+
+   if (ret < 0)
+   dev_err(>dev, "dma setup error %d, use pio\n",
+   ret);
+   }
 
spi_imx->devtype_data->reset(spi_imx);
 
-- 
2.6.3

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


[PATCH v4 6/7] spi: imx: return error from dma channel request

2015-11-27 Thread Anton Bondarenko
On SDMA initialization return exactly the same error, which is
reported by dma_request_slave_channel_reason(), it is a preceding
change to defer SPI DMA initialization, if SDMA module is not yet
available.

Signed-off-by: Vladimir Zapolskiy <vladimir_zapols...@mentor.com>
Signed-off-by: Anton Bondarenko <anton.bondarenko.s...@gmail.com>
---
 drivers/spi/spi-imx.c | 18 ++
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index f556eaa..aaa32c2 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -923,18 +923,20 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2;
 
/* Prepare for TX DMA: */
-   master->dma_tx = dma_request_slave_channel(dev, "tx");
-   if (!master->dma_tx) {
-   dev_err(dev, "cannot get the TX DMA channel!\n");
-   ret = -EINVAL;
+   master->dma_tx = dma_request_slave_channel_reason(dev, "tx");
+   if (IS_ERR(master->dma_tx)) {
+   dev_info(dev, "cannot get the TX DMA channel!\n");
+   ret = PTR_ERR(master->dma_tx);
+   master->dma_tx = NULL;
goto err;
}
 
/* Prepare for RX : */
-   master->dma_rx = dma_request_slave_channel(dev, "rx");
-   if (!master->dma_rx) {
-   dev_dbg(dev, "cannot get the DMA channel.\n");
-   ret = -EINVAL;
+   master->dma_rx = dma_request_slave_channel_reason(dev, "rx");
+   if (IS_ERR(master->dma_rx)) {
+   dev_info(dev, "cannot get the DMA channel.\n");
+   ret = PTR_ERR(master->dma_rx);
+   master->dma_rx = NULL;
goto err;
}
 
-- 
2.6.3

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


Re: [PATCH 3/8] Documentation/spi/spidev_test.c: accept input from a file

2015-11-17 Thread Anton Bondarenko

On 17.11.2015 16:24, Joshua Clayton wrote:

Add input file support to facilitate testing larger data.

Signed-off-by: Joshua Clayton 
---
  Documentation/spi/spidev_test.c | 42 -
  1 file changed, 41 insertions(+), 1 deletion(-)

diff --git a/Documentation/spi/spidev_test.c b/Documentation/spi/spidev_test.c
index 1ed9110..ef812ad 100644
--- a/Documentation/spi/spidev_test.c
+++ b/Documentation/spi/spidev_test.c
@@ -19,6 +19,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 

@@ -33,6 +34,7 @@ static void pabort(const char *s)
  static const char *device = "/dev/spidev1.1";
  static uint32_t mode;
  static uint8_t bits = 8;
+static char *input_file;
  static uint32_t speed = 50;
  static uint16_t delay;
  static int verbose;
@@ -144,6 +146,7 @@ static void print_usage(const char *prog)
 "  -s --speedmax speed (Hz)\n"
 "  -d --delaydelay (usec)\n"
 "  -b --bpw  bits per word \n"
+"  -i --inputinput data from a file (e.g. \"test.bin\")\n"
 "  -l --loop loopback\n"
 "  -H --cpha clock phase\n"
 "  -O --cpol clock polarity\n"
@@ -167,6 +170,7 @@ static void parse_opts(int argc, char *argv[])
{ "speed",   1, 0, 's' },
{ "delay",   1, 0, 'd' },
{ "bpw", 1, 0, 'b' },
+   { "input",   1, 0, 'i' },
{ "loop",0, 0, 'l' },
{ "cpha",0, 0, 'H' },
{ "cpol",0, 0, 'O' },
@@ -182,7 +186,8 @@ static void parse_opts(int argc, char *argv[])
};
int c;

-   c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR24p:v", lopts, 
NULL);
+   c = getopt_long(argc, argv, "D:s:d:b:i:lHOLC3NR24p:v",
+   lopts, NULL);

if (c == -1)
break;
@@ -200,6 +205,9 @@ static void parse_opts(int argc, char *argv[])
case 'b':
bits = atoi(optarg);
break;
+   case 'i':
+   input_file = optarg;
+   break;
case 'l':
mode |= SPI_LOOP;
break;
@@ -259,6 +267,33 @@ static void transfer_escaped_string(int fd, char *str)
free(tx);
  }

+static void transfer_file(int fd, char *filename)
+{
+   ssize_t bytes;
+   struct stat sb;
+   int tx_fd;
+   uint8_t *tx;
+
+   if (stat(filename, ) == -1)
+   pabort("can't stat input file");
+
+   if (sb.st_size > 4096)
+   pabort("input file exceeds spidev's 4k limit");
This is not a true. IIRC PAGE_SIZE is the default buffer size for 
spidev, but can be changed using bufsiz module parameter.

Just 'insmod spidev bufsiz=X', where X is number of bytes.

+
+   tx_fd = open(filename, O_RDONLY);
+   if (fd < 0)
+   pabort("can't open input file");
+
+   tx = malloc(sb.st_size);

It would be good to check new allocations for fail.

+   bytes = read(tx_fd, tx, sb.st_size);
+   if (bytes != sb.st_size)
+   pabort("failed to read input file");
+
+   transfer(fd, tx, sb.st_size);
+   free(tx);
+   close(tx_fd);
+}
+
  int main(int argc, char *argv[])
  {
int ret = 0;
@@ -307,8 +342,13 @@ int main(int argc, char *argv[])
printf("bits per word: %d\n", bits);
printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);

+   if (input_tx && input_file)
+   pabort("only one of -p and --input may be selected");
+
if (input_tx)
transfer_escaped_string(fd, input_tx);
+   else if (input_file)
+   transfer_file(fd, input_file);
else
transfer(fd, default_tx, sizeof(default_tx));



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


Re: [PATCH 3/8] Documentation/spi/spidev_test.c: accept input from a file

2015-11-17 Thread Anton Bondarenko

On 17.11.2015 16:24, Joshua Clayton wrote:

Add input file support to facilitate testing larger data.

Signed-off-by: Joshua Clayton 
---
  Documentation/spi/spidev_test.c | 42 -
  1 file changed, 41 insertions(+), 1 deletion(-)

diff --git a/Documentation/spi/spidev_test.c b/Documentation/spi/spidev_test.c
index 1ed9110..ef812ad 100644
--- a/Documentation/spi/spidev_test.c
+++ b/Documentation/spi/spidev_test.c
@@ -19,6 +19,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 

@@ -33,6 +34,7 @@ static void pabort(const char *s)
  static const char *device = "/dev/spidev1.1";
  static uint32_t mode;
  static uint8_t bits = 8;
+static char *input_file;
  static uint32_t speed = 50;
  static uint16_t delay;
  static int verbose;
@@ -144,6 +146,7 @@ static void print_usage(const char *prog)
 "  -s --speedmax speed (Hz)\n"
 "  -d --delaydelay (usec)\n"
 "  -b --bpw  bits per word \n"
+"  -i --inputinput data from a file (e.g. \"test.bin\")\n"
 "  -l --loop loopback\n"
 "  -H --cpha clock phase\n"
 "  -O --cpol clock polarity\n"
@@ -167,6 +170,7 @@ static void parse_opts(int argc, char *argv[])
{ "speed",   1, 0, 's' },
{ "delay",   1, 0, 'd' },
{ "bpw", 1, 0, 'b' },
+   { "input",   1, 0, 'i' },
{ "loop",0, 0, 'l' },
{ "cpha",0, 0, 'H' },
{ "cpol",0, 0, 'O' },
@@ -182,7 +186,8 @@ static void parse_opts(int argc, char *argv[])
};
int c;

-   c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR24p:v", lopts, 
NULL);
+   c = getopt_long(argc, argv, "D:s:d:b:i:lHOLC3NR24p:v",
+   lopts, NULL);

if (c == -1)
break;
@@ -200,6 +205,9 @@ static void parse_opts(int argc, char *argv[])
case 'b':
bits = atoi(optarg);
break;
+   case 'i':
+   input_file = optarg;
+   break;
case 'l':
mode |= SPI_LOOP;
break;
@@ -259,6 +267,33 @@ static void transfer_escaped_string(int fd, char *str)
free(tx);
  }

+static void transfer_file(int fd, char *filename)
+{
+   ssize_t bytes;
+   struct stat sb;
+   int tx_fd;
+   uint8_t *tx;
+
+   if (stat(filename, ) == -1)
+   pabort("can't stat input file");
+
+   if (sb.st_size > 4096)
+   pabort("input file exceeds spidev's 4k limit");
This is not a true. IIRC PAGE_SIZE is the default buffer size for 
spidev, but can be changed using bufsiz module parameter.

Just 'insmod spidev bufsiz=X', where X is number of bytes.

+
+   tx_fd = open(filename, O_RDONLY);
+   if (fd < 0)
+   pabort("can't open input file");
+
+   tx = malloc(sb.st_size);

It would be good to check new allocations for fail.

+   bytes = read(tx_fd, tx, sb.st_size);
+   if (bytes != sb.st_size)
+   pabort("failed to read input file");
+
+   transfer(fd, tx, sb.st_size);
+   free(tx);
+   close(tx_fd);
+}
+
  int main(int argc, char *argv[])
  {
int ret = 0;
@@ -307,8 +342,13 @@ int main(int argc, char *argv[])
printf("bits per word: %d\n", bits);
printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);

+   if (input_tx && input_file)
+   pabort("only one of -p and --input may be selected");
+
if (input_tx)
transfer_escaped_string(fd, input_tx);
+   else if (input_file)
+   transfer_file(fd, input_file);
else
transfer(fd, default_tx, sizeof(default_tx));



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


Re: [PATCH v3 3/7] spi: imx: add support for all SPI word width for DMA transfer

2015-11-14 Thread Anton Bondarenko



On 01.11.2015 15:41, Anton Bondarenko wrote:

From: Anton Bondarenko 

DMA transfer for SPI was limited to up to 8 bits word size until now.
Sync in SPI burst size and DMA bus width is necessary to correctly
support other BPW supported by HW.

Signed-off-by: Anton Bondarenko 
---
  drivers/spi/spi-imx.c | 133 ++
  1 file changed, 102 insertions(+), 31 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 9b80c7f..06f52c3 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -89,11 +89,15 @@ struct spi_imx_data {

struct completion xfer_done;
void __iomem *base;
+   unsigned long base_phys;
+
struct clk *clk_per;
struct clk *clk_ipg;
unsigned long spi_clk;
unsigned int spi_bus_clk;

+   unsigned int bytes_per_word;
+
unsigned int count;
void (*tx)(struct spi_imx_data *);
void (*rx)(struct spi_imx_data *);
@@ -195,12 +199,31 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
return 7;
  }

+static int spi_imx_get_bytes_per_word(const int bpw)
+{
+   return DIV_ROUND_UP(bpw, BITS_PER_BYTE);
+}
+
  static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
 struct spi_transfer *transfer)
  {
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+   unsigned int bpw = transfer->bits_per_word;
+
+   if (!bpw)
+   bpw = spi->bits_per_word;

-   if (spi_imx->dma_is_inited && transfer->len > spi_imx->wml)
+   bpw = spi_imx_get_bytes_per_word(bpw);
+
+   /*
+* We need to use SPI word size in calculation to decide
+* if we want to go with DMA or PIO mode. Just a short example:
+* We need to transfer 24 SPI words with BPW == 32. This will take
+* 24 PIO writes to FIFO (and same for reads). But transfer->len will
+* be 24*4=96 bytes. WML is 32 SPI words. The decision will be incorrect
+* if we do not take into account SPI bits per word.
+*/
+   if (spi_imx->dma_is_inited && (transfer->len > spi_imx->wml * bpw))
return true;
return false;
  }
@@ -764,11 +787,60 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id)
return IRQ_HANDLED;
  }

+static int spi_imx_sdma_configure(struct spi_master *master)
+{
+   int ret;
+   enum dma_slave_buswidth dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE;
+   struct dma_slave_config slave_config = {};
+   struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+
+   switch (spi_imx->bytes_per_word) {
+   case 4:
+   dsb_default = DMA_SLAVE_BUSWIDTH_4_BYTES;
+   break;
+   case 2:
+   dsb_default = DMA_SLAVE_BUSWIDTH_2_BYTES;
+   break;
+   case 1:
+   dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE;
+   break;
+   default:
+   pr_err("Not supported word size %d\n", spi_imx->bytes_per_word);
+   ret = -EINVAL;
+   goto err;
+   }
+
+   slave_config.direction = DMA_MEM_TO_DEV;
+   slave_config.dst_addr = spi_imx->base_phys + MXC_CSPITXDATA;
+   slave_config.dst_addr_width = dsb_default;
+   slave_config.dst_maxburst = spi_imx->wml;
+   ret = dmaengine_slave_config(master->dma_tx, _config);
+   if (ret) {
+   pr_err("error in TX dma configuration.\n");
+   goto err;
+   }
+
+   memset(_config, 0, sizeof(slave_config));
+
+   slave_config.direction = DMA_DEV_TO_MEM;
+   slave_config.src_addr = spi_imx->base_phys + MXC_CSPIRXDATA;
+   slave_config.src_addr_width = dsb_default;
+   slave_config.src_maxburst = spi_imx->wml;
+   ret = dmaengine_slave_config(master->dma_rx, _config);
+   if (ret)
+   pr_err("error in RX dma configuration.\n");
+
+err:
+   return ret;
+}
+
  static int spi_imx_setupxfer(struct spi_device *spi,
 struct spi_transfer *t)
  {
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
struct spi_imx_config config;
+   unsigned int new_bytes_per_word;
+   int ret = 0;

config.bpw = t ? t->bits_per_word : spi->bits_per_word;
config.speed_hz  = t ? t->speed_hz : spi->max_speed_hz;
@@ -792,9 +864,19 @@ static int spi_imx_setupxfer(struct spi_device *spi,
spi_imx->tx = spi_imx_buf_tx_u32;
}

-   spi_imx->devtype_data->config(spi_imx, );
+   new_bytes_per_word = spi_imx_get_bytes_per_word(config.bpw);
+   if (spi_imx->dma_is_inited &&
+   spi_imx->bytes_per_word != new_bytes_per_word) {
+   spi_imx->bytes_per_word = new_bytes_per_word;
+   ret = spi_imx_sdma_configure(s

Re: [PATCH v3 5/7] spi: imx: Add support for loopback for ECSPI controllers

2015-11-14 Thread Anton Bondarenko



On 01.11.2015 15:41, Anton Bondarenko wrote:

From: Anton Bondarenko 

Support for ECSPI loopback for IMX51,IMX53 and IMX6Q using TEST register.

Signed-off-by: Mohsin Kazmi 
Signed-off-by: Anton Bondarenko 
---
  drivers/spi/spi-imx.c | 19 ---
  1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 48fdfa1..dc492e2 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -270,6 +270,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_TEST0x20
+#define MX51_ECSPI_LOOPBIT(31)
+
  /* MX51 eCSPI */
  static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi,
  unsigned int *fres)
@@ -343,6 +346,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
@@ -385,6 +389,12 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);

+   if (config->mode & SPI_LOOP)
+   lpb |= MX51_ECSPI_LOOP;
+
+   if ((readl(spi_imx->base + MX51_ECSPI_TEST) & MX51_ECSPI_LOOP) != lpb)
+   writel(lpb, spi_imx->base + MX51_ECSPI_TEST);
+
/*
 * Wait until the changes in the configuration register CONFIGREG
 * propagate into the hardware. It takes exactly one tick of the
@@ -1262,6 +1272,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)
@@ -1288,10 +1301,10 @@ static int spi_imx_probe(struct platform_device *pdev)
spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;

-   init_completion(_imx->xfer_done);
+   if (is_imx51_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(_imx->xfer_done);

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
spi_imx->base = devm_ioremap_resource(>dev, res);



Does anyone has other comments regarding this commit?

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


Re: [PATCH v3 4/7] spi: imx: add function to check for IMX51 family controller

2015-11-14 Thread Anton Bondarenko



On 01.11.2015 15:41, Anton Bondarenko wrote:

From: Anton Bondarenko 

Similar to other controller type checks add check function for
IMX51. This also includes IMX53 and IMX6.

Signed-off-by: Anton Bondarenko 
---
  drivers/spi/spi-imx.c | 9 +++--
  1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 06f52c3..48fdfa1 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -127,9 +127,14 @@ static inline int is_imx35_cspi(struct spi_imx_data *d)
return d->devtype_data->devtype == IMX35_CSPI;
  }

+static inline int is_imx51_ecspi(struct spi_imx_data *d)
+{
+   return d->devtype_data->devtype == IMX51_ECSPI;
+}
+
  static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d)
  {
-   return (d->devtype_data->devtype == IMX51_ECSPI) ? 64 : 8;
+   return is_imx51_ecspi(d) ? 64 : 8;
  }

  #define MXC_SPI_BUF_RX(type)  \
@@ -1334,7 +1339,7 @@ static int spi_imx_probe(struct platform_device *pdev)
 * Only validated on i.mx6 now, can remove the constrain if validated on
 * other chips.
 */
-   if (spi_imx->devtype_data == _ecspi_devtype_data &&
+   if (is_imx51_ecspi(spi_imx) &&
spi_imx_sdma_init(>dev, spi_imx, master))
dev_err(>dev, "dma setup error,use pio instead\n");




Does anyone has other comments regarding this commit?

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


Re: [PATCH v3 6/7] spi: imx: return error from dma channel request

2015-11-14 Thread Anton Bondarenko



On 05.11.2015 17:00, Anton Bondarenko wrote:

On 05.11.2015 09:56, Sascha Hauer wrote:

On Sun, Nov 01, 2015 at 03:41:40PM +0100, Anton Bondarenko wrote:

From: Anton Bondarenko 

On SDMA initialization return exactly the same error, which is
reported by dma_request_slave_channel_reason(), it is a preceding
change to defer SPI DMA initialization, if SDMA module is not yet
available.


Maybe something like: "fix probe deferral when dmaengine is not yet
available" in the subject line will better express that this is a patch
that should be applied ASAP. Also you can move this up to the front of
the series when resending.

Sascha



This patch itself does not implement deferral for spi-imx if dmaengine
not ready. The patch targets 2 things: give a bit more detailed error
information of SPI dma slave channel initialization error and provide a
basis for the next patch ([PATCH v3 7/7] spi: imx: defer spi
initialization, if DMA engine is pending).

Regards, Anton


Does anyone has other comments regarding this commit?

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


Re: [PATCH v3 6/7] spi: imx: return error from dma channel request

2015-11-14 Thread Anton Bondarenko



On 05.11.2015 17:00, Anton Bondarenko wrote:

On 05.11.2015 09:56, Sascha Hauer wrote:

On Sun, Nov 01, 2015 at 03:41:40PM +0100, Anton Bondarenko wrote:

From: Anton Bondarenko 

On SDMA initialization return exactly the same error, which is
reported by dma_request_slave_channel_reason(), it is a preceding
change to defer SPI DMA initialization, if SDMA module is not yet
available.


Maybe something like: "fix probe deferral when dmaengine is not yet
available" in the subject line will better express that this is a patch
that should be applied ASAP. Also you can move this up to the front of
the series when resending.

Sascha



This patch itself does not implement deferral for spi-imx if dmaengine
not ready. The patch targets 2 things: give a bit more detailed error
information of SPI dma slave channel initialization error and provide a
basis for the next patch ([PATCH v3 7/7] spi: imx: defer spi
initialization, if DMA engine is pending).

Regards, Anton


Does anyone has other comments regarding this commit?

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


Re: [PATCH v3 1/7] spi: imx: Fix DMA transfer

2015-11-14 Thread Anton Bondarenko


On 05.11.2015 17:51, Anton Bondarenko wrote:

On 05.11.2015 09:34, Sascha Hauer wrote:

On Sun, Nov 01, 2015 at 03:41:35PM +0100, Anton Bondarenko wrote:

From: Anton Bondarenko 

RX DMA tail data handling doesn't work correctly in many cases with
current implementation. It happens because SPI core was setup
to generates both RX watermark level and RX DATA TAIL events
incorrectly. SPI transfer triggering for DMA also done in wrong way.

SPI client wants to transfer 70 words for example. The old DMA
implementation setup RX DATA TAIL equal 6 words. In this case
RX DMA event will be generated after 6 words read from RX FIFO.
The garbage can be read out from RX FIFO because SPI HW does
not receive all required words to trigger RX watermark event.

New implementation change handling of RX data tail. DMA is used to
process
all TX data and only full chunks of RX data with size aligned to FIFO/2.
Driver is waiting until both TX and RX DMA transaction done and all
TX data are pushed out. At that moment there is only RX data tail in
the RX FIFO. This data read out using PIO.


Have you looked at the RX_DMA_LENGTH and RXTDEN fields of the DMA
register? These seem to be for handling the remaining bytes of a DMA
transfer which do not reach the watermark level. From reading the
documentation I haven't really understood how it works though.

Sascha



A lot of times. Current implementation is trying to use it, but works
incorrectly if length % WML != 0 (which means RX_DMA_LENGTH == 0).

Regards, Anton


Does anyone has other comments regarding this commit?

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


Re: [PATCH v3 7/7] spi: imx: defer spi initialization, if DMA engine is pending

2015-11-14 Thread Anton Bondarenko



On 05.11.2015 17:18, Anton Bondarenko wrote:

On 05.11.2015 09:59, Sascha Hauer wrote:

On Sun, Nov 01, 2015 at 03:41:41PM +0100, Anton Bondarenko wrote:

From: Anton Bondarenko 

If SPI device supports DMA mode, but DMA controller is not yet
available due to e.g. a delay in the corresponding kernel module
initialization, retry to initialize SPI driver later on instead of
falling back into PIO only mode.

Signed-off-by: Vladimir Zapolskiy 
Signed-off-by: Anton Bondarenko 


Ok, so 6/7 is only part of the deferral story. Maybe squash the two
patches into one?

Sascha


I would like to keep these two changes separately since I have a small
concern about this exact change.

Let's assume such scenario:
- ECSPI configured to use DMA in device tree and DMA controller
description specified. But there is no driver for this controller in
kernel.
In this case dmaengine will always return -EDEFER and driver postpone
spi-imx initialization. So finally there will be no SPI support even in
PIO mode.
Or for example spi-imx will be compiled into kernel, but DMA controller
driver will be on SPI-NOR based rootfs.

So the question is "Should we allow user to use incorrect combination of
kernel configuration and DTS and work at least with some limitation?" Or
should we try to guarantee device tree file requirement to use DMA.

Any thoughts?

Regards, Anton


Does anyone has other comments regarding this commit?

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


Re: [PATCH v3 2/7] spi: imx: replace fixed timeout with calculated one

2015-11-14 Thread Anton Bondarenko


On 11.11.2015 09:12, Sascha Hauer wrote:

On Tue, Nov 10, 2015 at 09:20:06PM +0100, Anton Bondarenko wrote:



On 05.11.2015 09:47, Sascha Hauer wrote:

@@ -890,12 +891,40 @@ static void spi_imx_dma_tx_callback(void *cookie)
complete(_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);
+}


I think you can simplify this function to:

timeout = size * 8 / spi_imx->spi_bus_clk;
timeout += 2;

return msecs_to_jiffies(timeout * MSEC_PER_SEC);

The rationale is that when size * 8 / spi_imx->spi_bus_clk is 0 then we
can add another second and be fine. No need to calculate this more
accurate, in the end it's important to catch the timeout. If we do this
one or two seconds too late doesn't matter.

Sascha



Sascha,

What about something like this:
timeout = size * (8 + 4) / spi_imx->spi_bus_clk;
timeout += 2;

return msecs_to_jiffies(2 * timeout * MSEC_PER_SEC);

I think we still need to take into account 4 CLKs between each burst.


Fine with me.

Sascha




Tested new implementation successfully. Will be V4 patchset. Does anyone 
has other comments regarding this commit?


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


Re: [PATCH v3 6/7] spi: imx: return error from dma channel request

2015-11-14 Thread Anton Bondarenko



On 05.11.2015 17:00, Anton Bondarenko wrote:

On 05.11.2015 09:56, Sascha Hauer wrote:

On Sun, Nov 01, 2015 at 03:41:40PM +0100, Anton Bondarenko wrote:

From: Anton Bondarenko <anton_bondare...@mentor.com>

On SDMA initialization return exactly the same error, which is
reported by dma_request_slave_channel_reason(), it is a preceding
change to defer SPI DMA initialization, if SDMA module is not yet
available.


Maybe something like: "fix probe deferral when dmaengine is not yet
available" in the subject line will better express that this is a patch
that should be applied ASAP. Also you can move this up to the front of
the series when resending.

Sascha



This patch itself does not implement deferral for spi-imx if dmaengine
not ready. The patch targets 2 things: give a bit more detailed error
information of SPI dma slave channel initialization error and provide a
basis for the next patch ([PATCH v3 7/7] spi: imx: defer spi
initialization, if DMA engine is pending).

Regards, Anton


Does anyone has other comments regarding this commit?

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


Re: [PATCH v3 1/7] spi: imx: Fix DMA transfer

2015-11-14 Thread Anton Bondarenko


On 05.11.2015 17:51, Anton Bondarenko wrote:

On 05.11.2015 09:34, Sascha Hauer wrote:

On Sun, Nov 01, 2015 at 03:41:35PM +0100, Anton Bondarenko wrote:

From: Anton Bondarenko <anton_bondare...@mentor.com>

RX DMA tail data handling doesn't work correctly in many cases with
current implementation. It happens because SPI core was setup
to generates both RX watermark level and RX DATA TAIL events
incorrectly. SPI transfer triggering for DMA also done in wrong way.

SPI client wants to transfer 70 words for example. The old DMA
implementation setup RX DATA TAIL equal 6 words. In this case
RX DMA event will be generated after 6 words read from RX FIFO.
The garbage can be read out from RX FIFO because SPI HW does
not receive all required words to trigger RX watermark event.

New implementation change handling of RX data tail. DMA is used to
process
all TX data and only full chunks of RX data with size aligned to FIFO/2.
Driver is waiting until both TX and RX DMA transaction done and all
TX data are pushed out. At that moment there is only RX data tail in
the RX FIFO. This data read out using PIO.


Have you looked at the RX_DMA_LENGTH and RXTDEN fields of the DMA
register? These seem to be for handling the remaining bytes of a DMA
transfer which do not reach the watermark level. From reading the
documentation I haven't really understood how it works though.

Sascha



A lot of times. Current implementation is trying to use it, but works
incorrectly if length % WML != 0 (which means RX_DMA_LENGTH == 0).

Regards, Anton


Does anyone has other comments regarding this commit?

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


Re: [PATCH v3 7/7] spi: imx: defer spi initialization, if DMA engine is pending

2015-11-14 Thread Anton Bondarenko



On 05.11.2015 17:18, Anton Bondarenko wrote:

On 05.11.2015 09:59, Sascha Hauer wrote:

On Sun, Nov 01, 2015 at 03:41:41PM +0100, Anton Bondarenko wrote:

From: Anton Bondarenko <anton_bondare...@mentor.com>

If SPI device supports DMA mode, but DMA controller is not yet
available due to e.g. a delay in the corresponding kernel module
initialization, retry to initialize SPI driver later on instead of
falling back into PIO only mode.

Signed-off-by: Vladimir Zapolskiy <vladimir_zapols...@mentor.com>
Signed-off-by: Anton Bondarenko <anton_bondare...@mentor.com>


Ok, so 6/7 is only part of the deferral story. Maybe squash the two
patches into one?

Sascha


I would like to keep these two changes separately since I have a small
concern about this exact change.

Let's assume such scenario:
- ECSPI configured to use DMA in device tree and DMA controller
description specified. But there is no driver for this controller in
kernel.
In this case dmaengine will always return -EDEFER and driver postpone
spi-imx initialization. So finally there will be no SPI support even in
PIO mode.
Or for example spi-imx will be compiled into kernel, but DMA controller
driver will be on SPI-NOR based rootfs.

So the question is "Should we allow user to use incorrect combination of
kernel configuration and DTS and work at least with some limitation?" Or
should we try to guarantee device tree file requirement to use DMA.

Any thoughts?

Regards, Anton


Does anyone has other comments regarding this commit?

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


Re: [PATCH v3 2/7] spi: imx: replace fixed timeout with calculated one

2015-11-14 Thread Anton Bondarenko


On 11.11.2015 09:12, Sascha Hauer wrote:

On Tue, Nov 10, 2015 at 09:20:06PM +0100, Anton Bondarenko wrote:



On 05.11.2015 09:47, Sascha Hauer wrote:

@@ -890,12 +891,40 @@ static void spi_imx_dma_tx_callback(void *cookie)
complete(_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);
+}


I think you can simplify this function to:

timeout = size * 8 / spi_imx->spi_bus_clk;
timeout += 2;

return msecs_to_jiffies(timeout * MSEC_PER_SEC);

The rationale is that when size * 8 / spi_imx->spi_bus_clk is 0 then we
can add another second and be fine. No need to calculate this more
accurate, in the end it's important to catch the timeout. If we do this
one or two seconds too late doesn't matter.

Sascha



Sascha,

What about something like this:
timeout = size * (8 + 4) / spi_imx->spi_bus_clk;
timeout += 2;

return msecs_to_jiffies(2 * timeout * MSEC_PER_SEC);

I think we still need to take into account 4 CLKs between each burst.


Fine with me.

Sascha




Tested new implementation successfully. Will be V4 patchset. Does anyone 
has other comments regarding this commit?


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


Re: [PATCH v3 3/7] spi: imx: add support for all SPI word width for DMA transfer

2015-11-14 Thread Anton Bondarenko



On 01.11.2015 15:41, Anton Bondarenko wrote:

From: Anton Bondarenko <anton_bondare...@mentor.com>

DMA transfer for SPI was limited to up to 8 bits word size until now.
Sync in SPI burst size and DMA bus width is necessary to correctly
support other BPW supported by HW.

Signed-off-by: Anton Bondarenko <anton_bondare...@mentor.com>
---
  drivers/spi/spi-imx.c | 133 ++
  1 file changed, 102 insertions(+), 31 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 9b80c7f..06f52c3 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -89,11 +89,15 @@ struct spi_imx_data {

struct completion xfer_done;
void __iomem *base;
+   unsigned long base_phys;
+
struct clk *clk_per;
struct clk *clk_ipg;
unsigned long spi_clk;
unsigned int spi_bus_clk;

+   unsigned int bytes_per_word;
+
unsigned int count;
void (*tx)(struct spi_imx_data *);
void (*rx)(struct spi_imx_data *);
@@ -195,12 +199,31 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
return 7;
  }

+static int spi_imx_get_bytes_per_word(const int bpw)
+{
+   return DIV_ROUND_UP(bpw, BITS_PER_BYTE);
+}
+
  static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
 struct spi_transfer *transfer)
  {
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+   unsigned int bpw = transfer->bits_per_word;
+
+   if (!bpw)
+   bpw = spi->bits_per_word;

-   if (spi_imx->dma_is_inited && transfer->len > spi_imx->wml)
+   bpw = spi_imx_get_bytes_per_word(bpw);
+
+   /*
+* We need to use SPI word size in calculation to decide
+* if we want to go with DMA or PIO mode. Just a short example:
+* We need to transfer 24 SPI words with BPW == 32. This will take
+* 24 PIO writes to FIFO (and same for reads). But transfer->len will
+* be 24*4=96 bytes. WML is 32 SPI words. The decision will be incorrect
+* if we do not take into account SPI bits per word.
+*/
+   if (spi_imx->dma_is_inited && (transfer->len > spi_imx->wml * bpw))
return true;
return false;
  }
@@ -764,11 +787,60 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id)
return IRQ_HANDLED;
  }

+static int spi_imx_sdma_configure(struct spi_master *master)
+{
+   int ret;
+   enum dma_slave_buswidth dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE;
+   struct dma_slave_config slave_config = {};
+   struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+
+   switch (spi_imx->bytes_per_word) {
+   case 4:
+   dsb_default = DMA_SLAVE_BUSWIDTH_4_BYTES;
+   break;
+   case 2:
+   dsb_default = DMA_SLAVE_BUSWIDTH_2_BYTES;
+   break;
+   case 1:
+   dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE;
+   break;
+   default:
+   pr_err("Not supported word size %d\n", spi_imx->bytes_per_word);
+   ret = -EINVAL;
+   goto err;
+   }
+
+   slave_config.direction = DMA_MEM_TO_DEV;
+   slave_config.dst_addr = spi_imx->base_phys + MXC_CSPITXDATA;
+   slave_config.dst_addr_width = dsb_default;
+   slave_config.dst_maxburst = spi_imx->wml;
+   ret = dmaengine_slave_config(master->dma_tx, _config);
+   if (ret) {
+   pr_err("error in TX dma configuration.\n");
+   goto err;
+   }
+
+   memset(_config, 0, sizeof(slave_config));
+
+   slave_config.direction = DMA_DEV_TO_MEM;
+   slave_config.src_addr = spi_imx->base_phys + MXC_CSPIRXDATA;
+   slave_config.src_addr_width = dsb_default;
+   slave_config.src_maxburst = spi_imx->wml;
+   ret = dmaengine_slave_config(master->dma_rx, _config);
+   if (ret)
+   pr_err("error in RX dma configuration.\n");
+
+err:
+   return ret;
+}
+
  static int spi_imx_setupxfer(struct spi_device *spi,
 struct spi_transfer *t)
  {
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
struct spi_imx_config config;
+   unsigned int new_bytes_per_word;
+   int ret = 0;

config.bpw = t ? t->bits_per_word : spi->bits_per_word;
config.speed_hz  = t ? t->speed_hz : spi->max_speed_hz;
@@ -792,9 +864,19 @@ static int spi_imx_setupxfer(struct spi_device *spi,
spi_imx->tx = spi_imx_buf_tx_u32;
}

-   spi_imx->devtype_data->config(spi_imx, );
+   new_bytes_per_word = spi_imx_get_bytes_per_word(config.bpw);
+   if (spi_imx->dma_is_inited &&
+   spi_imx->bytes_per_word != new_bytes_per_word) {
+   spi_imx->bytes_per_word = new_bytes_pe

Re: [PATCH v3 6/7] spi: imx: return error from dma channel request

2015-11-14 Thread Anton Bondarenko



On 05.11.2015 17:00, Anton Bondarenko wrote:

On 05.11.2015 09:56, Sascha Hauer wrote:

On Sun, Nov 01, 2015 at 03:41:40PM +0100, Anton Bondarenko wrote:

From: Anton Bondarenko <anton_bondare...@mentor.com>

On SDMA initialization return exactly the same error, which is
reported by dma_request_slave_channel_reason(), it is a preceding
change to defer SPI DMA initialization, if SDMA module is not yet
available.


Maybe something like: "fix probe deferral when dmaengine is not yet
available" in the subject line will better express that this is a patch
that should be applied ASAP. Also you can move this up to the front of
the series when resending.

Sascha



This patch itself does not implement deferral for spi-imx if dmaengine
not ready. The patch targets 2 things: give a bit more detailed error
information of SPI dma slave channel initialization error and provide a
basis for the next patch ([PATCH v3 7/7] spi: imx: defer spi
initialization, if DMA engine is pending).

Regards, Anton


Does anyone has other comments regarding this commit?

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


Re: [PATCH v3 5/7] spi: imx: Add support for loopback for ECSPI controllers

2015-11-14 Thread Anton Bondarenko



On 01.11.2015 15:41, Anton Bondarenko wrote:

From: Anton Bondarenko <anton_bondare...@mentor.com>

Support for ECSPI loopback for IMX51,IMX53 and IMX6Q using TEST register.

Signed-off-by: Mohsin Kazmi <mohsin_ka...@mentor.com>
Signed-off-by: Anton Bondarenko <anton_bondare...@mentor.com>
---
  drivers/spi/spi-imx.c | 19 ---
  1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 48fdfa1..dc492e2 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -270,6 +270,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_TEST0x20
+#define MX51_ECSPI_LOOPBIT(31)
+
  /* MX51 eCSPI */
  static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi,
  unsigned int *fres)
@@ -343,6 +346,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
@@ -385,6 +389,12 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);

+   if (config->mode & SPI_LOOP)
+   lpb |= MX51_ECSPI_LOOP;
+
+   if ((readl(spi_imx->base + MX51_ECSPI_TEST) & MX51_ECSPI_LOOP) != lpb)
+   writel(lpb, spi_imx->base + MX51_ECSPI_TEST);
+
/*
 * Wait until the changes in the configuration register CONFIGREG
 * propagate into the hardware. It takes exactly one tick of the
@@ -1262,6 +1272,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)
@@ -1288,10 +1301,10 @@ static int spi_imx_probe(struct platform_device *pdev)
spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;

-   init_completion(_imx->xfer_done);
+   if (is_imx51_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(_imx->xfer_done);

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
spi_imx->base = devm_ioremap_resource(>dev, res);



Does anyone has other comments regarding this commit?

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


Re: [PATCH v3 4/7] spi: imx: add function to check for IMX51 family controller

2015-11-14 Thread Anton Bondarenko



On 01.11.2015 15:41, Anton Bondarenko wrote:

From: Anton Bondarenko <anton_bondare...@mentor.com>

Similar to other controller type checks add check function for
IMX51. This also includes IMX53 and IMX6.

Signed-off-by: Anton Bondarenko <anton_bondare...@mentor.com>
---
  drivers/spi/spi-imx.c | 9 +++--
  1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 06f52c3..48fdfa1 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -127,9 +127,14 @@ static inline int is_imx35_cspi(struct spi_imx_data *d)
return d->devtype_data->devtype == IMX35_CSPI;
  }

+static inline int is_imx51_ecspi(struct spi_imx_data *d)
+{
+   return d->devtype_data->devtype == IMX51_ECSPI;
+}
+
  static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d)
  {
-   return (d->devtype_data->devtype == IMX51_ECSPI) ? 64 : 8;
+   return is_imx51_ecspi(d) ? 64 : 8;
  }

  #define MXC_SPI_BUF_RX(type)  \
@@ -1334,7 +1339,7 @@ static int spi_imx_probe(struct platform_device *pdev)
 * Only validated on i.mx6 now, can remove the constrain if validated on
 * other chips.
 */
-   if (spi_imx->devtype_data == _ecspi_devtype_data &&
+   if (is_imx51_ecspi(spi_imx) &&
spi_imx_sdma_init(>dev, spi_imx, master))
dev_err(>dev, "dma setup error,use pio instead\n");




Does anyone has other comments regarding this commit?

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


Re: [PATCH v3 2/7] spi: imx: replace fixed timeout with calculated one

2015-11-10 Thread Anton Bondarenko



On 05.11.2015 09:47, Sascha Hauer wrote:

@@ -890,12 +891,40 @@ static void spi_imx_dma_tx_callback(void *cookie)
complete(_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);
+}


I think you can simplify this function to:

timeout = size * 8 / spi_imx->spi_bus_clk;
timeout += 2;

return msecs_to_jiffies(timeout * MSEC_PER_SEC);

The rationale is that when size * 8 / spi_imx->spi_bus_clk is 0 then we
can add another second and be fine. No need to calculate this more
accurate, in the end it's important to catch the timeout. If we do this
one or two seconds too late doesn't matter.

Sascha



Sascha,

What about something like this:
timeout = size * (8 + 4) / spi_imx->spi_bus_clk;
timeout += 2;

return msecs_to_jiffies(2 * timeout * MSEC_PER_SEC);

I think we still need to take into account 4 CLKs between each burst.

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


Re: [PATCH v3 2/7] spi: imx: replace fixed timeout with calculated one

2015-11-10 Thread Anton Bondarenko



On 05.11.2015 09:47, Sascha Hauer wrote:

@@ -890,12 +891,40 @@ static void spi_imx_dma_tx_callback(void *cookie)
complete(_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);
+}


I think you can simplify this function to:

timeout = size * 8 / spi_imx->spi_bus_clk;
timeout += 2;

return msecs_to_jiffies(timeout * MSEC_PER_SEC);

The rationale is that when size * 8 / spi_imx->spi_bus_clk is 0 then we
can add another second and be fine. No need to calculate this more
accurate, in the end it's important to catch the timeout. If we do this
one or two seconds too late doesn't matter.

Sascha



Sascha,

What about something like this:
timeout = size * (8 + 4) / spi_imx->spi_bus_clk;
timeout += 2;

return msecs_to_jiffies(2 * timeout * MSEC_PER_SEC);

I think we still need to take into account 4 CLKs between each burst.

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


Re: [PATCH v3 1/7] spi: imx: Fix DMA transfer

2015-11-05 Thread Anton Bondarenko

On 05.11.2015 09:34, Sascha Hauer wrote:

On Sun, Nov 01, 2015 at 03:41:35PM +0100, Anton Bondarenko wrote:

From: Anton Bondarenko 

RX DMA tail data handling doesn't work correctly in many cases with
current implementation. It happens because SPI core was setup
to generates both RX watermark level and RX DATA TAIL events
incorrectly. SPI transfer triggering for DMA also done in wrong way.

SPI client wants to transfer 70 words for example. The old DMA
implementation setup RX DATA TAIL equal 6 words. In this case
RX DMA event will be generated after 6 words read from RX FIFO.
The garbage can be read out from RX FIFO because SPI HW does
not receive all required words to trigger RX watermark event.

New implementation change handling of RX data tail. DMA is used to process
all TX data and only full chunks of RX data with size aligned to FIFO/2.
Driver is waiting until both TX and RX DMA transaction done and all
TX data are pushed out. At that moment there is only RX data tail in
the RX FIFO. This data read out using PIO.


Have you looked at the RX_DMA_LENGTH and RXTDEN fields of the DMA
register? These seem to be for handling the remaining bytes of a DMA
transfer which do not reach the watermark level. From reading the
documentation I haven't really understood how it works though.

Sascha



A lot of times. Current implementation is trying to use it, but works 
incorrectly if length % WML != 0 (which means RX_DMA_LENGTH == 0).


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


Re: [PATCH v3 7/7] spi: imx: defer spi initialization, if DMA engine is pending

2015-11-05 Thread Anton Bondarenko

On 05.11.2015 09:59, Sascha Hauer wrote:

On Sun, Nov 01, 2015 at 03:41:41PM +0100, Anton Bondarenko wrote:

From: Anton Bondarenko 

If SPI device supports DMA mode, but DMA controller is not yet
available due to e.g. a delay in the corresponding kernel module
initialization, retry to initialize SPI driver later on instead of
falling back into PIO only mode.

Signed-off-by: Vladimir Zapolskiy 
Signed-off-by: Anton Bondarenko 


Ok, so 6/7 is only part of the deferral story. Maybe squash the two
patches into one?

Sascha


I would like to keep these two changes separately since I have a small 
concern about this exact change.


Let's assume such scenario:
- ECSPI configured to use DMA in device tree and DMA controller 
description specified. But there is no driver for this controller in kernel.
In this case dmaengine will always return -EDEFER and driver postpone 
spi-imx initialization. So finally there will be no SPI support even in 
PIO mode.
Or for example spi-imx will be compiled into kernel, but DMA controller 
driver will be on SPI-NOR based rootfs.


So the question is "Should we allow user to use incorrect combination of 
kernel configuration and DTS and work at least with some limitation?" Or 
should we try to guarantee device tree file requirement to use DMA.


Any thoughts?

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


Re: [PATCH v3 6/7] spi: imx: return error from dma channel request

2015-11-05 Thread Anton Bondarenko

On 05.11.2015 09:56, Sascha Hauer wrote:

On Sun, Nov 01, 2015 at 03:41:40PM +0100, Anton Bondarenko wrote:

From: Anton Bondarenko 

On SDMA initialization return exactly the same error, which is
reported by dma_request_slave_channel_reason(), it is a preceding
change to defer SPI DMA initialization, if SDMA module is not yet
available.


Maybe something like: "fix probe deferral when dmaengine is not yet
available" in the subject line will better express that this is a patch
that should be applied ASAP. Also you can move this up to the front of
the series when resending.

Sascha



This patch itself does not implement deferral for spi-imx if dmaengine 
not ready. The patch targets 2 things: give a bit more detailed error 
information of SPI dma slave channel initialization error and provide a 
basis for the next patch ([PATCH v3 7/7] spi: imx: defer spi 
initialization, if DMA engine is pending).


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


Re: [PATCH v3 7/7] spi: imx: defer spi initialization, if DMA engine is pending

2015-11-05 Thread Anton Bondarenko

On 05.11.2015 09:59, Sascha Hauer wrote:

On Sun, Nov 01, 2015 at 03:41:41PM +0100, Anton Bondarenko wrote:

From: Anton Bondarenko <anton_bondare...@mentor.com>

If SPI device supports DMA mode, but DMA controller is not yet
available due to e.g. a delay in the corresponding kernel module
initialization, retry to initialize SPI driver later on instead of
falling back into PIO only mode.

Signed-off-by: Vladimir Zapolskiy <vladimir_zapols...@mentor.com>
Signed-off-by: Anton Bondarenko <anton_bondare...@mentor.com>


Ok, so 6/7 is only part of the deferral story. Maybe squash the two
patches into one?

Sascha


I would like to keep these two changes separately since I have a small 
concern about this exact change.


Let's assume such scenario:
- ECSPI configured to use DMA in device tree and DMA controller 
description specified. But there is no driver for this controller in kernel.
In this case dmaengine will always return -EDEFER and driver postpone 
spi-imx initialization. So finally there will be no SPI support even in 
PIO mode.
Or for example spi-imx will be compiled into kernel, but DMA controller 
driver will be on SPI-NOR based rootfs.


So the question is "Should we allow user to use incorrect combination of 
kernel configuration and DTS and work at least with some limitation?" Or 
should we try to guarantee device tree file requirement to use DMA.


Any thoughts?

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


Re: [PATCH v3 1/7] spi: imx: Fix DMA transfer

2015-11-05 Thread Anton Bondarenko

On 05.11.2015 09:34, Sascha Hauer wrote:

On Sun, Nov 01, 2015 at 03:41:35PM +0100, Anton Bondarenko wrote:

From: Anton Bondarenko <anton_bondare...@mentor.com>

RX DMA tail data handling doesn't work correctly in many cases with
current implementation. It happens because SPI core was setup
to generates both RX watermark level and RX DATA TAIL events
incorrectly. SPI transfer triggering for DMA also done in wrong way.

SPI client wants to transfer 70 words for example. The old DMA
implementation setup RX DATA TAIL equal 6 words. In this case
RX DMA event will be generated after 6 words read from RX FIFO.
The garbage can be read out from RX FIFO because SPI HW does
not receive all required words to trigger RX watermark event.

New implementation change handling of RX data tail. DMA is used to process
all TX data and only full chunks of RX data with size aligned to FIFO/2.
Driver is waiting until both TX and RX DMA transaction done and all
TX data are pushed out. At that moment there is only RX data tail in
the RX FIFO. This data read out using PIO.


Have you looked at the RX_DMA_LENGTH and RXTDEN fields of the DMA
register? These seem to be for handling the remaining bytes of a DMA
transfer which do not reach the watermark level. From reading the
documentation I haven't really understood how it works though.

Sascha



A lot of times. Current implementation is trying to use it, but works 
incorrectly if length % WML != 0 (which means RX_DMA_LENGTH == 0).


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


Re: [PATCH v3 6/7] spi: imx: return error from dma channel request

2015-11-05 Thread Anton Bondarenko

On 05.11.2015 09:56, Sascha Hauer wrote:

On Sun, Nov 01, 2015 at 03:41:40PM +0100, Anton Bondarenko wrote:

From: Anton Bondarenko <anton_bondare...@mentor.com>

On SDMA initialization return exactly the same error, which is
reported by dma_request_slave_channel_reason(), it is a preceding
change to defer SPI DMA initialization, if SDMA module is not yet
available.


Maybe something like: "fix probe deferral when dmaengine is not yet
available" in the subject line will better express that this is a patch
that should be applied ASAP. Also you can move this up to the front of
the series when resending.

Sascha



This patch itself does not implement deferral for spi-imx if dmaengine 
not ready. The patch targets 2 things: give a bit more detailed error 
information of SPI dma slave channel initialization error and provide a 
basis for the next patch ([PATCH v3 7/7] spi: imx: defer spi 
initialization, if DMA engine is pending).


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


Re: [PATCH v3 1/7] spi: imx: Fix DMA transfer

2015-11-04 Thread Anton Bondarenko



On 03.11.2015 08:08, Robin Gong wrote:

On Sun, Nov 01, 2015 at 03:41:35PM +0100, Anton Bondarenko wrote:

From: Anton Bondarenko 

RX DMA tail data handling doesn't work correctly in many cases with
current implementation. It happens because SPI core was setup
to generates both RX watermark level and RX DATA TAIL events
incorrectly. SPI transfer triggering for DMA also done in wrong way.

SPI client wants to transfer 70 words for example. The old DMA
implementation setup RX DATA TAIL equal 6 words. In this case
RX DMA event will be generated after 6 words read from RX FIFO.
The garbage can be read out from RX FIFO because SPI HW does
not receive all required words to trigger RX watermark event.

New implementation change handling of RX data tail. DMA is used to process
all TX data and only full chunks of RX data with size aligned to FIFO/2.
Driver is waiting until both TX and RX DMA transaction done and all
TX data are pushed out. At that moment there is only RX data tail in
the RX FIFO. This data read out using PIO.

Transfer triggering changed to avoid RX data loss.

Signed-off-by: Anton Bondarenko 
---
  drivers/spi/spi-imx.c | 115 +-
  1 file changed, 76 insertions(+), 39 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
@@ -967,10 +974,40 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
dev_name(>dev));
spi_imx->devtype_data->reset(spi_imx);
dmaengine_terminate_all(master->dma_rx);
+   } else if (left) {
+   void *pio_buffer = transfer->rx_buf
+   + (transfer->len - left);
+
+   dma_sync_sg_for_cpu(master->dma_rx->device->dev,
+   >sgl[rx->nents - 1], 1,
+   DMA_FROM_DEVICE);
+
+   spi_imx->rx_buf = pio_buffer;
+   spi_imx->txfifo = left;
+   reinit_completion(_imx->xfer_done);
+
+   spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TCEN);
+
+   timeout = wait_for_completion_timeout(
+   _imx->xfer_done, IMX_DMA_TIMEOUT);
+   if (!timeout) {
+   pr_warn("%s %s: I/O Error in RX tail\n",
+   dev_driver_string(>dev),
+   dev_name(>dev));
+   }
+
+   /*
+* WARNING: this call will cause DMA debug complains
+* about wrong combination of DMA direction and sync
+* function. But we must use it to make sure the data
+* read by PIO mode will be cleared from CPU cache.
+* Otherwise SPI core will invalidate it during unmap of
+* SG buffers.
+*/
+   dma_sync_sg_for_device(master->dma_rx->device->dev,
+  >sgl[rx->nents - 1], 1,
+  DMA_TO_DEVICE);

I think the above dma_sync_sg_for_cpu for reading the last sgl by PIO mode is
enough, that move the right data into rx_buf which map by SPI core. And why
'DMA_TO_DEVICE' for rx here?
Actually this is described in comments above the call. So after writing 
data tail by CPU we must ensure cache content is flushed to RAM. 
Otherwise SPI core during dma_unmap will invalidate data in the CPU 
cache and we loose our data tail. I'm able to reproduce this very fast 
during 20-30 SPI transactions.

Hope this make things clearer.


}
-   writel(dma |
-  spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET,
-  spi_imx->base + MX51_ECSPI_DMA);
}

spi_imx->dma_finished = 1;
--
2.6.2


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


Re: [PATCH v3 1/7] spi: imx: Fix DMA transfer

2015-11-04 Thread Anton Bondarenko



On 03.11.2015 08:08, Robin Gong wrote:

On Sun, Nov 01, 2015 at 03:41:35PM +0100, Anton Bondarenko wrote:

From: Anton Bondarenko <anton_bondare...@mentor.com>

RX DMA tail data handling doesn't work correctly in many cases with
current implementation. It happens because SPI core was setup
to generates both RX watermark level and RX DATA TAIL events
incorrectly. SPI transfer triggering for DMA also done in wrong way.

SPI client wants to transfer 70 words for example. The old DMA
implementation setup RX DATA TAIL equal 6 words. In this case
RX DMA event will be generated after 6 words read from RX FIFO.
The garbage can be read out from RX FIFO because SPI HW does
not receive all required words to trigger RX watermark event.

New implementation change handling of RX data tail. DMA is used to process
all TX data and only full chunks of RX data with size aligned to FIFO/2.
Driver is waiting until both TX and RX DMA transaction done and all
TX data are pushed out. At that moment there is only RX data tail in
the RX FIFO. This data read out using PIO.

Transfer triggering changed to avoid RX data loss.

Signed-off-by: Anton Bondarenko <anton_bondare...@mentor.com>
---
  drivers/spi/spi-imx.c | 115 +-
  1 file changed, 76 insertions(+), 39 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
@@ -967,10 +974,40 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
*spi_imx,
dev_name(>dev));
spi_imx->devtype_data->reset(spi_imx);
dmaengine_terminate_all(master->dma_rx);
+   } else if (left) {
+   void *pio_buffer = transfer->rx_buf
+   + (transfer->len - left);
+
+   dma_sync_sg_for_cpu(master->dma_rx->device->dev,
+   >sgl[rx->nents - 1], 1,
+   DMA_FROM_DEVICE);
+
+   spi_imx->rx_buf = pio_buffer;
+   spi_imx->txfifo = left;
+   reinit_completion(_imx->xfer_done);
+
+   spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TCEN);
+
+   timeout = wait_for_completion_timeout(
+   _imx->xfer_done, IMX_DMA_TIMEOUT);
+   if (!timeout) {
+   pr_warn("%s %s: I/O Error in RX tail\n",
+   dev_driver_string(>dev),
+   dev_name(>dev));
+   }
+
+   /*
+* WARNING: this call will cause DMA debug complains
+* about wrong combination of DMA direction and sync
+* function. But we must use it to make sure the data
+* read by PIO mode will be cleared from CPU cache.
+* Otherwise SPI core will invalidate it during unmap of
+* SG buffers.
+*/
+   dma_sync_sg_for_device(master->dma_rx->device->dev,
+  >sgl[rx->nents - 1], 1,
+  DMA_TO_DEVICE);

I think the above dma_sync_sg_for_cpu for reading the last sgl by PIO mode is
enough, that move the right data into rx_buf which map by SPI core. And why
'DMA_TO_DEVICE' for rx here?
Actually this is described in comments above the call. So after writing 
data tail by CPU we must ensure cache content is flushed to RAM. 
Otherwise SPI core during dma_unmap will invalidate data in the CPU 
cache and we loose our data tail. I'm able to reproduce this very fast 
during 20-30 SPI transactions.

Hope this make things clearer.


}
-   writel(dma |
-  spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET,
-  spi_imx->base + MX51_ECSPI_DMA);
}

spi_imx->dma_finished = 1;
--
2.6.2


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


[PATCH v3 5/7] spi: imx: Add support for loopback for ECSPI controllers

2015-11-01 Thread Anton Bondarenko
From: Anton Bondarenko 

Support for ECSPI loopback for IMX51,IMX53 and IMX6Q using TEST register.

Signed-off-by: Mohsin Kazmi 
Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 48fdfa1..dc492e2 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -270,6 +270,9 @@ static bool spi_imx_can_dma(struct spi_master *master, 
struct spi_device *spi,
 #define MX51_ECSPI_STAT0x18
 #define MX51_ECSPI_STAT_RR (1 <<  3)
 
+#define MX51_ECSPI_TEST0x20
+#define MX51_ECSPI_LOOPBIT(31)
+
 /* MX51 eCSPI */
 static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi,
  unsigned int *fres)
@@ -343,6 +346,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
@@ -385,6 +389,12 @@ static int __maybe_unused mx51_ecspi_config(struct 
spi_imx_data *spi_imx,
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
 
+   if (config->mode & SPI_LOOP)
+   lpb |= MX51_ECSPI_LOOP;
+
+   if ((readl(spi_imx->base + MX51_ECSPI_TEST) & MX51_ECSPI_LOOP) != lpb)
+   writel(lpb, spi_imx->base + MX51_ECSPI_TEST);
+
/*
 * Wait until the changes in the configuration register CONFIGREG
 * propagate into the hardware. It takes exactly one tick of the
@@ -1262,6 +1272,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)
@@ -1288,10 +1301,10 @@ static int spi_imx_probe(struct platform_device *pdev)
spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 
-   init_completion(_imx->xfer_done);
+   if (is_imx51_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(_imx->xfer_done);
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
spi_imx->base = devm_ioremap_resource(>dev, res);
-- 
2.6.2

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


[PATCH v3 2/7] spi: imx: replace fixed timeout with calculated one

2015-11-01 Thread Anton Bondarenko
From: Anton Bondarenko 

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 
---
 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 bd7b721..9b80c7f 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -57,7 +57,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;
@@ -93,6 +92,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 *);
@@ -314,8 +314,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
@@ -327,7 +326,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, );
+   spi_imx->spi_bus_clk = config->speed_hz;
+   ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz,
+ _imx->spi_bus_clk);
 
/* set chip select to use */
ctrl |= MX51_ECSPI_CTRL_CS(config->cs);
@@ -367,7 +368,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 * 100) / 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 */
@@ -890,12 +891,40 @@ static void spi_imx_dma_tx_callback(void *cookie)
complete(_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 = >tx_sg, *rx = >rx_sg;
@@ -956,9 +985,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(_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(>dev),
@@ -966,8 +997,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(sp

[PATCH v3 6/7] spi: imx: return error from dma channel request

2015-11-01 Thread Anton Bondarenko
From: Anton Bondarenko 

On SDMA initialization return exactly the same error, which is
reported by dma_request_slave_channel_reason(), it is a preceding
change to defer SPI DMA initialization, if SDMA module is not yet
available.

Signed-off-by: Vladimir Zapolskiy 
Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 18 ++
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index dc492e2..6035ddd 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -923,18 +923,20 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2;
 
/* Prepare for TX DMA: */
-   master->dma_tx = dma_request_slave_channel(dev, "tx");
-   if (!master->dma_tx) {
-   dev_err(dev, "cannot get the TX DMA channel!\n");
-   ret = -EINVAL;
+   master->dma_tx = dma_request_slave_channel_reason(dev, "tx");
+   if (IS_ERR(master->dma_tx)) {
+   dev_info(dev, "cannot get the TX DMA channel!\n");
+   ret = PTR_ERR(master->dma_tx);
+   master->dma_tx = NULL;
goto err;
}
 
/* Prepare for RX : */
-   master->dma_rx = dma_request_slave_channel(dev, "rx");
-   if (!master->dma_rx) {
-   dev_dbg(dev, "cannot get the DMA channel.\n");
-   ret = -EINVAL;
+   master->dma_rx = dma_request_slave_channel_reason(dev, "rx");
+   if (IS_ERR(master->dma_rx)) {
+   dev_info(dev, "cannot get the DMA channel.\n");
+   ret = PTR_ERR(master->dma_rx);
+   master->dma_rx = NULL;
goto err;
}
 
-- 
2.6.2

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


[PATCH v3 4/7] spi: imx: add function to check for IMX51 family controller

2015-11-01 Thread Anton Bondarenko
From: Anton Bondarenko 

Similar to other controller type checks add check function for
IMX51. This also includes IMX53 and IMX6.

Signed-off-by: Anton Bondarenko 
---
 drivers/spi/spi-imx.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 06f52c3..48fdfa1 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -127,9 +127,14 @@ static inline int is_imx35_cspi(struct spi_imx_data *d)
return d->devtype_data->devtype == IMX35_CSPI;
 }
 
+static inline int is_imx51_ecspi(struct spi_imx_data *d)
+{
+   return d->devtype_data->devtype == IMX51_ECSPI;
+}
+
 static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d)
 {
-   return (d->devtype_data->devtype == IMX51_ECSPI) ? 64 : 8;
+   return is_imx51_ecspi(d) ? 64 : 8;
 }
 
 #define MXC_SPI_BUF_RX(type)   \
@@ -1334,7 +1339,7 @@ static int spi_imx_probe(struct platform_device *pdev)
 * Only validated on i.mx6 now, can remove the constrain if validated on
 * other chips.
 */
-   if (spi_imx->devtype_data == _ecspi_devtype_data &&
+   if (is_imx51_ecspi(spi_imx) &&
spi_imx_sdma_init(>dev, spi_imx, master))
dev_err(>dev, "dma setup error,use pio instead\n");
 
-- 
2.6.2

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


  1   2   >