[PATCH v8 05/18] dmaengine: st_fdma: Add STMicroelectronics FDMA engine driver support

2016-09-01 Thread Peter Griffin
Hi Vinod,

Thanks for reviewing.

On Tue, 30 Aug 2016, Vinod Koul wrote:

> On Fri, Aug 26, 2016 at 03:56:40PM +0100, Peter Griffin wrote:
> 
> >  config STM32_DMA
> > bool "STMicroelectronics STM32 DMA support"
> > depends on ARCH_STM32
> > @@ -567,7 +580,6 @@ config ZX_DMA
> > help
> >   Support the DMA engine for ZTE ZX296702 platform devices.
> >  
> > -
> 
> unrelated change?

OK will remove and send a separate patch.
> 
> > +   fdev->chans = devm_kzalloc(>dev,
> > +  fdev->nr_channels
> > +  * sizeof(struct st_fdma_chan), GFP_KERNEL);
> 
> devm_kcalloc()

Will fix in next version.

> 
> > +   if (!fdev->chans)
> > +   return -ENOMEM;
> > +
> > +   fdev->dev = >dev;
> > +   fdev->drvdata = drvdata;
> > +   platform_set_drvdata(pdev, fdev);
> > +
> > +   fdev->irq = platform_get_irq(pdev, 0);
> > +   if (fdev->irq < 0) {
> > +   dev_err(>dev, "Failed to get irq resource\n");
> > +   return -EINVAL;
> > +   }
> > +
> > +   ret = devm_request_irq(>dev, fdev->irq, st_fdma_irq_handler, 0,
> > +  dev_name(>dev), fdev);
> > +   if (ret) {
> > +   dev_err(>dev, "Failed to request irq (%d)\n", ret);
> > +   goto err;
> > +   }
> > +
> > +   fdev->slim_rproc = st_slim_rproc_alloc(pdev, fdev->fw_name);
> > +   if (!fdev->slim_rproc) {
> > +   ret = PTR_ERR(fdev->slim_rproc);
> > +   dev_err(>dev, "slim_rproc_alloc failed (%d)\n", ret);
> > +   goto err;
> > +   }
> > +
> > +   /* Initialise list of FDMA channels */
> > +   INIT_LIST_HEAD(>dma_device.channels);
> > +   for (i = 0; i < fdev->nr_channels; i++) {
> > +   struct st_fdma_chan *fchan = >chans[i];
> > +
> > +   fchan->fdev = fdev;
> > +   fchan->vchan.desc_free = st_fdma_free_desc;
> > +   vchan_init(>vchan, >dma_device);
> 
> this initialized a tasklet
> 
> > +static int st_fdma_remove(struct platform_device *pdev)
> > +{
> > +   struct st_fdma_dev *fdev = platform_get_drvdata(pdev);
> > +
> > +   devm_free_irq(>dev, fdev->irq, fdev);
> > +   st_slim_rproc_put(fdev->slim_rproc);
> > +   of_dma_controller_free(pdev->dev.of_node);
> > +   dma_async_device_unregister(>dma_device);
> 
> and that vchan tasklet is not quisced here :(

Eeek, good spot. Will fix in next version.

> 
> > +MODULE_LICENSE("GPL v2");
> > +MODULE_DESCRIPTION("STMicroelectronics FDMA engine driver");
> > +MODULE_AUTHOR("Ludovic.barre ");
> > +MODULE_AUTHOR("Peter Griffin ");
> 
> No MODULE_ALIAS?

Will add in next version.

regards,

Peter. 


[PATCH v8 05/18] dmaengine: st_fdma: Add STMicroelectronics FDMA engine driver support

2016-08-30 Thread Vinod Koul
On Fri, Aug 26, 2016 at 03:56:40PM +0100, Peter Griffin wrote:

>  config STM32_DMA
>   bool "STMicroelectronics STM32 DMA support"
>   depends on ARCH_STM32
> @@ -567,7 +580,6 @@ config ZX_DMA
>   help
> Support the DMA engine for ZTE ZX296702 platform devices.
>  
> -

unrelated change?

> + fdev->chans = devm_kzalloc(>dev,
> +fdev->nr_channels
> +* sizeof(struct st_fdma_chan), GFP_KERNEL);

devm_kcalloc()

> + if (!fdev->chans)
> + return -ENOMEM;
> +
> + fdev->dev = >dev;
> + fdev->drvdata = drvdata;
> + platform_set_drvdata(pdev, fdev);
> +
> + fdev->irq = platform_get_irq(pdev, 0);
> + if (fdev->irq < 0) {
> + dev_err(>dev, "Failed to get irq resource\n");
> + return -EINVAL;
> + }
> +
> + ret = devm_request_irq(>dev, fdev->irq, st_fdma_irq_handler, 0,
> +dev_name(>dev), fdev);
> + if (ret) {
> + dev_err(>dev, "Failed to request irq (%d)\n", ret);
> + goto err;
> + }
> +
> + fdev->slim_rproc = st_slim_rproc_alloc(pdev, fdev->fw_name);
> + if (!fdev->slim_rproc) {
> + ret = PTR_ERR(fdev->slim_rproc);
> + dev_err(>dev, "slim_rproc_alloc failed (%d)\n", ret);
> + goto err;
> + }
> +
> + /* Initialise list of FDMA channels */
> + INIT_LIST_HEAD(>dma_device.channels);
> + for (i = 0; i < fdev->nr_channels; i++) {
> + struct st_fdma_chan *fchan = >chans[i];
> +
> + fchan->fdev = fdev;
> + fchan->vchan.desc_free = st_fdma_free_desc;
> + vchan_init(>vchan, >dma_device);

this initialized a tasklet

> +static int st_fdma_remove(struct platform_device *pdev)
> +{
> + struct st_fdma_dev *fdev = platform_get_drvdata(pdev);
> +
> + devm_free_irq(>dev, fdev->irq, fdev);
> + st_slim_rproc_put(fdev->slim_rproc);
> + of_dma_controller_free(pdev->dev.of_node);
> + dma_async_device_unregister(>dma_device);

and that vchan tasklet is not quisced here :(

> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("STMicroelectronics FDMA engine driver");
> +MODULE_AUTHOR("Ludovic.barre ");
> +MODULE_AUTHOR("Peter Griffin ");

No MODULE_ALIAS?

-- 
~Vinod


[PATCH v8 05/18] dmaengine: st_fdma: Add STMicroelectronics FDMA engine driver support

2016-08-26 Thread Peter Griffin
This patch adds support for the Flexible Direct Memory Access (FDMA) core
driver. The FDMA is a slim core CPU with a dedicated firmware.
It is a general purpose DMA controller capable of supporting 16
independent DMA channels. Data moves maybe from memory to memory
or between memory and paced latency critical real time targets and it
is found on al STi based chipsets.

Signed-off-by: Ludovic Barre 
Signed-off-by: Peter Griffin 
---
 drivers/dma/Kconfig   |  14 +-
 drivers/dma/Makefile  |   1 +
 drivers/dma/st_fdma.c | 880 ++
 3 files changed, 894 insertions(+), 1 deletion(-)
 create mode 100644 drivers/dma/st_fdma.c

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 739f797..5b5a341 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -437,6 +437,19 @@ config STE_DMA40
help
  Support for ST-Ericsson DMA40 controller

+config ST_FDMA
+   tristate "ST FDMA dmaengine support"
+   depends on ARCH_STI
+   select ST_SLIM_REMOTEPROC
+   select DMA_ENGINE
+   select DMA_VIRTUAL_CHANNELS
+   help
+ Enable support for ST FDMA controller.
+ It supports 16 independent DMA channels, accepts up to 32 DMA requests
+
+ Say Y here if you have such a chipset.
+ If unsure, say N.
+
 config STM32_DMA
bool "STMicroelectronics STM32 DMA support"
depends on ARCH_STM32
@@ -567,7 +580,6 @@ config ZX_DMA
help
  Support the DMA engine for ZTE ZX296702 platform devices.

-
 # driver files
 source "drivers/dma/bestcomm/Kconfig"

diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index e4dc9ca..a4fa336 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_TI_DMA_CROSSBAR) += ti-dma-crossbar.o
 obj-$(CONFIG_TI_EDMA) += edma.o
 obj-$(CONFIG_XGENE_DMA) += xgene-dma.o
 obj-$(CONFIG_ZX_DMA) += zx296702_dma.o
+obj-$(CONFIG_ST_FDMA) += st_fdma.o

 obj-y += qcom/
 obj-y += xilinx/
diff --git a/drivers/dma/st_fdma.c b/drivers/dma/st_fdma.c
new file mode 100644
index 000..bb8d8a7
--- /dev/null
+++ b/drivers/dma/st_fdma.c
@@ -0,0 +1,880 @@
+/*
+ * st_fdma.c
+ *
+ * Copyright (C) 2014 STMicroelectronics
+ * Author: Ludovic Barre 
+ *Peter Griffin 
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "st_fdma.h"
+
+static inline struct st_fdma_chan *to_st_fdma_chan(struct dma_chan *c)
+{
+   return container_of(c, struct st_fdma_chan, vchan.chan);
+}
+
+static struct st_fdma_desc *to_st_fdma_desc(struct virt_dma_desc *vd)
+{
+   return container_of(vd, struct st_fdma_desc, vdesc);
+}
+
+static int st_fdma_dreq_get(struct st_fdma_chan *fchan)
+{
+   struct st_fdma_dev *fdev = fchan->fdev;
+   u32 req_line_cfg = fchan->cfg.req_line;
+   u32 dreq_line;
+   int try = 0;
+
+   /*
+* dreq_mask is shared for n channels of fdma, so all accesses must be
+* atomic. if the dreq_mask is changed between ffz and set_bit,
+* we retry
+*/
+   do {
+   if (fdev->dreq_mask == ~0L) {
+   dev_err(fdev->dev, "No req lines available\n");
+   return -EINVAL;
+   }
+
+   if (try || req_line_cfg >= ST_FDMA_NR_DREQS) {
+   dev_err(fdev->dev, "Invalid or used req line\n");
+   return -EINVAL;
+   } else {
+   dreq_line = req_line_cfg;
+   }
+
+   try++;
+   } while (test_and_set_bit(dreq_line, >dreq_mask));
+
+   dev_dbg(fdev->dev, "get dreq_line:%d mask:%#lx\n",
+   dreq_line, fdev->dreq_mask);
+
+   return dreq_line;
+}
+
+static void st_fdma_dreq_put(struct st_fdma_chan *fchan)
+{
+   struct st_fdma_dev *fdev = fchan->fdev;
+
+   dev_dbg(fdev->dev, "put dreq_line:%#x\n", fchan->dreq_line);
+   clear_bit(fchan->dreq_line, >dreq_mask);
+}
+
+static void st_fdma_xfer_desc(struct st_fdma_chan *fchan)
+{
+   struct virt_dma_desc *vdesc;
+   unsigned long nbytes, ch_cmd, cmd;
+
+   vdesc = vchan_next_desc(>vchan);
+   if (!vdesc)
+   return;
+
+   fchan->fdesc = to_st_fdma_desc(vdesc);
+   nbytes = fchan->fdesc->node[0].desc->nbytes;
+   cmd = FDMA_CMD_START(fchan->vchan.chan.chan_id);
+   ch_cmd = fchan->fdesc->node[0].pdesc | FDMA_CH_CMD_STA_START;
+
+   /* start the channel for the descriptor */
+   fnode_write(fchan, nbytes, FDMA_CNTN_OFST);
+   fchan_write(fchan, ch_cmd, FDMA_CH_CMD_OFST);
+   writel(cmd,
+   fchan->fdev->slim_rproc->peri + FDMA_CMD_SET_OFST);
+
+   dev_dbg(fchan->fdev->dev, "start chan:%d\n", fchan->vchan.chan.chan_id);
+}
+
+static void st_fdma_ch_sta_update(struct st_fdma_chan *fchan,
+ unsigned long int_sta)
+{
+   unsigned long ch_sta, ch_err;
+