* Re: [PATCH v3 2/7] dmaengine: sun6i: Add a quirk for additional mbus clock
From: Vinod Koul @ 2019-06-04 12:27 UTC (permalink / raw)
To: Clément Péron
Cc: Rob Herring, Mark Rutland, Maxime Ripard, Chen-Yu Tsai,
Dan Williams, dmaengine, devicetree, linux-arm-kernel,
linux-kernel, Jernej Skrabec
In-Reply-To: <20190527201459.20130-3-peron.clem@gmail.com>
On 27-05-19, 22:14, Clément Péron wrote:
> From: Jernej Skrabec <jernej.skrabec@siol.net>
>
> H6 DMA controller needs additional mbus clock to be enabled.
>
> Add a quirk for it and handle it accordingly.
Applied, thanks
--
~Vinod
^ permalink raw reply
* Re: [PATCH v3 1/7] dt-bindings: arm64: allwinner: h6: Add binding for DMA controller
From: Vinod Koul @ 2019-06-04 12:27 UTC (permalink / raw)
To: Clément Péron
Cc: Rob Herring, Mark Rutland, Maxime Ripard, Chen-Yu Tsai,
Dan Williams, dmaengine, devicetree, linux-arm-kernel,
linux-kernel, Jernej Skrabec, Rob Herring
In-Reply-To: <20190527201459.20130-2-peron.clem@gmail.com>
On 27-05-19, 22:14, Clément Péron wrote:
> From: Jernej Skrabec <jernej.skrabec@siol.net>
>
> DMA in H6 is similar to other DMA controller, except it is first which
> supports more than 32 request sources and has 16 channels. It also needs
> additional clock to be enabled.
>
Applied, thanks
--
~Vinod
^ permalink raw reply
* Re: [PATCH v1] dmaengine: tegra-apb: Error out if DMA_PREP_INTERRUPT flag is unset
From: Vinod Koul @ 2019-06-04 12:16 UTC (permalink / raw)
To: Dmitry Osipenko
Cc: Laxman Dewangan, Thierry Reding, Jonathan Hunter, Ben Dooks,
dmaengine, linux-tegra, linux-kernel
In-Reply-To: <20190529214355.15339-1-digetx@gmail.com>
On 30-05-19, 00:43, Dmitry Osipenko wrote:
> Apparently driver was never tested with DMA_PREP_INTERRUPT flag being
> unset since it completely disables interrupt handling instead of skipping
> the callbacks invocations, hence putting channel into unusable state.
>
> The flag is always set by all of kernel drivers that use APB DMA, so let's
> error out in otherwise case for consistency. It won't be difficult to
> support that case properly if ever will be needed.
Applied, thanks
--
~Vinod
^ permalink raw reply
* Re: [PATCH 2/2] dmagengine: pl330: add code to get reset property
From: Vinod Koul @ 2019-06-04 12:14 UTC (permalink / raw)
To: Dinh Nguyen; +Cc: dmaengine, robh+dt, mark.rutland, devicetree
In-Reply-To: <20190524002847.30961-2-dinguyen@kernel.org>
On 23-05-19, 19:28, Dinh Nguyen wrote:
> The DMA controller on some SoCs can be held in reset, and thus requires
> the reset signal(s) to deasserted. Most SoCs will have just one reset
> signal, but there are others, i.e. Arria10/Stratix10 will have an
> additional reset signal, referred to as the OCP.
>
> Add code to get the reset property from the device tree for deassert and
> assert.
>
> Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
> ---
> drivers/dma/pl330.c | 38 ++++++++++++++++++++++++++++++++++++++
> 1 file changed, 38 insertions(+)
>
> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> index 6e6837214210..6018c43e785d 100644
> --- a/drivers/dma/pl330.c
> +++ b/drivers/dma/pl330.c
> @@ -29,6 +29,7 @@
> #include <linux/err.h>
> #include <linux/pm_runtime.h>
> #include <linux/bug.h>
> +#include <linux/reset.h>
>
> #include "dmaengine.h"
> #define PL330_MAX_CHAN 8
> @@ -500,6 +501,9 @@ struct pl330_dmac {
> unsigned int num_peripherals;
> struct dma_pl330_chan *peripherals; /* keep at end */
> int quirks;
> +
> + struct reset_control *rstc;
> + struct reset_control *rstc_ocp;
> };
>
> static struct pl330_of_quirks {
> @@ -3028,6 +3032,30 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
>
> amba_set_drvdata(adev, pl330);
>
> + pl330->rstc = devm_reset_control_get_optional(&adev->dev, "dma");
> + if (IS_ERR(pl330->rstc)) {
> + dev_err(&adev->dev, "No reset controller specified.\n");
Wasnt this optional??
> + return PTR_ERR(pl330->rstc);
> + } else {
> + ret = reset_control_deassert(pl330->rstc);
> + if (ret) {
> + dev_err(&adev->dev, "Couldn't deassert the device from reset!\n");
> + return ret;
> + }
> + }
> +
> + pl330->rstc_ocp = devm_reset_control_get_optional(&adev->dev, "dma-ocp");
> + if (IS_ERR(pl330->rstc_ocp)) {
> + dev_err(&adev->dev, "No reset controller specified.\n");
> + return PTR_ERR(pl330->rstc_ocp);
> + } else {
> + ret = reset_control_deassert(pl330->rstc_ocp);
> + if (ret) {
> + dev_err(&adev->dev, "Couldn't deassert the device from OCP reset!\n");
> + return ret;
> + }
> + }
> +
> for (i = 0; i < AMBA_NR_IRQS; i++) {
> irq = adev->irq[i];
> if (irq) {
> @@ -3168,6 +3196,11 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
> probe_err2:
> pl330_del(pl330);
>
> + if (pl330->rstc_ocp)
> + reset_control_assert(pl330->rstc_ocp);
> +
> + if (pl330->rstc)
> + reset_control_assert(pl330->rstc);
> return ret;
> }
>
> @@ -3206,6 +3239,11 @@ static int pl330_remove(struct amba_device *adev)
>
> pl330_del(pl330);
>
> + if (pl330->rstc_ocp)
> + reset_control_assert(pl330->rstc_ocp);
> +
> + if (pl330->rstc)
> + reset_control_assert(pl330->rstc);
> return 0;
> }
>
> --
> 2.20.0
--
~Vinod
^ permalink raw reply
* Re: [V3 2/2] dmaengine: fsl-qdma: Add improvement
From: Vinod Koul @ 2019-06-04 12:07 UTC (permalink / raw)
To: Peng Ma; +Cc: dan.j.williams, dmaengine, linux-kernel
In-Reply-To: <20190522032103.13713-2-peng.ma@nxp.com>
On 22-05-19, 03:21, Peng Ma wrote:
> When an error occurs we should clean the error register then to return
The patch title is supposed to tell us about the change. "Add
improvement: is a very generic term!
I have change title to "Continue to clear register on error" and applied
>
> Signed-off-by: Peng Ma <peng.ma@nxp.com>
> ---
> changed for V3:
> - no changed.
>
> drivers/dma/fsl-qdma.c | 4 +---
> 1 files changed, 1 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/dma/fsl-qdma.c b/drivers/dma/fsl-qdma.c
> index da8fdf5..8e341c0 100644
> --- a/drivers/dma/fsl-qdma.c
> +++ b/drivers/dma/fsl-qdma.c
> @@ -703,10 +703,8 @@ static irqreturn_t fsl_qdma_error_handler(int irq, void *dev_id)
>
> intr = qdma_readl(fsl_qdma, status + FSL_QDMA_DEDR);
>
> - if (intr) {
> + if (intr)
> dev_err(fsl_qdma->dma_dev.dev, "DMA transaction error!\n");
> - return IRQ_NONE;
> - }
>
> qdma_writel(fsl_qdma, FSL_QDMA_DEDR_CLEAR, status + FSL_QDMA_DEDR);
> return IRQ_HANDLED;
> --
> 1.7.1
--
~Vinod
^ permalink raw reply
* Re: [V3 1/2] dmaengine: fsl-qdma: fixed the source/destination descriptor format
From: Vinod Koul @ 2019-06-04 12:06 UTC (permalink / raw)
To: Peng Ma; +Cc: dan.j.williams, dmaengine, linux-kernel
In-Reply-To: <20190522032103.13713-1-peng.ma@nxp.com>
On 22-05-19, 03:21, Peng Ma wrote:
> CMD of Source/Destination descriptor format should be lower of
> struct fsl_qdma_engine number data address.
Applied, thanks
--
~Vinod
^ permalink raw reply
* Re: [PATCH] dmaengine: dmatest: Add support for completion polling
From: Peter Ujfalusi @ 2019-06-03 7:05 UTC (permalink / raw)
To: vkoul; +Cc: dan.j.williams, dmaengine, andriy.shevchenko
In-Reply-To: <4f327f4a-9e3d-c9d2-fe48-14e492b07417@ti.com>
Hi,
On 31/05/2019 9.54, Peter Ujfalusi wrote:
>
> On 29/05/2019 11.37, Peter Ujfalusi wrote:
>> With the polled parameter the DMA drivers can be tested if they can work
>> correctly when no completion is requested (no DMA_PREP_INTERRUPT and no
>> callback is provided).
>>
>> If polled mode is selected then use dma_sync_wait() to execute the test
>> iteration instead of relying on the completion callback.
>>
>> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
>> ---
>> drivers/dma/dmatest.c | 35 ++++++++++++++++++++++++++++-------
>> 1 file changed, 28 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
>> index b96814a7dceb..088086d041e9 100644
>> --- a/drivers/dma/dmatest.c
>> +++ b/drivers/dma/dmatest.c
>> @@ -75,6 +75,10 @@ static bool norandom;
>> module_param(norandom, bool, 0644);
>> MODULE_PARM_DESC(norandom, "Disable random offset setup (default: random)");
>>
>> +static bool polled;
>> +module_param(polled, bool, S_IRUGO | S_IWUSR);
>> +MODULE_PARM_DESC(polled, "Use polling for completion instead of interrupts");
>> +
>> static bool verbose;
>> module_param(verbose, bool, S_IRUGO | S_IWUSR);
>> MODULE_PARM_DESC(verbose, "Enable \"success\" result messages (default: off)");
>> @@ -113,6 +117,7 @@ struct dmatest_params {
>> bool norandom;
>> int alignment;
>> unsigned int transfer_size;
>> + bool polled;
>> };
>>
>> /**
>> @@ -654,7 +659,10 @@ static int dmatest_func(void *data)
>> /*
>> * src and dst buffers are freed by ourselves below
>> */
>> - flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
>> + if (params->polled)
>> + flags = DMA_CTRL_ACK;
>> + else
>> + flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
>>
>> ktime = ktime_get();
>> while (!kthread_should_stop()
>> @@ -783,8 +791,10 @@ static int dmatest_func(void *data)
>> }
>>
>> done->done = false;
>> - tx->callback = dmatest_callback;
>> - tx->callback_param = done;
>> + if (!params->polled) {
>> + tx->callback = dmatest_callback;
>> + tx->callback_param = done;
>> + }
>> cookie = tx->tx_submit(tx);
>>
>> if (dma_submit_error(cookie)) {
>> @@ -793,12 +803,22 @@ static int dmatest_func(void *data)
>> msleep(100);
>> goto error_unmap_continue;
>> }
>> - dma_async_issue_pending(chan);
>>
>> - wait_event_freezable_timeout(thread->done_wait, done->done,
>> - msecs_to_jiffies(params->timeout));
>> + if (params->polled) {
>> + status = dma_sync_wait(chan, cookie);
>> + dmaengine_terminate_sync(chan);
>> + if (status == DMA_COMPLETE)
>> + done->done = true;
>
> I think the main question is how polling for completion should be
> handled when client does not request for completion interrupt, thus we
> will have no callback in the DMA driver when the transfer is completed.
>
> If DMA_PREP_INTERRUPT is set for the tx_descriptor then the polling will
> wait until the DMA driver internally receives the interrupt that the
> transfer is done and sets the cookie to completed state.
>
> However if DMA_PREP_INTERRUPT is not set, the DMA driver will not get
> notification from the HW that is the transfer is done, the only way to
> know is to check the tx_status and based on the residue (if it is 0 then
> it is done) decide what to tell the client.
>
> Should the client call dmaengine_terminate_* after the polling returned
> unconditionally to free up the descriptor?
This is how omap-dma is handling the polled memcpy support.
> Or client should only call dmaengine_terminate_* in case the polling
> returned with !DMA_COMPLETE and the DMA driver must clean things up
> before returning if the transfer is completed (residue == 0)?
>
>> + } else {
>> + dma_async_issue_pending(chan);
>> +
>> + wait_event_freezable_timeout(thread->done_wait,
>> + done->done,
>> + msecs_to_jiffies(params->timeout));
>>
>> - status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
>> + status = dma_async_is_tx_complete(chan, cookie, NULL,
>> + NULL);
>> + }
>>
>> if (!done->done) {
>> result("test timed out", total_tests, src->off, dst->off,
>> @@ -1068,6 +1088,7 @@ static void add_threaded_test(struct dmatest_info *info)
>> params->norandom = norandom;
>> params->alignment = alignment;
>> params->transfer_size = transfer_size;
>> + params->polled = polled;
>>
>> request_channels(info, DMA_MEMCPY);
>> request_channels(info, DMA_MEMSET);
>>
>
> - Péter
>
> Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
> Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
>
- Péter
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
^ permalink raw reply
* [PATCH AUTOSEL 4.4 52/56] dmaengine: idma64: Use actual device for DMA transfers
From: Sasha Levin @ 2019-06-01 13:25 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Andy Shevchenko, Mark Brown, Greg Kroah-Hartman, Vinod Koul,
Sasha Levin, dmaengine, linux-spi, linux-serial
In-Reply-To: <20190601132600.27427-1-sashal@kernel.org>
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
[ Upstream commit 5ba846b1ee0792f5a596b9b0b86d6e8cdebfab06 ]
Intel IOMMU, when enabled, tries to find the domain of the device,
assuming it's a PCI one, during DMA operations, such as mapping or
unmapping. Since we are splitting the actual PCI device to couple of
children via MFD framework (see drivers/mfd/intel-lpss.c for details),
the DMA device appears to be a platform one, and thus not an actual one
that performs DMA. In a such situation IOMMU can't find or allocate
a proper domain for its operations. As a result, all DMA operations are
failed.
In order to fix this, supply parent of the platform device
to the DMA engine framework and fix filter functions accordingly.
We may rely on the fact that parent is a real PCI device, because no
other configuration is present in the wild.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: Mark Brown <broonie@kernel.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> [for tty parts]
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/dma/idma64.c | 6 ++++--
drivers/dma/idma64.h | 2 ++
drivers/spi/spi-pxa2xx.c | 7 +------
drivers/tty/serial/8250/8250_dw.c | 4 ++--
4 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/drivers/dma/idma64.c b/drivers/dma/idma64.c
index 7d56b47e4fcfd..25e25b64bc89d 100644
--- a/drivers/dma/idma64.c
+++ b/drivers/dma/idma64.c
@@ -594,7 +594,7 @@ static int idma64_probe(struct idma64_chip *chip)
idma64->dma.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
idma64->dma.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
- idma64->dma.dev = chip->dev;
+ idma64->dma.dev = chip->sysdev;
ret = dma_async_device_register(&idma64->dma);
if (ret)
@@ -632,6 +632,7 @@ static int idma64_platform_probe(struct platform_device *pdev)
{
struct idma64_chip *chip;
struct device *dev = &pdev->dev;
+ struct device *sysdev = dev->parent;
struct resource *mem;
int ret;
@@ -648,11 +649,12 @@ static int idma64_platform_probe(struct platform_device *pdev)
if (IS_ERR(chip->regs))
return PTR_ERR(chip->regs);
- ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+ ret = dma_coerce_mask_and_coherent(sysdev, DMA_BIT_MASK(64));
if (ret)
return ret;
chip->dev = dev;
+ chip->sysdev = sysdev;
ret = idma64_probe(chip);
if (ret)
diff --git a/drivers/dma/idma64.h b/drivers/dma/idma64.h
index f6aeff0af8a52..e40c69bd1fb52 100644
--- a/drivers/dma/idma64.h
+++ b/drivers/dma/idma64.h
@@ -215,12 +215,14 @@ static inline void idma64_writel(struct idma64 *idma64, int offset, u32 value)
/**
* struct idma64_chip - representation of iDMA 64-bit controller hardware
* @dev: struct device of the DMA controller
+ * @sysdev: struct device of the physical device that does DMA
* @irq: irq line
* @regs: memory mapped I/O space
* @idma64: struct idma64 that is filed by idma64_probe()
*/
struct idma64_chip {
struct device *dev;
+ struct device *sysdev;
int irq;
void __iomem *regs;
struct idma64 *idma64;
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index 3cac73e4c3e4a..29c0c135fa6f9 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -1367,12 +1367,7 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
static bool pxa2xx_spi_idma_filter(struct dma_chan *chan, void *param)
{
- struct device *dev = param;
-
- if (dev != chan->device->dev->parent)
- return false;
-
- return true;
+ return param == chan->device->dev;
}
static struct pxa2xx_spi_master *
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index a30d68c4b6897..039837db65fcc 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -258,7 +258,7 @@ static bool dw8250_fallback_dma_filter(struct dma_chan *chan, void *param)
static bool dw8250_idma_filter(struct dma_chan *chan, void *param)
{
- return param == chan->device->dev->parent;
+ return param == chan->device->dev;
}
static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
@@ -290,7 +290,7 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
data->uart_16550_compatible = true;
}
- /* Platforms with iDMA */
+ /* Platforms with iDMA 64-bit */
if (platform_get_resource_byname(to_platform_device(p->dev),
IORESOURCE_MEM, "lpss_priv")) {
p->set_termios = dw8250_set_termios;
--
2.20.1
^ permalink raw reply related
* Re: [PATCH] dmaengine: dmatest: Add support for completion polling
From: Peter Ujfalusi @ 2019-05-31 6:54 UTC (permalink / raw)
To: vkoul; +Cc: dan.j.williams, dmaengine, andriy.shevchenko
In-Reply-To: <20190529083724.18182-1-peter.ujfalusi@ti.com>
On 29/05/2019 11.37, Peter Ujfalusi wrote:
> With the polled parameter the DMA drivers can be tested if they can work
> correctly when no completion is requested (no DMA_PREP_INTERRUPT and no
> callback is provided).
>
> If polled mode is selected then use dma_sync_wait() to execute the test
> iteration instead of relying on the completion callback.
>
> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
> ---
> drivers/dma/dmatest.c | 35 ++++++++++++++++++++++++++++-------
> 1 file changed, 28 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
> index b96814a7dceb..088086d041e9 100644
> --- a/drivers/dma/dmatest.c
> +++ b/drivers/dma/dmatest.c
> @@ -75,6 +75,10 @@ static bool norandom;
> module_param(norandom, bool, 0644);
> MODULE_PARM_DESC(norandom, "Disable random offset setup (default: random)");
>
> +static bool polled;
> +module_param(polled, bool, S_IRUGO | S_IWUSR);
> +MODULE_PARM_DESC(polled, "Use polling for completion instead of interrupts");
> +
> static bool verbose;
> module_param(verbose, bool, S_IRUGO | S_IWUSR);
> MODULE_PARM_DESC(verbose, "Enable \"success\" result messages (default: off)");
> @@ -113,6 +117,7 @@ struct dmatest_params {
> bool norandom;
> int alignment;
> unsigned int transfer_size;
> + bool polled;
> };
>
> /**
> @@ -654,7 +659,10 @@ static int dmatest_func(void *data)
> /*
> * src and dst buffers are freed by ourselves below
> */
> - flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
> + if (params->polled)
> + flags = DMA_CTRL_ACK;
> + else
> + flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
>
> ktime = ktime_get();
> while (!kthread_should_stop()
> @@ -783,8 +791,10 @@ static int dmatest_func(void *data)
> }
>
> done->done = false;
> - tx->callback = dmatest_callback;
> - tx->callback_param = done;
> + if (!params->polled) {
> + tx->callback = dmatest_callback;
> + tx->callback_param = done;
> + }
> cookie = tx->tx_submit(tx);
>
> if (dma_submit_error(cookie)) {
> @@ -793,12 +803,22 @@ static int dmatest_func(void *data)
> msleep(100);
> goto error_unmap_continue;
> }
> - dma_async_issue_pending(chan);
>
> - wait_event_freezable_timeout(thread->done_wait, done->done,
> - msecs_to_jiffies(params->timeout));
> + if (params->polled) {
> + status = dma_sync_wait(chan, cookie);
> + dmaengine_terminate_sync(chan);
> + if (status == DMA_COMPLETE)
> + done->done = true;
I think the main question is how polling for completion should be
handled when client does not request for completion interrupt, thus we
will have no callback in the DMA driver when the transfer is completed.
If DMA_PREP_INTERRUPT is set for the tx_descriptor then the polling will
wait until the DMA driver internally receives the interrupt that the
transfer is done and sets the cookie to completed state.
However if DMA_PREP_INTERRUPT is not set, the DMA driver will not get
notification from the HW that is the transfer is done, the only way to
know is to check the tx_status and based on the residue (if it is 0 then
it is done) decide what to tell the client.
Should the client call dmaengine_terminate_* after the polling returned
unconditionally to free up the descriptor?
Or client should only call dmaengine_terminate_* in case the polling
returned with !DMA_COMPLETE and the DMA driver must clean things up
before returning if the transfer is completed (residue == 0)?
> + } else {
> + dma_async_issue_pending(chan);
> +
> + wait_event_freezable_timeout(thread->done_wait,
> + done->done,
> + msecs_to_jiffies(params->timeout));
>
> - status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
> + status = dma_async_is_tx_complete(chan, cookie, NULL,
> + NULL);
> + }
>
> if (!done->done) {
> result("test timed out", total_tests, src->off, dst->off,
> @@ -1068,6 +1088,7 @@ static void add_threaded_test(struct dmatest_info *info)
> params->norandom = norandom;
> params->alignment = alignment;
> params->transfer_size = transfer_size;
> + params->polled = polled;
>
> request_channels(info, DMA_MEMCPY);
> request_channels(info, DMA_MEMSET);
>
- Péter
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
^ permalink raw reply
* Re: [PATCH v1] dmaengine: tegra-apb: Error out if DMA_PREP_INTERRUPT flag is unset
From: Dmitry Osipenko @ 2019-05-30 17:32 UTC (permalink / raw)
To: Jon Hunter, Laxman Dewangan, Vinod Koul, Thierry Reding,
Ben Dooks
Cc: dmaengine, linux-tegra, linux-kernel
In-Reply-To: <9b0e0d20-6386-a38a-1347-4264d249cb44@nvidia.com>
30.05.2019 15:01, Jon Hunter пишет:
>
> On 29/05/2019 22:43, Dmitry Osipenko wrote:
>> Apparently driver was never tested with DMA_PREP_INTERRUPT flag being
>> unset since it completely disables interrupt handling instead of skipping
>> the callbacks invocations, hence putting channel into unusable state.
>>
>> The flag is always set by all of kernel drivers that use APB DMA, so let's
>> error out in otherwise case for consistency. It won't be difficult to
>> support that case properly if ever will be needed.
>>
>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>> ---
>> drivers/dma/tegra20-apb-dma.c | 12 ++++++++++--
>> 1 file changed, 10 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
>> index cf462b1abc0b..2c84a660ba36 100644
>> --- a/drivers/dma/tegra20-apb-dma.c
>> +++ b/drivers/dma/tegra20-apb-dma.c
>> @@ -988,8 +988,12 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg(
>> csr |= tdc->slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
>> }
>>
>> - if (flags & DMA_PREP_INTERRUPT)
>> + if (flags & DMA_PREP_INTERRUPT) {
>> csr |= TEGRA_APBDMA_CSR_IE_EOC;
>> + } else {
>> + WARN_ON_ONCE(1);
>> + return NULL;
>> + }
>>
>> apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1;
>>
>> @@ -1131,8 +1135,12 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
>> csr |= tdc->slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
>> }
>>
>> - if (flags & DMA_PREP_INTERRUPT)
>> + if (flags & DMA_PREP_INTERRUPT) {
>> csr |= TEGRA_APBDMA_CSR_IE_EOC;
>> + } else {
>> + WARN_ON_ONCE(1);
>> + return NULL;
>> + }
>>
>> apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1;
>
> Looks good to me.
>
> Acked-by: Jon Hunter <jonathanh@nvidia.com>
>
> Cheers
> Jon
>
Thanks
^ permalink raw reply
* Re: [PATCH v1] dmaengine: tegra-apb: Error out if DMA_PREP_INTERRUPT flag is unset
From: Jon Hunter @ 2019-05-30 12:01 UTC (permalink / raw)
To: Dmitry Osipenko, Laxman Dewangan, Vinod Koul, Thierry Reding,
Ben Dooks
Cc: dmaengine, linux-tegra, linux-kernel
In-Reply-To: <20190529214355.15339-1-digetx@gmail.com>
On 29/05/2019 22:43, Dmitry Osipenko wrote:
> Apparently driver was never tested with DMA_PREP_INTERRUPT flag being
> unset since it completely disables interrupt handling instead of skipping
> the callbacks invocations, hence putting channel into unusable state.
>
> The flag is always set by all of kernel drivers that use APB DMA, so let's
> error out in otherwise case for consistency. It won't be difficult to
> support that case properly if ever will be needed.
>
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
> drivers/dma/tegra20-apb-dma.c | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
> index cf462b1abc0b..2c84a660ba36 100644
> --- a/drivers/dma/tegra20-apb-dma.c
> +++ b/drivers/dma/tegra20-apb-dma.c
> @@ -988,8 +988,12 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg(
> csr |= tdc->slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
> }
>
> - if (flags & DMA_PREP_INTERRUPT)
> + if (flags & DMA_PREP_INTERRUPT) {
> csr |= TEGRA_APBDMA_CSR_IE_EOC;
> + } else {
> + WARN_ON_ONCE(1);
> + return NULL;
> + }
>
> apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1;
>
> @@ -1131,8 +1135,12 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
> csr |= tdc->slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
> }
>
> - if (flags & DMA_PREP_INTERRUPT)
> + if (flags & DMA_PREP_INTERRUPT) {
> csr |= TEGRA_APBDMA_CSR_IE_EOC;
> + } else {
> + WARN_ON_ONCE(1);
> + return NULL;
> + }
>
> apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1;
Looks good to me.
Acked-by: Jon Hunter <jonathanh@nvidia.com>
Cheers
Jon
--
nvpublic
^ permalink raw reply
* Re: [PATCH 2/2] serial: 8250-mtk: modify uart DMA rx
From: Long Cheng @ 2019-05-30 9:34 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Vinod Koul, Randy Dunlap, Rob Herring, Mark Rutland, Ryder Lee,
Sean Wang, Nicolas Boichat, Matthias Brugger, Dan Williams,
Greg Kroah-Hartman, Jiri Slaby, Sean Wang, dmaengine, devicetree,
linux-arm-kernel, linux-mediatek, linux-kernel, linux-serial,
srv_heupstream, Yingjoe Chen, YT Shen, Zhenbao Liu, Long Cheng,
Changqi Hu
In-Reply-To: <1558596909-14084-3-git-send-email-long.cheng@mediatek.com>
On Thu, 2019-05-23 at 15:35 +0800, Long Cheng wrote:
Hi Greg,
Just a gentle ping!
thanks.
> Modify uart rx and complete for DMA
>
> Signed-off-by: Long Cheng <long.cheng@mediatek.com>
> ---
> drivers/tty/serial/8250/8250_mtk.c | 49 +++++++++++++++---------------------
> 1 file changed, 20 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
> index 417c7c8..f470ded 100644
> --- a/drivers/tty/serial/8250/8250_mtk.c
> +++ b/drivers/tty/serial/8250/8250_mtk.c
> @@ -47,7 +47,6 @@
> #define MTK_UART_DMA_EN_RX 0x5
>
> #define MTK_UART_ESCAPE_CHAR 0x77 /* Escape char added under sw fc */
> -#define MTK_UART_TX_SIZE UART_XMIT_SIZE
> #define MTK_UART_RX_SIZE 0x8000
> #define MTK_UART_TX_TRIGGER 1
> #define MTK_UART_RX_TRIGGER MTK_UART_RX_SIZE
> @@ -89,28 +88,30 @@ static void mtk8250_dma_rx_complete(void *param)
> struct mtk8250_data *data = up->port.private_data;
> struct tty_port *tty_port = &up->port.state->port;
> struct dma_tx_state state;
> + int copied, total, cnt;
> unsigned char *ptr;
> - int copied;
>
> - dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr,
> - dma->rx_size, DMA_FROM_DEVICE);
> + if (data->rx_status == DMA_RX_SHUTDOWN)
> + return;
>
> dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
> + total = dma->rx_size - state.residue;
> + cnt = total;
>
> - if (data->rx_status == DMA_RX_SHUTDOWN)
> - return;
> + if ((data->rx_pos + cnt) > dma->rx_size)
> + cnt = dma->rx_size - data->rx_pos;
>
> - if ((data->rx_pos + state.residue) <= dma->rx_size) {
> - ptr = (unsigned char *)(data->rx_pos + dma->rx_buf);
> - copied = tty_insert_flip_string(tty_port, ptr, state.residue);
> - } else {
> - ptr = (unsigned char *)(data->rx_pos + dma->rx_buf);
> - copied = tty_insert_flip_string(tty_port, ptr,
> - dma->rx_size - data->rx_pos);
> + ptr = (unsigned char *)(data->rx_pos + dma->rx_buf);
> + copied = tty_insert_flip_string(tty_port, ptr, cnt);
> + data->rx_pos += cnt;
> +
> + if (total > cnt) {
> ptr = (unsigned char *)(dma->rx_buf);
> - copied += tty_insert_flip_string(tty_port, ptr,
> - data->rx_pos + state.residue - dma->rx_size);
> + cnt = total - cnt;
> + copied += tty_insert_flip_string(tty_port, ptr, cnt);
> + data->rx_pos = cnt;
> }
> +
> up->port.icount.rx += copied;
>
> tty_flip_buffer_push(tty_port);
> @@ -121,9 +122,7 @@ static void mtk8250_dma_rx_complete(void *param)
> static void mtk8250_rx_dma(struct uart_8250_port *up)
> {
> struct uart_8250_dma *dma = up->dma;
> - struct mtk8250_data *data = up->port.private_data;
> struct dma_async_tx_descriptor *desc;
> - struct dma_tx_state state;
>
> desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
> dma->rx_size, DMA_DEV_TO_MEM,
> @@ -138,12 +137,6 @@ static void mtk8250_rx_dma(struct uart_8250_port *up)
>
> dma->rx_cookie = dmaengine_submit(desc);
>
> - dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
> - data->rx_pos = state.residue;
> -
> - dma_sync_single_for_device(dma->rxchan->device->dev, dma->rx_addr,
> - dma->rx_size, DMA_FROM_DEVICE);
> -
> dma_async_issue_pending(dma->rxchan);
> }
>
> @@ -156,13 +149,11 @@ static void mtk8250_dma_enable(struct uart_8250_port *up)
> if (data->rx_status != DMA_RX_START)
> return;
>
> - dma->rxconf.direction = DMA_DEV_TO_MEM;
> - dma->rxconf.src_addr_width = dma->rx_size / 1024;
> - dma->rxconf.src_addr = dma->rx_addr;
> + dma->rxconf.src_port_window_size = dma->rx_size;
> + dma->rxconf.src_addr = dma->rx_addr;
>
> - dma->txconf.direction = DMA_MEM_TO_DEV;
> - dma->txconf.dst_addr_width = MTK_UART_TX_SIZE / 1024;
> - dma->txconf.dst_addr = dma->tx_addr;
> + dma->txconf.dst_port_window_size = UART_XMIT_SIZE;
> + dma->txconf.dst_addr = dma->tx_addr;
>
> serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR |
> UART_FCR_CLEAR_XMIT);
^ permalink raw reply
* [PATCH v1] dmaengine: tegra-apb: Error out if DMA_PREP_INTERRUPT flag is unset
From: Dmitry Osipenko @ 2019-05-29 21:43 UTC (permalink / raw)
To: Laxman Dewangan, Vinod Koul, Thierry Reding, Jonathan Hunter,
Ben Dooks
Cc: dmaengine, linux-tegra, linux-kernel
Apparently driver was never tested with DMA_PREP_INTERRUPT flag being
unset since it completely disables interrupt handling instead of skipping
the callbacks invocations, hence putting channel into unusable state.
The flag is always set by all of kernel drivers that use APB DMA, so let's
error out in otherwise case for consistency. It won't be difficult to
support that case properly if ever will be needed.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/dma/tegra20-apb-dma.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
index cf462b1abc0b..2c84a660ba36 100644
--- a/drivers/dma/tegra20-apb-dma.c
+++ b/drivers/dma/tegra20-apb-dma.c
@@ -988,8 +988,12 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg(
csr |= tdc->slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
}
- if (flags & DMA_PREP_INTERRUPT)
+ if (flags & DMA_PREP_INTERRUPT) {
csr |= TEGRA_APBDMA_CSR_IE_EOC;
+ } else {
+ WARN_ON_ONCE(1);
+ return NULL;
+ }
apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1;
@@ -1131,8 +1135,12 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
csr |= tdc->slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
}
- if (flags & DMA_PREP_INTERRUPT)
+ if (flags & DMA_PREP_INTERRUPT) {
csr |= TEGRA_APBDMA_CSR_IE_EOC;
+ } else {
+ WARN_ON_ONCE(1);
+ return NULL;
+ }
apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1;
--
2.21.0
^ permalink raw reply related
* [PATCH v3 0/8] add edma2 for i.mx7ulp
From: yibin.gong @ 2019-05-29 9:08 UTC (permalink / raw)
To: robh, shawnguo, s.hauer, festevam, mark.rutland, vkoul,
dan.j.williams
Cc: linux-imx, linux-arm-kernel, linux-kernel, dmaengine, devicetree,
kernel
From: Robin Gong <yibin.gong@nxp.com>
This patch set add new version of edma for i.mx7ulp, the main changes
are as belows:
1. only one dmamux.
2. another clock dma_clk except dmamux clk.
3. 16 independent interrupts instead of only one interrupt for
all channels.
For the first change, need modify fsl-edma-common.c and mcf-edma,
so create the first two patches to prepare without any function impact.
For the third change, need request single irq for every channel with
the legacy handler. But actually 2 dma channels share one interrupt(16
channel interrupts, but 32 channels.),ch0/ch16,ch1/ch17... For now, just
simply request irq without IRQF_SHARED flag, since 16 channels are enough
on i.mx7ulp whose M4 domain own some peripherals.
change from v1:
1. check .data of 'of_device_id' in probe instead of compatible name.
change from v2:
1. move the difference between edma and edma2 into driver data so that
no need version checking in fsl-edma.c.
Robin Gong (8):
dmaengine: fsl-edma: add dmamux_nr for next version
dmaengine: mcf-edma: update to 'dmamux_nr'
dmaengine: fsl-edma-common: move dmamux register to another single
function
dmaengine: fsl-edma-common: version check for v2 instead
dmaengine: fsl-edma: add drvdata for vf610
dt-bindings: dma: fsl-edma: add new i.mx7ulp-edma
dmaengine: fsl-edma: add i.mx7ulp edma2 version support
ARM: dts: imx7ulp: add edma device node
Documentation/devicetree/bindings/dma/fsl-edma.txt | 44 +++++++-
arch/arm/boot/dts/imx7ulp.dtsi | 28 ++++++
drivers/dma/fsl-edma-common.c | 74 +++++++++-----
drivers/dma/fsl-edma-common.h | 13 +++
drivers/dma/fsl-edma.c | 112 ++++++++++++++++++---
drivers/dma/mcf-edma.c | 1 +
6 files changed, 230 insertions(+), 42 deletions(-)
--
2.7.4
^ permalink raw reply
* [PATCH v3 3/8] dmaengine: fsl-edma-common: move dmamux register to another single function
From: yibin.gong @ 2019-05-29 9:08 UTC (permalink / raw)
To: robh, shawnguo, s.hauer, festevam, mark.rutland, vkoul,
dan.j.williams
Cc: linux-imx, linux-arm-kernel, linux-kernel, dmaengine, devicetree,
kernel
In-Reply-To: <20190529090848.34350-1-yibin.gong@nxp.com>
From: Robin Gong <yibin.gong@nxp.com>
Prepare for edmav2 on i.mx7ulp whose dmamux register is 32bit. No function
impacted.
Signed-off-by: Robin Gong <yibin.gong@nxp.com>
---
drivers/dma/fsl-edma-common.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c
index c9a17fc..bb24251 100644
--- a/drivers/dma/fsl-edma-common.c
+++ b/drivers/dma/fsl-edma-common.c
@@ -77,6 +77,19 @@ void fsl_edma_disable_request(struct fsl_edma_chan *fsl_chan)
}
EXPORT_SYMBOL_GPL(fsl_edma_disable_request);
+static void mux_configure8(struct fsl_edma_chan *fsl_chan, void __iomem *addr,
+ u32 off, u32 slot, bool enable)
+{
+ u8 val8;
+
+ if (enable)
+ val8 = EDMAMUX_CHCFG_ENBL | slot;
+ else
+ val8 = EDMAMUX_CHCFG_DIS;
+
+ iowrite8(val8, addr + off);
+}
+
void fsl_edma_chan_mux(struct fsl_edma_chan *fsl_chan,
unsigned int slot, bool enable)
{
@@ -89,10 +102,7 @@ void fsl_edma_chan_mux(struct fsl_edma_chan *fsl_chan,
muxaddr = fsl_chan->edma->muxbase[ch / chans_per_mux];
slot = EDMAMUX_CHCFG_SOURCE(slot);
- if (enable)
- iowrite8(EDMAMUX_CHCFG_ENBL | slot, muxaddr + ch_off);
- else
- iowrite8(EDMAMUX_CHCFG_DIS, muxaddr + ch_off);
+ mux_configure8(fsl_chan, muxaddr, ch_off, slot, enable);
}
EXPORT_SYMBOL_GPL(fsl_edma_chan_mux);
--
2.7.4
^ permalink raw reply related
* [PATCH v3 4/8] dmaengine: fsl-edma-common: version check for v2 instead
From: yibin.gong @ 2019-05-29 9:08 UTC (permalink / raw)
To: robh, shawnguo, s.hauer, festevam, mark.rutland, vkoul,
dan.j.williams
Cc: linux-imx, linux-arm-kernel, linux-kernel, dmaengine, devicetree,
kernel
In-Reply-To: <20190529090848.34350-1-yibin.gong@nxp.com>
From: Robin Gong <yibin.gong@nxp.com>
The next v3 i.mx7ulp edma is based on v1, so change version
check logic for v2 instead.
Signed-off-by: Robin Gong <yibin.gong@nxp.com>
---
drivers/dma/fsl-edma-common.c | 40 ++++++++++++++++++++--------------------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c
index bb24251..45d70d3 100644
--- a/drivers/dma/fsl-edma-common.c
+++ b/drivers/dma/fsl-edma-common.c
@@ -657,26 +657,26 @@ void fsl_edma_setup_regs(struct fsl_edma_engine *edma)
edma->regs.erql = edma->membase + EDMA_ERQ;
edma->regs.eeil = edma->membase + EDMA_EEI;
- edma->regs.serq = edma->membase + ((edma->version == v1) ?
- EDMA_SERQ : EDMA64_SERQ);
- edma->regs.cerq = edma->membase + ((edma->version == v1) ?
- EDMA_CERQ : EDMA64_CERQ);
- edma->regs.seei = edma->membase + ((edma->version == v1) ?
- EDMA_SEEI : EDMA64_SEEI);
- edma->regs.ceei = edma->membase + ((edma->version == v1) ?
- EDMA_CEEI : EDMA64_CEEI);
- edma->regs.cint = edma->membase + ((edma->version == v1) ?
- EDMA_CINT : EDMA64_CINT);
- edma->regs.cerr = edma->membase + ((edma->version == v1) ?
- EDMA_CERR : EDMA64_CERR);
- edma->regs.ssrt = edma->membase + ((edma->version == v1) ?
- EDMA_SSRT : EDMA64_SSRT);
- edma->regs.cdne = edma->membase + ((edma->version == v1) ?
- EDMA_CDNE : EDMA64_CDNE);
- edma->regs.intl = edma->membase + ((edma->version == v1) ?
- EDMA_INTR : EDMA64_INTL);
- edma->regs.errl = edma->membase + ((edma->version == v1) ?
- EDMA_ERR : EDMA64_ERRL);
+ edma->regs.serq = edma->membase + ((edma->version == v2) ?
+ EDMA64_SERQ : EDMA_SERQ);
+ edma->regs.cerq = edma->membase + ((edma->version == v2) ?
+ EDMA64_CERQ : EDMA_CERQ);
+ edma->regs.seei = edma->membase + ((edma->version == v2) ?
+ EDMA64_SEEI : EDMA_SEEI);
+ edma->regs.ceei = edma->membase + ((edma->version == v2) ?
+ EDMA64_CEEI : EDMA_CEEI);
+ edma->regs.cint = edma->membase + ((edma->version == v2) ?
+ EDMA64_CINT : EDMA_CINT);
+ edma->regs.cerr = edma->membase + ((edma->version == v2) ?
+ EDMA64_CERR : EDMA_CERR);
+ edma->regs.ssrt = edma->membase + ((edma->version == v2) ?
+ EDMA64_SSRT : EDMA_SSRT);
+ edma->regs.cdne = edma->membase + ((edma->version == v2) ?
+ EDMA64_CDNE : EDMA_CDNE);
+ edma->regs.intl = edma->membase + ((edma->version == v2) ?
+ EDMA64_INTL : EDMA_INTR);
+ edma->regs.errl = edma->membase + ((edma->version == v2) ?
+ EDMA64_ERRL : EDMA_ERR);
if (edma->version == v2) {
edma->regs.erqh = edma->membase + EDMA64_ERQH;
--
2.7.4
^ permalink raw reply related
* [PATCH v3 5/8] dmaengine: fsl-edma: add drvdata for vf610
From: yibin.gong @ 2019-05-29 9:08 UTC (permalink / raw)
To: robh, shawnguo, s.hauer, festevam, mark.rutland, vkoul,
dan.j.williams
Cc: linux-imx, linux-arm-kernel, linux-kernel, dmaengine, devicetree,
kernel
In-Reply-To: <20190529090848.34350-1-yibin.gong@nxp.com>
From: Robin Gong <yibin.gong@nxp.com>
There are some differences between vf610 and next i.mx7ulp. Put such
differences into static driver data for distiguish easily in driver.
Signed-off-by: Robin Gong <yibin.gong@nxp.com>
---
drivers/dma/fsl-edma-common.h | 10 ++++++++++
drivers/dma/fsl-edma.c | 36 +++++++++++++++++++++++++++---------
2 files changed, 37 insertions(+), 9 deletions(-)
diff --git a/drivers/dma/fsl-edma-common.h b/drivers/dma/fsl-edma-common.h
index 21a9cfd..014ab74 100644
--- a/drivers/dma/fsl-edma-common.h
+++ b/drivers/dma/fsl-edma-common.h
@@ -7,6 +7,7 @@
#define _FSL_EDMA_COMMON_H_
#include <linux/dma-direction.h>
+#include <linux/platform_device.h>
#include "virt-dma.h"
#define EDMA_CR_EDBG BIT(1)
@@ -140,6 +141,14 @@ enum edma_version {
v2, /* 64ch Coldfire */
};
+struct fsl_edma_drvdata {
+ enum edma_version version;
+ u32 dmamuxs;
+ bool has_dmaclk;
+ int (*setup_irq)(struct platform_device *pdev,
+ struct fsl_edma_engine *fsl_edma);
+};
+
struct fsl_edma_engine {
struct dma_device dma_dev;
void __iomem *membase;
@@ -147,6 +156,7 @@ struct fsl_edma_engine {
struct clk *muxclk[DMAMUX_NR];
u32 dmamux_nr;
struct mutex fsl_edma_mutex;
+ const struct fsl_edma_drvdata *drvdata;
u32 n_chans;
int txirq;
int errirq;
diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c
index 7b65ef4..cf18301 100644
--- a/drivers/dma/fsl-edma.c
+++ b/drivers/dma/fsl-edma.c
@@ -184,16 +184,39 @@ static void fsl_disable_clocks(struct fsl_edma_engine *fsl_edma, int nr_clocks)
clk_disable_unprepare(fsl_edma->muxclk[i]);
}
+static struct fsl_edma_drvdata vf610_data = {
+ .version = v1,
+ .dmamuxs = DMAMUX_NR,
+ .has_dmaclk = false,
+ .setup_irq = fsl_edma_irq_init,
+};
+
+static const struct of_device_id fsl_edma_dt_ids[] = {
+ { .compatible = "fsl,vf610-edma", .data = &vf610_data},
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids);
+
static int fsl_edma_probe(struct platform_device *pdev)
{
+ const struct of_device_id *of_id =
+ of_match_device(fsl_edma_dt_ids, &pdev->dev);
struct device_node *np = pdev->dev.of_node;
struct fsl_edma_engine *fsl_edma;
+ const struct fsl_edma_drvdata *drvdata = NULL;
struct fsl_edma_chan *fsl_chan;
struct edma_regs *regs;
struct resource *res;
int len, chans;
int ret, i;
+ if (of_id)
+ drvdata = of_id->data;
+ if (!drvdata) {
+ dev_err(&pdev->dev, "unable to find driver data\n");
+ return -EINVAL;
+ }
+
ret = of_property_read_u32(np, "dma-channels", &chans);
if (ret) {
dev_err(&pdev->dev, "Can't get dma-channels.\n");
@@ -205,8 +228,9 @@ static int fsl_edma_probe(struct platform_device *pdev)
if (!fsl_edma)
return -ENOMEM;
- fsl_edma->version = v1;
- fsl_edma->dmamux_nr = DMAMUX_NR;
+ fsl_edma->drvdata = drvdata;
+ fsl_edma->version = drvdata->version;
+ fsl_edma->dmamux_nr = drvdata->dmamuxs;
fsl_edma->n_chans = chans;
mutex_init(&fsl_edma->fsl_edma_mutex);
@@ -264,7 +288,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
}
edma_writel(fsl_edma, ~0, regs->intl);
- ret = fsl_edma_irq_init(pdev, fsl_edma);
+ ret = fsl_edma->drvdata->setup_irq(pdev, fsl_edma);
if (ret)
return ret;
@@ -383,12 +407,6 @@ static const struct dev_pm_ops fsl_edma_pm_ops = {
.resume_early = fsl_edma_resume_early,
};
-static const struct of_device_id fsl_edma_dt_ids[] = {
- { .compatible = "fsl,vf610-edma", },
- { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids);
-
static struct platform_driver fsl_edma_driver = {
.driver = {
.name = "fsl-edma",
--
2.7.4
^ permalink raw reply related
* [PATCH v3 7/8] dmaengine: fsl-edma: add i.mx7ulp edma2 version support
From: yibin.gong @ 2019-05-29 9:08 UTC (permalink / raw)
To: robh, shawnguo, s.hauer, festevam, mark.rutland, vkoul,
dan.j.williams
Cc: linux-imx, linux-arm-kernel, linux-kernel, dmaengine, devicetree,
kernel
In-Reply-To: <20190529090848.34350-1-yibin.gong@nxp.com>
From: Robin Gong <yibin.gong@nxp.com>
Add edma2 for i.mx7ulp by version v3, since v2 has already
been used by mcf-edma.
The big changes based on v1 are belows:
1. only one dmamux.
2. another clock dma_clk except dmamux clk.
3. 16 independent interrupts instead of only one interrupt for
all channels.
Signed-off-by: Robin Gong <yibin.gong@nxp.com>
---
drivers/dma/fsl-edma-common.c | 18 +++++++++++-
drivers/dma/fsl-edma-common.h | 3 ++
drivers/dma/fsl-edma.c | 67 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 87 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c
index 45d70d3..0d9915c 100644
--- a/drivers/dma/fsl-edma-common.c
+++ b/drivers/dma/fsl-edma-common.c
@@ -90,6 +90,19 @@ static void mux_configure8(struct fsl_edma_chan *fsl_chan, void __iomem *addr,
iowrite8(val8, addr + off);
}
+void mux_configure32(struct fsl_edma_chan *fsl_chan, void __iomem *addr,
+ u32 off, u32 slot, bool enable)
+{
+ u32 val;
+
+ if (enable)
+ val = EDMAMUX_CHCFG_ENBL << 24 | slot;
+ else
+ val = EDMAMUX_CHCFG_DIS;
+
+ iowrite32(val, addr + off * 4);
+}
+
void fsl_edma_chan_mux(struct fsl_edma_chan *fsl_chan,
unsigned int slot, bool enable)
{
@@ -102,7 +115,10 @@ void fsl_edma_chan_mux(struct fsl_edma_chan *fsl_chan,
muxaddr = fsl_chan->edma->muxbase[ch / chans_per_mux];
slot = EDMAMUX_CHCFG_SOURCE(slot);
- mux_configure8(fsl_chan, muxaddr, ch_off, slot, enable);
+ if (fsl_chan->edma->version == v3)
+ mux_configure32(fsl_chan, muxaddr, ch_off, slot, enable);
+ else
+ mux_configure8(fsl_chan, muxaddr, ch_off, slot, enable);
}
EXPORT_SYMBOL_GPL(fsl_edma_chan_mux);
diff --git a/drivers/dma/fsl-edma-common.h b/drivers/dma/fsl-edma-common.h
index 014ab74..07482d2 100644
--- a/drivers/dma/fsl-edma-common.h
+++ b/drivers/dma/fsl-edma-common.h
@@ -125,6 +125,7 @@ struct fsl_edma_chan {
dma_addr_t dma_dev_addr;
u32 dma_dev_size;
enum dma_data_direction dma_dir;
+ char chan_name[16];
};
struct fsl_edma_desc {
@@ -139,6 +140,7 @@ struct fsl_edma_desc {
enum edma_version {
v1, /* 32ch, Vybrid, mpc57x, etc */
v2, /* 64ch Coldfire */
+ v3, /* 32ch, i.mx7ulp */
};
struct fsl_edma_drvdata {
@@ -154,6 +156,7 @@ struct fsl_edma_engine {
void __iomem *membase;
void __iomem *muxbase[DMAMUX_NR];
struct clk *muxclk[DMAMUX_NR];
+ struct clk *dmaclk;
u32 dmamux_nr;
struct mutex fsl_edma_mutex;
const struct fsl_edma_drvdata *drvdata;
diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c
index cf18301..45b26d6 100644
--- a/drivers/dma/fsl-edma.c
+++ b/drivers/dma/fsl-edma.c
@@ -165,6 +165,51 @@ fsl_edma_irq_init(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma
return 0;
}
+static int
+fsl_edma2_irq_init(struct platform_device *pdev,
+ struct fsl_edma_engine *fsl_edma)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int i, ret, irq;
+ int count = 0;
+
+ count = of_irq_count(np);
+ dev_info(&pdev->dev, "%s Found %d interrupts\r\n", __func__, count);
+ if (count <= 2) {
+ dev_err(&pdev->dev, "Interrupts in DTS not correct.\n");
+ return -EINVAL;
+ }
+ /*
+ * 16 channel independent interrupts + 1 error interrupt on i.mx7ulp.
+ * 2 channel share one interrupt, for example, ch0/ch16, ch1/ch17...
+ * For now, just simply request irq without IRQF_SHARED flag, since 16
+ * channels are enough on i.mx7ulp whose M4 domain own some peripherals.
+ */
+ for (i = 0; i < count; i++) {
+ irq = platform_get_irq(pdev, i);
+ if (irq < 0)
+ return -ENXIO;
+
+ sprintf(fsl_edma->chans[i].chan_name, "eDMA2-CH%02d", i);
+
+ /* The last IRQ is for eDMA err */
+ if (i == count - 1)
+ ret = devm_request_irq(&pdev->dev, irq,
+ fsl_edma_err_handler,
+ 0, "eDMA2-ERR", fsl_edma);
+ else
+
+ ret = devm_request_irq(&pdev->dev, irq,
+ fsl_edma_tx_handler, 0,
+ fsl_edma->chans[i].chan_name,
+ fsl_edma);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static void fsl_edma_irq_exit(
struct platform_device *pdev, struct fsl_edma_engine *fsl_edma)
{
@@ -191,8 +236,16 @@ static struct fsl_edma_drvdata vf610_data = {
.setup_irq = fsl_edma_irq_init,
};
+static struct fsl_edma_drvdata imx7ulp_data = {
+ .version = v3,
+ .dmamuxs = 1,
+ .has_dmaclk = true,
+ .setup_irq = fsl_edma2_irq_init,
+};
+
static const struct of_device_id fsl_edma_dt_ids[] = {
{ .compatible = "fsl,vf610-edma", .data = &vf610_data},
+ { .compatible = "fsl,imx7ulp-edma", .data = &imx7ulp_data},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids);
@@ -242,6 +295,20 @@ static int fsl_edma_probe(struct platform_device *pdev)
fsl_edma_setup_regs(fsl_edma);
regs = &fsl_edma->regs;
+ if (drvdata->has_dmaclk) {
+ fsl_edma->dmaclk = devm_clk_get(&pdev->dev, "dma");
+ if (IS_ERR(fsl_edma->dmaclk)) {
+ dev_err(&pdev->dev, "Missing DMA block clock.\n");
+ return PTR_ERR(fsl_edma->dmaclk);
+ }
+
+ ret = clk_prepare_enable(fsl_edma->dmaclk);
+ if (ret) {
+ dev_err(&pdev->dev, "DMA clk block failed.\n");
+ return ret;
+ }
+ }
+
for (i = 0; i < fsl_edma->dmamux_nr; i++) {
char clkname[32];
--
2.7.4
^ permalink raw reply related
* [PATCH v3 6/8] dt-bindings: dma: fsl-edma: add new i.mx7ulp-edma
From: yibin.gong @ 2019-05-29 9:08 UTC (permalink / raw)
To: robh, shawnguo, s.hauer, festevam, mark.rutland, vkoul,
dan.j.williams
Cc: linux-imx, linux-arm-kernel, linux-kernel, dmaengine, devicetree,
kernel
In-Reply-To: <20190529090848.34350-1-yibin.gong@nxp.com>
From: Robin Gong <yibin.gong@nxp.com>
More channel interrupts, one more clock, and only one
dmamux on i.mx7ulp-edma.
Signed-off-by: Robin Gong <yibin.gong@nxp.com>
---
Documentation/devicetree/bindings/dma/fsl-edma.txt | 44 +++++++++++++++++++---
1 file changed, 39 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/dma/fsl-edma.txt b/Documentation/devicetree/bindings/dma/fsl-edma.txt
index 97e213e..29dd3cc 100644
--- a/Documentation/devicetree/bindings/dma/fsl-edma.txt
+++ b/Documentation/devicetree/bindings/dma/fsl-edma.txt
@@ -9,15 +9,16 @@ group, DMAMUX0 or DMAMUX1, but not both.
Required properties:
- compatible :
- "fsl,vf610-edma" for eDMA used similar to that on Vybrid vf610 SoC
+ - "fsl,imx7ulp-edma" for eDMA2 used similar to that on i.mx7ulp
- reg : Specifies base physical address(s) and size of the eDMA registers.
The 1st region is eDMA control register's address and size.
The 2nd and the 3rd regions are programmable channel multiplexing
control register's address and size.
- interrupts : A list of interrupt-specifiers, one for each entry in
- interrupt-names.
-- interrupt-names : Should contain:
- "edma-tx" - the transmission interrupt
- "edma-err" - the error interrupt
+ interrupt-names on vf610 similar SoC. But for i.mx7ulp per channel
+ per transmission interrupt, total 16 channel interrupt and 1
+ error interrupt(located in the last), no interrupt-names list on
+ i.mx7ulp for clean on dts.
- #dma-cells : Must be <2>.
The 1st cell specifies the DMAMUX(0 for DMAMUX0 and 1 for DMAMUX1).
Specific request source can only be multiplexed by specific channels
@@ -28,6 +29,7 @@ Required properties:
- clock-names : A list of channel group clock names. Should contain:
"dmamux0" - clock name of mux0 group
"dmamux1" - clock name of mux1 group
+ Note: No dmamux0 on i.mx7ulp, but another 'dma' clk added on i.mx7ulp.
- clocks : A list of phandle and clock-specifier pairs, one for each entry in
clock-names.
@@ -35,6 +37,10 @@ Optional properties:
- big-endian: If present registers and hardware scatter/gather descriptors
of the eDMA are implemented in big endian mode, otherwise in little
mode.
+- interrupt-names : Should contain the below on vf610 similar SoC but not used
+ on i.mx7ulp similar SoC:
+ "edma-tx" - the transmission interrupt
+ "edma-err" - the error interrupt
Examples:
@@ -52,8 +58,36 @@ edma0: dma-controller@40018000 {
clock-names = "dmamux0", "dmamux1";
clocks = <&clks VF610_CLK_DMAMUX0>,
<&clks VF610_CLK_DMAMUX1>;
-};
+}; /* vf610 */
+edma1: dma-controller@40080000 {
+ #dma-cells = <2>;
+ compatible = "fsl,imx7ulp-edma";
+ reg = <0x40080000 0x2000>,
+ <0x40210000 0x1000>;
+ dma-channels = <32>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
+ /* last is eDMA2-ERR interrupt */
+ <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "dma", "dmamux0";
+ clocks = <&pcc2 IMX7ULP_CLK_DMA1>,
+ <&pcc2 IMX7ULP_CLK_DMA_MUX1>;
+}; /* i.mx7ulp */
* DMA clients
DMA client drivers that uses the DMA function must use the format described
--
2.7.4
^ permalink raw reply related
* [PATCH v3 8/8] ARM: dts: imx7ulp: add edma device node
From: yibin.gong @ 2019-05-29 9:08 UTC (permalink / raw)
To: robh, shawnguo, s.hauer, festevam, mark.rutland, vkoul,
dan.j.williams
Cc: linux-imx, linux-arm-kernel, linux-kernel, dmaengine, devicetree,
kernel
In-Reply-To: <20190529090848.34350-1-yibin.gong@nxp.com>
From: Robin Gong <yibin.gong@nxp.com>
Add edma device node in dts.
Signed-off-by: Robin Gong <yibin.gong@nxp.com>
---
arch/arm/boot/dts/imx7ulp.dtsi | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/imx7ulp.dtsi
index d6b7110..b4f7adf 100644
--- a/arch/arm/boot/dts/imx7ulp.dtsi
+++ b/arch/arm/boot/dts/imx7ulp.dtsi
@@ -100,6 +100,34 @@
reg = <0x40000000 0x800000>;
ranges;
+ edma1: dma-controller@40080000 {
+ #dma-cells = <2>;
+ compatible = "fsl,imx7ulp-edma";
+ reg = <0x40080000 0x2000>,
+ <0x40210000 0x1000>;
+ dma-channels = <32>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "dma", "dmamux0";
+ clocks = <&pcc2 IMX7ULP_CLK_DMA1>,
+ <&pcc2 IMX7ULP_CLK_DMA_MUX1>;
+ };
+
lpuart4: serial@402d0000 {
compatible = "fsl,imx7ulp-lpuart";
reg = <0x402d0000 0x1000>;
--
2.7.4
^ permalink raw reply related
* [PATCH v3 2/8] dmaengine: mcf-edma: update to 'dmamux_nr'
From: yibin.gong @ 2019-05-29 9:08 UTC (permalink / raw)
To: robh, shawnguo, s.hauer, festevam, mark.rutland, vkoul,
dan.j.williams
Cc: linux-imx, linux-arm-kernel, linux-kernel, dmaengine, devicetree,
kernel
In-Reply-To: <20190529090848.34350-1-yibin.gong@nxp.com>
From: Robin Gong <yibin.gong@nxp.com>
Update to 'dmamux_nr' instead of static macro DMAMUX_NR since
new version edma only has one dmamux.
Signed-off-by: Robin Gong <yibin.gong@nxp.com>
---
drivers/dma/fsl-edma-common.c | 2 +-
drivers/dma/mcf-edma.c | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c
index 680b2a0..c9a17fc 100644
--- a/drivers/dma/fsl-edma-common.c
+++ b/drivers/dma/fsl-edma-common.c
@@ -84,7 +84,7 @@ void fsl_edma_chan_mux(struct fsl_edma_chan *fsl_chan,
void __iomem *muxaddr;
unsigned int chans_per_mux, ch_off;
- chans_per_mux = fsl_chan->edma->n_chans / DMAMUX_NR;
+ chans_per_mux = fsl_chan->edma->n_chans / fsl_chan->edma->dmamux_nr;
ch_off = fsl_chan->vchan.chan.chan_id % chans_per_mux;
muxaddr = fsl_chan->edma->muxbase[ch / chans_per_mux];
slot = EDMAMUX_CHCFG_SOURCE(slot);
diff --git a/drivers/dma/mcf-edma.c b/drivers/dma/mcf-edma.c
index 7de54b2f..4484190 100644
--- a/drivers/dma/mcf-edma.c
+++ b/drivers/dma/mcf-edma.c
@@ -189,6 +189,7 @@ static int mcf_edma_probe(struct platform_device *pdev)
/* Set up version for ColdFire edma */
mcf_edma->version = v2;
+ mcf_edma->dmamux_nr = DMAMUX_NR;
mcf_edma->big_endian = 1;
if (!mcf_edma->n_chans) {
--
2.7.4
^ permalink raw reply related
* [PATCH v3 1/8] dmaengine: fsl-edma: add dmamux_nr for next version
From: yibin.gong @ 2019-05-29 9:08 UTC (permalink / raw)
To: robh, shawnguo, s.hauer, festevam, mark.rutland, vkoul,
dan.j.williams
Cc: linux-imx, linux-arm-kernel, linux-kernel, dmaengine, devicetree,
kernel
In-Reply-To: <20190529090848.34350-1-yibin.gong@nxp.com>
From: Robin Gong <yibin.gong@nxp.com>
Next version of edma such as edmav2 on i.mx7ulp has only one dmamux.
Add dmamux_nr instead of static macro define 'DMAMUX_NR'. No any
function change here.
Signed-off-by: Robin Gong <yibin.gong@nxp.com>
---
drivers/dma/fsl-edma-common.h | 1 +
drivers/dma/fsl-edma.c | 11 ++++++-----
2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/dma/fsl-edma-common.h b/drivers/dma/fsl-edma-common.h
index c53f76e..21a9cfd 100644
--- a/drivers/dma/fsl-edma-common.h
+++ b/drivers/dma/fsl-edma-common.h
@@ -145,6 +145,7 @@ struct fsl_edma_engine {
void __iomem *membase;
void __iomem *muxbase[DMAMUX_NR];
struct clk *muxclk[DMAMUX_NR];
+ u32 dmamux_nr;
struct mutex fsl_edma_mutex;
u32 n_chans;
int txirq;
diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c
index d641ef8..7b65ef4 100644
--- a/drivers/dma/fsl-edma.c
+++ b/drivers/dma/fsl-edma.c
@@ -96,7 +96,7 @@ static struct dma_chan *fsl_edma_xlate(struct of_phandle_args *dma_spec,
struct fsl_edma_engine *fsl_edma = ofdma->of_dma_data;
struct dma_chan *chan, *_chan;
struct fsl_edma_chan *fsl_chan;
- unsigned long chans_per_mux = fsl_edma->n_chans / DMAMUX_NR;
+ unsigned long chans_per_mux = fsl_edma->n_chans / fsl_edma->dmamux_nr;
if (dma_spec->args_count != 2)
return NULL;
@@ -206,6 +206,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
return -ENOMEM;
fsl_edma->version = v1;
+ fsl_edma->dmamux_nr = DMAMUX_NR;
fsl_edma->n_chans = chans;
mutex_init(&fsl_edma->fsl_edma_mutex);
@@ -217,7 +218,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
fsl_edma_setup_regs(fsl_edma);
regs = &fsl_edma->regs;
- for (i = 0; i < DMAMUX_NR; i++) {
+ for (i = 0; i < fsl_edma->dmamux_nr; i++) {
char clkname[32];
res = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
@@ -295,7 +296,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev,
"Can't register Freescale eDMA engine. (%d)\n", ret);
- fsl_disable_clocks(fsl_edma, DMAMUX_NR);
+ fsl_disable_clocks(fsl_edma, fsl_edma->dmamux_nr);
return ret;
}
@@ -304,7 +305,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"Can't register Freescale eDMA of_dma. (%d)\n", ret);
dma_async_device_unregister(&fsl_edma->dma_dev);
- fsl_disable_clocks(fsl_edma, DMAMUX_NR);
+ fsl_disable_clocks(fsl_edma, fsl_edma->dmamux_nr);
return ret;
}
@@ -323,7 +324,7 @@ static int fsl_edma_remove(struct platform_device *pdev)
fsl_edma_cleanup_vchan(&fsl_edma->dma_dev);
of_dma_controller_free(np);
dma_async_device_unregister(&fsl_edma->dma_dev);
- fsl_disable_clocks(fsl_edma, DMAMUX_NR);
+ fsl_disable_clocks(fsl_edma, fsl_edma->dmamux_nr);
return 0;
}
--
2.7.4
^ permalink raw reply related
* [PATCH] dmaengine: dmatest: Add support for completion polling
From: Peter Ujfalusi @ 2019-05-29 8:37 UTC (permalink / raw)
To: vkoul; +Cc: dan.j.williams, dmaengine, andriy.shevchenko
With the polled parameter the DMA drivers can be tested if they can work
correctly when no completion is requested (no DMA_PREP_INTERRUPT and no
callback is provided).
If polled mode is selected then use dma_sync_wait() to execute the test
iteration instead of relying on the completion callback.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
---
drivers/dma/dmatest.c | 35 ++++++++++++++++++++++++++++-------
1 file changed, 28 insertions(+), 7 deletions(-)
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index b96814a7dceb..088086d041e9 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -75,6 +75,10 @@ static bool norandom;
module_param(norandom, bool, 0644);
MODULE_PARM_DESC(norandom, "Disable random offset setup (default: random)");
+static bool polled;
+module_param(polled, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(polled, "Use polling for completion instead of interrupts");
+
static bool verbose;
module_param(verbose, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(verbose, "Enable \"success\" result messages (default: off)");
@@ -113,6 +117,7 @@ struct dmatest_params {
bool norandom;
int alignment;
unsigned int transfer_size;
+ bool polled;
};
/**
@@ -654,7 +659,10 @@ static int dmatest_func(void *data)
/*
* src and dst buffers are freed by ourselves below
*/
- flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+ if (params->polled)
+ flags = DMA_CTRL_ACK;
+ else
+ flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
ktime = ktime_get();
while (!kthread_should_stop()
@@ -783,8 +791,10 @@ static int dmatest_func(void *data)
}
done->done = false;
- tx->callback = dmatest_callback;
- tx->callback_param = done;
+ if (!params->polled) {
+ tx->callback = dmatest_callback;
+ tx->callback_param = done;
+ }
cookie = tx->tx_submit(tx);
if (dma_submit_error(cookie)) {
@@ -793,12 +803,22 @@ static int dmatest_func(void *data)
msleep(100);
goto error_unmap_continue;
}
- dma_async_issue_pending(chan);
- wait_event_freezable_timeout(thread->done_wait, done->done,
- msecs_to_jiffies(params->timeout));
+ if (params->polled) {
+ status = dma_sync_wait(chan, cookie);
+ dmaengine_terminate_sync(chan);
+ if (status == DMA_COMPLETE)
+ done->done = true;
+ } else {
+ dma_async_issue_pending(chan);
+
+ wait_event_freezable_timeout(thread->done_wait,
+ done->done,
+ msecs_to_jiffies(params->timeout));
- status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
+ status = dma_async_is_tx_complete(chan, cookie, NULL,
+ NULL);
+ }
if (!done->done) {
result("test timed out", total_tests, src->off, dst->off,
@@ -1068,6 +1088,7 @@ static void add_threaded_test(struct dmatest_info *info)
params->norandom = norandom;
params->alignment = alignment;
params->transfer_size = transfer_size;
+ params->polled = polled;
request_channels(info, DMA_MEMCPY);
request_channels(info, DMA_MEMSET);
--
Peter
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
^ permalink raw reply related
* Purchase_rfq
From: aishatu @ 2019-05-28 18:12 UTC (permalink / raw)
To: dmaengine
[-- Attachment #1: INQUIRY_4178916..xlsx --]
[-- Type: application/octet-stream, Size: 9404 bytes --]
^ permalink raw reply
* Re: [PATCH v3 0/7] Allwinner H6 DMA support
From: Maxime Ripard @ 2019-05-28 11:10 UTC (permalink / raw)
To: Clément Péron
Cc: Vinod Koul, Rob Herring, Mark Rutland, Chen-Yu Tsai, Dan Williams,
dmaengine, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20190527201459.20130-1-peron.clem@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 954 bytes --]
On Mon, May 27, 2019 at 10:14:52PM +0200, Clément Péron wrote:
> Hi,
>
> This series has been first proposed by Jernej Skrabec[1].
> As this series is mandatory for SPDIF/I2S support and because he is
> busy on Cedrus stuff. I asked him to make the minor change requested
> and repost it.
> Authorship remains to him.
>
> I have tested this series with SPDIF driver and added a patch to enable
> DMA_SUN6I_CONFIG for arm64.
>
> Original Post:
> "
> DMA engine engine on H6 almost the same as on older SoCs. The biggest
> difference is that it has slightly rearranged bits in registers and
> it needs additional clock, probably due to iommu.
>
> These patches were tested with I2S connected to HDMI. I2S needs
> additional patches which will be sent later.
For the whole series,
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
Maxime
--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox