From: Angelo Dureghello <angelo@sysam.it>
To: Krzysztof Kozlowski <krzk@kernel.org>
Cc: vinod.koul@linaro.org, dmaengine@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, linux-m68k@vger.kernel.org,
Stefan Agner <stefan@agner.ch>
Subject: [v8,3/3] dmaengine: fsl-edma: add ColdFire mcf5441x edma support
Date: Mon, 6 Aug 2018 23:01:10 +0200 [thread overview]
Message-ID: <20180806210110.GD6092@jerusalem> (raw)
Hi Krzysztof,
On Mon, Aug 06, 2018 at 10:09:08AM +0200, Krzysztof Kozlowski wrote:
> On 3 August 2018 at 21:32, Angelo Dureghello <angelo@sysam.it> wrote:
> > This patch adds support for ColdFire mcf5441x-family edma
> > module.
> >
> > The ColdFire edma module is slightly different from fsl-edma,
> > so a new driver is added. But most of the code is common
> > between fsl-edma and mcf-edma so it has been collected into a
> > separate common module fsl-edma-common (patch 1/3).
> >
> > Signed-off-by: Angelo Dureghello <angelo@sysam.it>
> > ---
> > Changes for v7:
> > - patch rewritten from scratch, this patch (3/3) has just been added.
> > ---
> > drivers/dma/Kconfig | 11 +
> > drivers/dma/Makefile | 1 +
> > drivers/dma/fsl-edma-common.c | 24 +-
> > drivers/dma/mcf-edma.c | 315 +++++++++++++++++++++
> > include/linux/platform_data/dma-mcf-edma.h | 38 +++
> > 5 files changed, 385 insertions(+), 4 deletions(-)
> > create mode 100644 drivers/dma/mcf-edma.c
> > create mode 100644 include/linux/platform_data/dma-mcf-edma.h
> >
> > diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
> > index ca1680afa20a..b45008e9c7e9 100644
> > --- a/drivers/dma/Kconfig
> > +++ b/drivers/dma/Kconfig
> > @@ -320,6 +320,17 @@ config LPC18XX_DMAMUX
> > Enable support for DMA on NXP LPC18xx/43xx platforms
> > with PL080 and multiplexed DMA request lines.
> >
> > +config MCF_EDMA
> > + tristate "Freescale eDMA engine support, ColdFire mcf5441x SoCs"
> > + depends on M5441x
> > + select DMA_ENGINE
> > + select DMA_VIRTUAL_CHANNELS
> > + help
> > + Support the Freescale ColdFire eDMA engine, 64-channel
> > + implementation that performs complex data transfers with
> > + minimal intervention from a host processor.
> > + This module can be found on Freescale ColdFire mcf5441x SoCs.
> > +
> > config MMP_PDMA
> > bool "MMP PDMA support"
> > depends on ARCH_MMP || ARCH_PXA || COMPILE_TEST
> > diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
> > index 66022f59fca4..d97f317f4b34 100644
> > --- a/drivers/dma/Makefile
> > +++ b/drivers/dma/Makefile
> > @@ -32,6 +32,7 @@ obj-$(CONFIG_DW_DMAC_CORE) += dw/
> > obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
> > obj-$(CONFIG_FSL_DMA) += fsldma.o
> > obj-$(CONFIG_FSL_EDMA) += fsl-edma.o fsl-edma-common.o
> > +obj-$(CONFIG_MCF_EDMA) += mcf-edma.o fsl-edma-common.o
> > obj-$(CONFIG_FSL_RAID) += fsl_raid.o
> > obj-$(CONFIG_HSU_DMA) += hsu/
> > obj-$(CONFIG_IMG_MDC_DMA) += img-mdc-dma.o
> > diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c
> > index 948a3ee51bbb..5a830a238a0c 100644
> > --- a/drivers/dma/fsl-edma-common.c
> > +++ b/drivers/dma/fsl-edma-common.c
> > @@ -102,8 +102,16 @@ static void fsl_edma_enable_request(struct fsl_edma_chan *fsl_chan)
> > struct edma_regs *regs = &fsl_chan->edma->regs;
> > u32 ch = fsl_chan->vchan.chan.chan_id;
> >
> > - edma_writeb(fsl_chan->edma, EDMA_SEEI_SEEI(ch), regs->seei);
> > - edma_writeb(fsl_chan->edma, ch, regs->serq);
> > + if (fsl_chan->edma->version == v1) {
> > + edma_writeb(fsl_chan->edma, EDMA_SEEI_SEEI(ch), regs->seei);
> > + edma_writeb(fsl_chan->edma, ch, regs->serq);
> > + } else {
> > + /* ColdFire is big endian, and accesses natively
> > + * big endian I/O peripherals
> > + */
> > + iowrite8(EDMA_SEEI_SEEI(ch), regs->seei);
> > + iowrite8(ch, regs->serq);
> > + }
> > }
> >
> > void fsl_edma_disable_request(struct fsl_edma_chan *fsl_chan)
> > @@ -111,8 +119,16 @@ void fsl_edma_disable_request(struct fsl_edma_chan *fsl_chan)
> > struct edma_regs *regs = &fsl_chan->edma->regs;
> > u32 ch = fsl_chan->vchan.chan.chan_id;
> >
> > - edma_writeb(fsl_chan->edma, ch, regs->cerq);
> > - edma_writeb(fsl_chan->edma, EDMA_CEEI_CEEI(ch), regs->ceei);
> > + if (fsl_chan->edma->version == v1) {
> > + edma_writeb(fsl_chan->edma, ch, regs->cerq);
> > + edma_writeb(fsl_chan->edma, EDMA_CEEI_CEEI(ch), regs->ceei);
> > + } else {
> > + /* ColdFire is big endian, and accesses natively
> > + * big endian I/O peripherals
> > + */
> > + iowrite8(ch, regs->cerq);
> > + iowrite8(EDMA_CEEI_CEEI(ch), regs->ceei);
> > + }
> > }
> > EXPORT_SYMBOL_GPL(fsl_edma_disable_request);
> >
> > diff --git a/drivers/dma/mcf-edma.c b/drivers/dma/mcf-edma.c
> > new file mode 100644
> > index 000000000000..31e5317a8f90
> > --- /dev/null
> > +++ b/drivers/dma/mcf-edma.c
> > @@ -0,0 +1,315 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// Copyright (c) 2013-2014 Freescale Semiconductor, Inc
>
> Same comment as to 1/3 - if this is derivative work...
>
Well, in this case the driver is brand new, i maintained the
Freescale Copyright too, since i copied some code from fsl-edma.c.
> > +// Copyright (c) 2017 Sysam, Angelo Dureghello <angelo@sysam.it>
> > +
> > +#include <linux/module.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/dmaengine.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/platform_data/dma-mcf-edma.h>
> > +
> > +#include "fsl-edma-common.h"
> > +
> > +#define EDMA_CHANNELS 64
> > +#define EDMA_MASK_CH(x) ((x) & GENMASK(5, 0))
> > +
> > +static irqreturn_t mcf_edma_tx_handler(int irq, void *dev_id)
> > +{
> > + struct fsl_edma_engine *mcf_edma = dev_id;
> > + struct edma_regs *regs = &mcf_edma->regs;
> > + unsigned int ch;
> > + struct fsl_edma_chan *mcf_chan;
> > + u64 intmap;
> > +
> > + intmap = ioread32(regs->inth);
> > + intmap <<= 32;
> > + intmap |= ioread32(regs->intl);
> > + if (!intmap)
> > + return IRQ_NONE;
> > +
> > + for (ch = 0; ch < mcf_edma->n_chans; ch++) {
> > + if (intmap & BIT(ch)) {
> > + iowrite8(EDMA_MASK_CH(ch), regs->cint);
> > +
> > + mcf_chan = &mcf_edma->chans[ch];
> > +
> > + spin_lock(&mcf_chan->vchan.lock);
> > + if (!mcf_chan->edesc->iscyclic) {
> > + list_del(&mcf_chan->edesc->vdesc.node);
> > + vchan_cookie_complete(&mcf_chan->edesc->vdesc);
> > + mcf_chan->edesc = NULL;
> > + mcf_chan->status = DMA_COMPLETE;
> > + mcf_chan->idle = true;
> > + } else {
> > + vchan_cyclic_callback(&mcf_chan->edesc->vdesc);
> > + }
> > +
> > + if (!mcf_chan->edesc)
> > + fsl_edma_xfer_desc(mcf_chan);
> > +
> > + spin_unlock(&mcf_chan->vchan.lock);
> > + }
> > + }
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +static irqreturn_t mcf_edma_err_handler(int irq, void *dev_id)
> > +{
> > + struct fsl_edma_engine *mcf_edma = dev_id;
> > + struct edma_regs *regs = &mcf_edma->regs;
> > + unsigned int err, ch;
> > +
> > + err = ioread32(regs->errl);
> > + if (!err)
> > + return IRQ_NONE;
> > +
> > + for (ch = 0; ch < (EDMA_CHANNELS / 2); ch++) {
> > + if (err & BIT(ch)) {
> > + fsl_edma_disable_request(&mcf_edma->chans[ch]);
> > + iowrite8(EDMA_CERR_CERR(ch), regs->cerr);
> > + mcf_edma->chans[ch].status = DMA_ERROR;
> > + mcf_edma->chans[ch].idle = true;
> > + }
> > + }
> > +
> > + err = ioread32(regs->errh);
> > + if (!err)
> > + return IRQ_NONE;
> > +
> > + for (ch = (EDMA_CHANNELS / 2); ch < EDMA_CHANNELS; ch++) {
> > + if (err & (BIT(ch - (EDMA_CHANNELS / 2)))) {
> > + fsl_edma_disable_request(&mcf_edma->chans[ch]);
> > + iowrite8(EDMA_CERR_CERR(ch), regs->cerr);
> > + mcf_edma->chans[ch].status = DMA_ERROR;
> > + mcf_edma->chans[ch].idle = true;
> > + }
> > + }
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +static int mcf_edma_irq_init(struct platform_device *pdev,
> > + struct fsl_edma_engine *mcf_edma)
> > +{
> > + int ret = 0, i;
> > + struct resource *res;
> > +
> > + res = platform_get_resource_byname(pdev,
> > + IORESOURCE_IRQ, "edma-tx-00-15");
> > + if (!res)
> > + return -1;
> > +
> > + for (ret = 0, i = res->start; i <= res->end; ++i)
> > + ret |= request_irq(i, mcf_edma_tx_handler, 0, "eDMA", mcf_edma);
> > + if (ret)
> > + return ret;
> > +
> > + res = platform_get_resource_byname(pdev,
> > + IORESOURCE_IRQ, "edma-tx-16-55");
> > + if (!res)
> > + return -1;
> > +
> > + for (ret = 0, i = res->start; i <= res->end; ++i)
> > + ret |= request_irq(i, mcf_edma_tx_handler, 0, "eDMA", mcf_edma);
> > + if (ret)
> > + return ret;
> > +
> > + ret = platform_get_irq_byname(pdev, "edma-tx-56-63");
> > + if (ret != -ENXIO) {
> > + ret = request_irq(ret, mcf_edma_tx_handler,
> > + 0, "eDMA", mcf_edma);
> > + if (ret)
> > + return ret;
> > + }
> > +
> > + ret = platform_get_irq_byname(pdev, "edma-err");
> > + if (ret != -ENXIO) {
> > + ret = request_irq(ret, mcf_edma_err_handler,
> > + 0, "eDMA", mcf_edma);
> > + if (ret)
> > + return ret;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static void mcf_edma_irq_free(struct platform_device *pdev,
> > + struct fsl_edma_engine *mcf_edma)
> > +{
> > + int irq;
> > + struct resource *res;
> > +
> > + res = platform_get_resource_byname(pdev,
> > + IORESOURCE_IRQ, "edma-tx-00-15");
> > + if (res) {
> > + for (irq = res->start; irq <= res->end; irq++)
> > + free_irq(irq, mcf_edma);
> > + }
> > +
> > + res = platform_get_resource_byname(pdev,
> > + IORESOURCE_IRQ, "edma-tx-16-55");
> > + if (res) {
> > + for (irq = res->start; irq <= res->end; irq++)
> > + free_irq(irq, mcf_edma);
> > + }
> > +
> > + irq = platform_get_irq_byname(pdev, "edma-tx-56-63");
> > + if (irq != -ENXIO)
> > + free_irq(irq, mcf_edma);
> > +
> > + irq = platform_get_irq_byname(pdev, "edma-err");
> > + if (irq != -ENXIO)
> > + free_irq(irq, mcf_edma);
> > +}
> > +
> > +static int mcf_edma_probe(struct platform_device *pdev)
> > +{
> > + struct mcf_edma_platform_data *pdata;
> > + struct fsl_edma_engine *mcf_edma;
> > + struct fsl_edma_chan *mcf_chan;
> > + struct edma_regs *regs;
> > + struct resource *res;
> > + int ret, i, len, chans;
> > +
> > + pdata = dev_get_platdata(&pdev->dev);
> > + if (!pdata)
> > + return PTR_ERR(pdata);
> > +
> > + chans = pdata->dma_channels;
> > + len = sizeof(*mcf_edma) + sizeof(*mcf_chan) * chans;
> > + mcf_edma = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
> > + if (!mcf_edma)
> > + return -ENOMEM;
> > +
> > + mcf_edma->n_chans = chans;
> > +
> > + /* Set up version for ColdFire edma */
> > + mcf_edma->version = v2;
> > + mcf_edma->big_endian = 1;
> > +
> > + if (!mcf_edma->n_chans) {
> > + dev_info(&pdev->dev, "setting default channel number to 64");
> > + mcf_edma->n_chans = 64;
> > + }
> > +
> > + mutex_init(&mcf_edma->fsl_edma_mutex);
> > +
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +
> > + mcf_edma->membase = devm_ioremap_resource(&pdev->dev, res);
> > + if (IS_ERR(mcf_edma->membase))
> > + return PTR_ERR(mcf_edma->membase);
> > +
> > + fsl_edma_setup_regs(mcf_edma);
> > + regs = &mcf_edma->regs;
> > +
> > + INIT_LIST_HEAD(&mcf_edma->dma_dev.channels);
> > + for (i = 0; i < mcf_edma->n_chans; i++) {
> > + struct fsl_edma_chan *mcf_chan = &mcf_edma->chans[i];
> > +
> > + mcf_chan->edma = mcf_edma;
> > + mcf_chan->slave_id = i;
> > + mcf_chan->idle = true;
> > + mcf_chan->vchan.desc_free = fsl_edma_free_desc;
> > + vchan_init(&mcf_chan->vchan, &mcf_edma->dma_dev);
> > + iowrite32(0x0, ®s->tcd[i].csr);
> > + }
> > +
> > + iowrite32(~0, regs->inth);
> > + iowrite32(~0, regs->intl);
> > +
> > + ret = mcf_edma_irq_init(pdev, mcf_edma);
> > + if (ret)
> > + return ret;
> > +
> > + dma_cap_set(DMA_PRIVATE, mcf_edma->dma_dev.cap_mask);
> > + dma_cap_set(DMA_SLAVE, mcf_edma->dma_dev.cap_mask);
> > + dma_cap_set(DMA_CYCLIC, mcf_edma->dma_dev.cap_mask);
> > +
> > + mcf_edma->dma_dev.dev = &pdev->dev;
> > + mcf_edma->dma_dev.device_alloc_chan_resources =
> > + fsl_edma_alloc_chan_resources;
> > + mcf_edma->dma_dev.device_free_chan_resources =
> > + fsl_edma_free_chan_resources;
> > + mcf_edma->dma_dev.device_config = fsl_edma_slave_config;
> > + mcf_edma->dma_dev.device_prep_dma_cyclic =
> > + fsl_edma_prep_dma_cyclic;
> > + mcf_edma->dma_dev.device_prep_slave_sg = fsl_edma_prep_slave_sg;
> > + mcf_edma->dma_dev.device_tx_status = fsl_edma_tx_status;
> > + mcf_edma->dma_dev.device_pause = fsl_edma_pause;
> > + mcf_edma->dma_dev.device_resume = fsl_edma_resume;
> > + mcf_edma->dma_dev.device_terminate_all = fsl_edma_terminate_all;
> > + mcf_edma->dma_dev.device_issue_pending = fsl_edma_issue_pending;
> > +
> > + mcf_edma->dma_dev.src_addr_widths = FSL_EDMA_BUSWIDTHS;
> > + mcf_edma->dma_dev.dst_addr_widths = FSL_EDMA_BUSWIDTHS;
> > + mcf_edma->dma_dev.directions =
> > + BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
> > +
> > + mcf_edma->dma_dev.filter.fn = mcf_edma_filter_fn;
> > + mcf_edma->dma_dev.filter.map = pdata->slave_map;
> > + mcf_edma->dma_dev.filter.mapcnt = pdata->slavecnt;
> > +
> > + platform_set_drvdata(pdev, mcf_edma);
> > +
> > + ret = dma_async_device_register(&mcf_edma->dma_dev);
> > + if (ret) {
> > + dev_err(&pdev->dev,
> > + "Can't register Freescale eDMA engine. (%d)\n", ret);
> > + return ret;
> > + }
> > +
> > + /* Enable round robin arbitration */
> > + iowrite32(EDMA_CR_ERGA | EDMA_CR_ERCA, regs->cr);
> > +
> > + return 0;
> > +}
> > +
> > +static int mcf_edma_remove(struct platform_device *pdev)
> > +{
> > + struct fsl_edma_engine *mcf_edma = platform_get_drvdata(pdev);
> > +
> > + mcf_edma_irq_free(pdev, mcf_edma);
> > + fsl_edma_cleanup_vchan(&mcf_edma->dma_dev);
> > + dma_async_device_unregister(&mcf_edma->dma_dev);
> > +
> > + return 0;
> > +}
> > +
> > +static struct platform_driver mcf_edma_driver = {
> > + .driver = {
> > + .name = "mcf-edma",
> > + },
> > + .probe = mcf_edma_probe,
> > + .remove = mcf_edma_remove,
> > +};
> > +
> > +bool mcf_edma_filter_fn(struct dma_chan *chan, void *param)
> > +{
> > + if (chan->device->dev->driver == &mcf_edma_driver.driver) {
> > + struct fsl_edma_chan *mcf_chan = to_fsl_edma_chan(chan);
> > +
> > + return (mcf_chan->slave_id == (int)param);
> > + }
> > +
> > + return false;
> > +}
> > +EXPORT_SYMBOL(mcf_edma_filter_fn);
> > +
> > +static int __init mcf_edma_init(void)
> > +{
> > + return platform_driver_register(&mcf_edma_driver);
> > +}
> > +subsys_initcall(mcf_edma_init);
> > +
> > +static void __exit mcf_edma_exit(void)
> > +{
> > + platform_driver_unregister(&mcf_edma_driver);
> > +}
> > +module_exit(mcf_edma_exit);
> > +
> > +MODULE_ALIAS("platform:mcf-edma");
> > +MODULE_DESCRIPTION("Freescale eDMA engine driver, ColdFire family");
> > +MODULE_LICENSE("GPL v2");
> > diff --git a/include/linux/platform_data/dma-mcf-edma.h b/include/linux/platform_data/dma-mcf-edma.h
> > new file mode 100644
> > index 000000000000..9a1819acb28f
> > --- /dev/null
> > +++ b/include/linux/platform_data/dma-mcf-edma.h
> > @@ -0,0 +1,38 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Freescale eDMA platform data, ColdFire SoC's family.
> > + *
> > + * Copyright (c) 2017 Angelo Dureghello <angelo@sysam.it>
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#ifndef __MACH_MCF_EDMA_H__
> > +#define __MACH_MCF_EDMA_H__
>
> The guard should rather match current location, e.g.
> __LINUX_PLATFORM_DATA_MCF_EDMA_H__
>
Ack.
> Tested-by: Krzysztof Kozlowski <krzk@kernel.org>
>
> Best regards,
> Krzysztof
> --
> To unsubscribe from this list: send the line "unsubscribe dmaengine" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Regards,
Angelo
---
To unsubscribe from this list: send the line "unsubscribe dmaengine" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
WARNING: multiple messages have this Message-ID (diff)
From: Angelo Dureghello <angelo@sysam.it>
To: Krzysztof Kozlowski <krzk@kernel.org>
Cc: dmaengine@vger.kernel.org, Stefan Agner <stefan@agner.ch>,
linux-m68k@vger.kernel.org, vinod.koul@linaro.org,
linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v8 3/3] dmaengine: fsl-edma: add ColdFire mcf5441x edma support
Date: Mon, 6 Aug 2018 23:01:10 +0200 [thread overview]
Message-ID: <20180806210110.GD6092@jerusalem> (raw)
In-Reply-To: <CAJKOXPe=+KCwxJULZ5RPpZtemrPr2YARFFxH4jEQsA0bVzrrBA@mail.gmail.com>
Hi Krzysztof,
On Mon, Aug 06, 2018 at 10:09:08AM +0200, Krzysztof Kozlowski wrote:
> On 3 August 2018 at 21:32, Angelo Dureghello <angelo@sysam.it> wrote:
> > This patch adds support for ColdFire mcf5441x-family edma
> > module.
> >
> > The ColdFire edma module is slightly different from fsl-edma,
> > so a new driver is added. But most of the code is common
> > between fsl-edma and mcf-edma so it has been collected into a
> > separate common module fsl-edma-common (patch 1/3).
> >
> > Signed-off-by: Angelo Dureghello <angelo@sysam.it>
> > ---
> > Changes for v7:
> > - patch rewritten from scratch, this patch (3/3) has just been added.
> > ---
> > drivers/dma/Kconfig | 11 +
> > drivers/dma/Makefile | 1 +
> > drivers/dma/fsl-edma-common.c | 24 +-
> > drivers/dma/mcf-edma.c | 315 +++++++++++++++++++++
> > include/linux/platform_data/dma-mcf-edma.h | 38 +++
> > 5 files changed, 385 insertions(+), 4 deletions(-)
> > create mode 100644 drivers/dma/mcf-edma.c
> > create mode 100644 include/linux/platform_data/dma-mcf-edma.h
> >
> > diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
> > index ca1680afa20a..b45008e9c7e9 100644
> > --- a/drivers/dma/Kconfig
> > +++ b/drivers/dma/Kconfig
> > @@ -320,6 +320,17 @@ config LPC18XX_DMAMUX
> > Enable support for DMA on NXP LPC18xx/43xx platforms
> > with PL080 and multiplexed DMA request lines.
> >
> > +config MCF_EDMA
> > + tristate "Freescale eDMA engine support, ColdFire mcf5441x SoCs"
> > + depends on M5441x
> > + select DMA_ENGINE
> > + select DMA_VIRTUAL_CHANNELS
> > + help
> > + Support the Freescale ColdFire eDMA engine, 64-channel
> > + implementation that performs complex data transfers with
> > + minimal intervention from a host processor.
> > + This module can be found on Freescale ColdFire mcf5441x SoCs.
> > +
> > config MMP_PDMA
> > bool "MMP PDMA support"
> > depends on ARCH_MMP || ARCH_PXA || COMPILE_TEST
> > diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
> > index 66022f59fca4..d97f317f4b34 100644
> > --- a/drivers/dma/Makefile
> > +++ b/drivers/dma/Makefile
> > @@ -32,6 +32,7 @@ obj-$(CONFIG_DW_DMAC_CORE) += dw/
> > obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
> > obj-$(CONFIG_FSL_DMA) += fsldma.o
> > obj-$(CONFIG_FSL_EDMA) += fsl-edma.o fsl-edma-common.o
> > +obj-$(CONFIG_MCF_EDMA) += mcf-edma.o fsl-edma-common.o
> > obj-$(CONFIG_FSL_RAID) += fsl_raid.o
> > obj-$(CONFIG_HSU_DMA) += hsu/
> > obj-$(CONFIG_IMG_MDC_DMA) += img-mdc-dma.o
> > diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c
> > index 948a3ee51bbb..5a830a238a0c 100644
> > --- a/drivers/dma/fsl-edma-common.c
> > +++ b/drivers/dma/fsl-edma-common.c
> > @@ -102,8 +102,16 @@ static void fsl_edma_enable_request(struct fsl_edma_chan *fsl_chan)
> > struct edma_regs *regs = &fsl_chan->edma->regs;
> > u32 ch = fsl_chan->vchan.chan.chan_id;
> >
> > - edma_writeb(fsl_chan->edma, EDMA_SEEI_SEEI(ch), regs->seei);
> > - edma_writeb(fsl_chan->edma, ch, regs->serq);
> > + if (fsl_chan->edma->version == v1) {
> > + edma_writeb(fsl_chan->edma, EDMA_SEEI_SEEI(ch), regs->seei);
> > + edma_writeb(fsl_chan->edma, ch, regs->serq);
> > + } else {
> > + /* ColdFire is big endian, and accesses natively
> > + * big endian I/O peripherals
> > + */
> > + iowrite8(EDMA_SEEI_SEEI(ch), regs->seei);
> > + iowrite8(ch, regs->serq);
> > + }
> > }
> >
> > void fsl_edma_disable_request(struct fsl_edma_chan *fsl_chan)
> > @@ -111,8 +119,16 @@ void fsl_edma_disable_request(struct fsl_edma_chan *fsl_chan)
> > struct edma_regs *regs = &fsl_chan->edma->regs;
> > u32 ch = fsl_chan->vchan.chan.chan_id;
> >
> > - edma_writeb(fsl_chan->edma, ch, regs->cerq);
> > - edma_writeb(fsl_chan->edma, EDMA_CEEI_CEEI(ch), regs->ceei);
> > + if (fsl_chan->edma->version == v1) {
> > + edma_writeb(fsl_chan->edma, ch, regs->cerq);
> > + edma_writeb(fsl_chan->edma, EDMA_CEEI_CEEI(ch), regs->ceei);
> > + } else {
> > + /* ColdFire is big endian, and accesses natively
> > + * big endian I/O peripherals
> > + */
> > + iowrite8(ch, regs->cerq);
> > + iowrite8(EDMA_CEEI_CEEI(ch), regs->ceei);
> > + }
> > }
> > EXPORT_SYMBOL_GPL(fsl_edma_disable_request);
> >
> > diff --git a/drivers/dma/mcf-edma.c b/drivers/dma/mcf-edma.c
> > new file mode 100644
> > index 000000000000..31e5317a8f90
> > --- /dev/null
> > +++ b/drivers/dma/mcf-edma.c
> > @@ -0,0 +1,315 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// Copyright (c) 2013-2014 Freescale Semiconductor, Inc
>
> Same comment as to 1/3 - if this is derivative work...
>
Well, in this case the driver is brand new, i maintained the
Freescale Copyright too, since i copied some code from fsl-edma.c.
> > +// Copyright (c) 2017 Sysam, Angelo Dureghello <angelo@sysam.it>
> > +
> > +#include <linux/module.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/dmaengine.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/platform_data/dma-mcf-edma.h>
> > +
> > +#include "fsl-edma-common.h"
> > +
> > +#define EDMA_CHANNELS 64
> > +#define EDMA_MASK_CH(x) ((x) & GENMASK(5, 0))
> > +
> > +static irqreturn_t mcf_edma_tx_handler(int irq, void *dev_id)
> > +{
> > + struct fsl_edma_engine *mcf_edma = dev_id;
> > + struct edma_regs *regs = &mcf_edma->regs;
> > + unsigned int ch;
> > + struct fsl_edma_chan *mcf_chan;
> > + u64 intmap;
> > +
> > + intmap = ioread32(regs->inth);
> > + intmap <<= 32;
> > + intmap |= ioread32(regs->intl);
> > + if (!intmap)
> > + return IRQ_NONE;
> > +
> > + for (ch = 0; ch < mcf_edma->n_chans; ch++) {
> > + if (intmap & BIT(ch)) {
> > + iowrite8(EDMA_MASK_CH(ch), regs->cint);
> > +
> > + mcf_chan = &mcf_edma->chans[ch];
> > +
> > + spin_lock(&mcf_chan->vchan.lock);
> > + if (!mcf_chan->edesc->iscyclic) {
> > + list_del(&mcf_chan->edesc->vdesc.node);
> > + vchan_cookie_complete(&mcf_chan->edesc->vdesc);
> > + mcf_chan->edesc = NULL;
> > + mcf_chan->status = DMA_COMPLETE;
> > + mcf_chan->idle = true;
> > + } else {
> > + vchan_cyclic_callback(&mcf_chan->edesc->vdesc);
> > + }
> > +
> > + if (!mcf_chan->edesc)
> > + fsl_edma_xfer_desc(mcf_chan);
> > +
> > + spin_unlock(&mcf_chan->vchan.lock);
> > + }
> > + }
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +static irqreturn_t mcf_edma_err_handler(int irq, void *dev_id)
> > +{
> > + struct fsl_edma_engine *mcf_edma = dev_id;
> > + struct edma_regs *regs = &mcf_edma->regs;
> > + unsigned int err, ch;
> > +
> > + err = ioread32(regs->errl);
> > + if (!err)
> > + return IRQ_NONE;
> > +
> > + for (ch = 0; ch < (EDMA_CHANNELS / 2); ch++) {
> > + if (err & BIT(ch)) {
> > + fsl_edma_disable_request(&mcf_edma->chans[ch]);
> > + iowrite8(EDMA_CERR_CERR(ch), regs->cerr);
> > + mcf_edma->chans[ch].status = DMA_ERROR;
> > + mcf_edma->chans[ch].idle = true;
> > + }
> > + }
> > +
> > + err = ioread32(regs->errh);
> > + if (!err)
> > + return IRQ_NONE;
> > +
> > + for (ch = (EDMA_CHANNELS / 2); ch < EDMA_CHANNELS; ch++) {
> > + if (err & (BIT(ch - (EDMA_CHANNELS / 2)))) {
> > + fsl_edma_disable_request(&mcf_edma->chans[ch]);
> > + iowrite8(EDMA_CERR_CERR(ch), regs->cerr);
> > + mcf_edma->chans[ch].status = DMA_ERROR;
> > + mcf_edma->chans[ch].idle = true;
> > + }
> > + }
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +static int mcf_edma_irq_init(struct platform_device *pdev,
> > + struct fsl_edma_engine *mcf_edma)
> > +{
> > + int ret = 0, i;
> > + struct resource *res;
> > +
> > + res = platform_get_resource_byname(pdev,
> > + IORESOURCE_IRQ, "edma-tx-00-15");
> > + if (!res)
> > + return -1;
> > +
> > + for (ret = 0, i = res->start; i <= res->end; ++i)
> > + ret |= request_irq(i, mcf_edma_tx_handler, 0, "eDMA", mcf_edma);
> > + if (ret)
> > + return ret;
> > +
> > + res = platform_get_resource_byname(pdev,
> > + IORESOURCE_IRQ, "edma-tx-16-55");
> > + if (!res)
> > + return -1;
> > +
> > + for (ret = 0, i = res->start; i <= res->end; ++i)
> > + ret |= request_irq(i, mcf_edma_tx_handler, 0, "eDMA", mcf_edma);
> > + if (ret)
> > + return ret;
> > +
> > + ret = platform_get_irq_byname(pdev, "edma-tx-56-63");
> > + if (ret != -ENXIO) {
> > + ret = request_irq(ret, mcf_edma_tx_handler,
> > + 0, "eDMA", mcf_edma);
> > + if (ret)
> > + return ret;
> > + }
> > +
> > + ret = platform_get_irq_byname(pdev, "edma-err");
> > + if (ret != -ENXIO) {
> > + ret = request_irq(ret, mcf_edma_err_handler,
> > + 0, "eDMA", mcf_edma);
> > + if (ret)
> > + return ret;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static void mcf_edma_irq_free(struct platform_device *pdev,
> > + struct fsl_edma_engine *mcf_edma)
> > +{
> > + int irq;
> > + struct resource *res;
> > +
> > + res = platform_get_resource_byname(pdev,
> > + IORESOURCE_IRQ, "edma-tx-00-15");
> > + if (res) {
> > + for (irq = res->start; irq <= res->end; irq++)
> > + free_irq(irq, mcf_edma);
> > + }
> > +
> > + res = platform_get_resource_byname(pdev,
> > + IORESOURCE_IRQ, "edma-tx-16-55");
> > + if (res) {
> > + for (irq = res->start; irq <= res->end; irq++)
> > + free_irq(irq, mcf_edma);
> > + }
> > +
> > + irq = platform_get_irq_byname(pdev, "edma-tx-56-63");
> > + if (irq != -ENXIO)
> > + free_irq(irq, mcf_edma);
> > +
> > + irq = platform_get_irq_byname(pdev, "edma-err");
> > + if (irq != -ENXIO)
> > + free_irq(irq, mcf_edma);
> > +}
> > +
> > +static int mcf_edma_probe(struct platform_device *pdev)
> > +{
> > + struct mcf_edma_platform_data *pdata;
> > + struct fsl_edma_engine *mcf_edma;
> > + struct fsl_edma_chan *mcf_chan;
> > + struct edma_regs *regs;
> > + struct resource *res;
> > + int ret, i, len, chans;
> > +
> > + pdata = dev_get_platdata(&pdev->dev);
> > + if (!pdata)
> > + return PTR_ERR(pdata);
> > +
> > + chans = pdata->dma_channels;
> > + len = sizeof(*mcf_edma) + sizeof(*mcf_chan) * chans;
> > + mcf_edma = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
> > + if (!mcf_edma)
> > + return -ENOMEM;
> > +
> > + mcf_edma->n_chans = chans;
> > +
> > + /* Set up version for ColdFire edma */
> > + mcf_edma->version = v2;
> > + mcf_edma->big_endian = 1;
> > +
> > + if (!mcf_edma->n_chans) {
> > + dev_info(&pdev->dev, "setting default channel number to 64");
> > + mcf_edma->n_chans = 64;
> > + }
> > +
> > + mutex_init(&mcf_edma->fsl_edma_mutex);
> > +
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +
> > + mcf_edma->membase = devm_ioremap_resource(&pdev->dev, res);
> > + if (IS_ERR(mcf_edma->membase))
> > + return PTR_ERR(mcf_edma->membase);
> > +
> > + fsl_edma_setup_regs(mcf_edma);
> > + regs = &mcf_edma->regs;
> > +
> > + INIT_LIST_HEAD(&mcf_edma->dma_dev.channels);
> > + for (i = 0; i < mcf_edma->n_chans; i++) {
> > + struct fsl_edma_chan *mcf_chan = &mcf_edma->chans[i];
> > +
> > + mcf_chan->edma = mcf_edma;
> > + mcf_chan->slave_id = i;
> > + mcf_chan->idle = true;
> > + mcf_chan->vchan.desc_free = fsl_edma_free_desc;
> > + vchan_init(&mcf_chan->vchan, &mcf_edma->dma_dev);
> > + iowrite32(0x0, ®s->tcd[i].csr);
> > + }
> > +
> > + iowrite32(~0, regs->inth);
> > + iowrite32(~0, regs->intl);
> > +
> > + ret = mcf_edma_irq_init(pdev, mcf_edma);
> > + if (ret)
> > + return ret;
> > +
> > + dma_cap_set(DMA_PRIVATE, mcf_edma->dma_dev.cap_mask);
> > + dma_cap_set(DMA_SLAVE, mcf_edma->dma_dev.cap_mask);
> > + dma_cap_set(DMA_CYCLIC, mcf_edma->dma_dev.cap_mask);
> > +
> > + mcf_edma->dma_dev.dev = &pdev->dev;
> > + mcf_edma->dma_dev.device_alloc_chan_resources =
> > + fsl_edma_alloc_chan_resources;
> > + mcf_edma->dma_dev.device_free_chan_resources =
> > + fsl_edma_free_chan_resources;
> > + mcf_edma->dma_dev.device_config = fsl_edma_slave_config;
> > + mcf_edma->dma_dev.device_prep_dma_cyclic =
> > + fsl_edma_prep_dma_cyclic;
> > + mcf_edma->dma_dev.device_prep_slave_sg = fsl_edma_prep_slave_sg;
> > + mcf_edma->dma_dev.device_tx_status = fsl_edma_tx_status;
> > + mcf_edma->dma_dev.device_pause = fsl_edma_pause;
> > + mcf_edma->dma_dev.device_resume = fsl_edma_resume;
> > + mcf_edma->dma_dev.device_terminate_all = fsl_edma_terminate_all;
> > + mcf_edma->dma_dev.device_issue_pending = fsl_edma_issue_pending;
> > +
> > + mcf_edma->dma_dev.src_addr_widths = FSL_EDMA_BUSWIDTHS;
> > + mcf_edma->dma_dev.dst_addr_widths = FSL_EDMA_BUSWIDTHS;
> > + mcf_edma->dma_dev.directions =
> > + BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
> > +
> > + mcf_edma->dma_dev.filter.fn = mcf_edma_filter_fn;
> > + mcf_edma->dma_dev.filter.map = pdata->slave_map;
> > + mcf_edma->dma_dev.filter.mapcnt = pdata->slavecnt;
> > +
> > + platform_set_drvdata(pdev, mcf_edma);
> > +
> > + ret = dma_async_device_register(&mcf_edma->dma_dev);
> > + if (ret) {
> > + dev_err(&pdev->dev,
> > + "Can't register Freescale eDMA engine. (%d)\n", ret);
> > + return ret;
> > + }
> > +
> > + /* Enable round robin arbitration */
> > + iowrite32(EDMA_CR_ERGA | EDMA_CR_ERCA, regs->cr);
> > +
> > + return 0;
> > +}
> > +
> > +static int mcf_edma_remove(struct platform_device *pdev)
> > +{
> > + struct fsl_edma_engine *mcf_edma = platform_get_drvdata(pdev);
> > +
> > + mcf_edma_irq_free(pdev, mcf_edma);
> > + fsl_edma_cleanup_vchan(&mcf_edma->dma_dev);
> > + dma_async_device_unregister(&mcf_edma->dma_dev);
> > +
> > + return 0;
> > +}
> > +
> > +static struct platform_driver mcf_edma_driver = {
> > + .driver = {
> > + .name = "mcf-edma",
> > + },
> > + .probe = mcf_edma_probe,
> > + .remove = mcf_edma_remove,
> > +};
> > +
> > +bool mcf_edma_filter_fn(struct dma_chan *chan, void *param)
> > +{
> > + if (chan->device->dev->driver == &mcf_edma_driver.driver) {
> > + struct fsl_edma_chan *mcf_chan = to_fsl_edma_chan(chan);
> > +
> > + return (mcf_chan->slave_id == (int)param);
> > + }
> > +
> > + return false;
> > +}
> > +EXPORT_SYMBOL(mcf_edma_filter_fn);
> > +
> > +static int __init mcf_edma_init(void)
> > +{
> > + return platform_driver_register(&mcf_edma_driver);
> > +}
> > +subsys_initcall(mcf_edma_init);
> > +
> > +static void __exit mcf_edma_exit(void)
> > +{
> > + platform_driver_unregister(&mcf_edma_driver);
> > +}
> > +module_exit(mcf_edma_exit);
> > +
> > +MODULE_ALIAS("platform:mcf-edma");
> > +MODULE_DESCRIPTION("Freescale eDMA engine driver, ColdFire family");
> > +MODULE_LICENSE("GPL v2");
> > diff --git a/include/linux/platform_data/dma-mcf-edma.h b/include/linux/platform_data/dma-mcf-edma.h
> > new file mode 100644
> > index 000000000000..9a1819acb28f
> > --- /dev/null
> > +++ b/include/linux/platform_data/dma-mcf-edma.h
> > @@ -0,0 +1,38 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Freescale eDMA platform data, ColdFire SoC's family.
> > + *
> > + * Copyright (c) 2017 Angelo Dureghello <angelo@sysam.it>
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#ifndef __MACH_MCF_EDMA_H__
> > +#define __MACH_MCF_EDMA_H__
>
> The guard should rather match current location, e.g.
> __LINUX_PLATFORM_DATA_MCF_EDMA_H__
>
Ack.
> Tested-by: Krzysztof Kozlowski <krzk@kernel.org>
>
> Best regards,
> Krzysztof
> --
> To unsubscribe from this list: send the line "unsubscribe dmaengine" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Regards,
Angelo
WARNING: multiple messages have this Message-ID (diff)
From: angelo@sysam.it (Angelo Dureghello)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v8 3/3] dmaengine: fsl-edma: add ColdFire mcf5441x edma support
Date: Mon, 6 Aug 2018 23:01:10 +0200 [thread overview]
Message-ID: <20180806210110.GD6092@jerusalem> (raw)
In-Reply-To: <CAJKOXPe=+KCwxJULZ5RPpZtemrPr2YARFFxH4jEQsA0bVzrrBA@mail.gmail.com>
Hi Krzysztof,
On Mon, Aug 06, 2018 at 10:09:08AM +0200, Krzysztof Kozlowski wrote:
> On 3 August 2018 at 21:32, Angelo Dureghello <angelo@sysam.it> wrote:
> > This patch adds support for ColdFire mcf5441x-family edma
> > module.
> >
> > The ColdFire edma module is slightly different from fsl-edma,
> > so a new driver is added. But most of the code is common
> > between fsl-edma and mcf-edma so it has been collected into a
> > separate common module fsl-edma-common (patch 1/3).
> >
> > Signed-off-by: Angelo Dureghello <angelo@sysam.it>
> > ---
> > Changes for v7:
> > - patch rewritten from scratch, this patch (3/3) has just been added.
> > ---
> > drivers/dma/Kconfig | 11 +
> > drivers/dma/Makefile | 1 +
> > drivers/dma/fsl-edma-common.c | 24 +-
> > drivers/dma/mcf-edma.c | 315 +++++++++++++++++++++
> > include/linux/platform_data/dma-mcf-edma.h | 38 +++
> > 5 files changed, 385 insertions(+), 4 deletions(-)
> > create mode 100644 drivers/dma/mcf-edma.c
> > create mode 100644 include/linux/platform_data/dma-mcf-edma.h
> >
> > diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
> > index ca1680afa20a..b45008e9c7e9 100644
> > --- a/drivers/dma/Kconfig
> > +++ b/drivers/dma/Kconfig
> > @@ -320,6 +320,17 @@ config LPC18XX_DMAMUX
> > Enable support for DMA on NXP LPC18xx/43xx platforms
> > with PL080 and multiplexed DMA request lines.
> >
> > +config MCF_EDMA
> > + tristate "Freescale eDMA engine support, ColdFire mcf5441x SoCs"
> > + depends on M5441x
> > + select DMA_ENGINE
> > + select DMA_VIRTUAL_CHANNELS
> > + help
> > + Support the Freescale ColdFire eDMA engine, 64-channel
> > + implementation that performs complex data transfers with
> > + minimal intervention from a host processor.
> > + This module can be found on Freescale ColdFire mcf5441x SoCs.
> > +
> > config MMP_PDMA
> > bool "MMP PDMA support"
> > depends on ARCH_MMP || ARCH_PXA || COMPILE_TEST
> > diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
> > index 66022f59fca4..d97f317f4b34 100644
> > --- a/drivers/dma/Makefile
> > +++ b/drivers/dma/Makefile
> > @@ -32,6 +32,7 @@ obj-$(CONFIG_DW_DMAC_CORE) += dw/
> > obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
> > obj-$(CONFIG_FSL_DMA) += fsldma.o
> > obj-$(CONFIG_FSL_EDMA) += fsl-edma.o fsl-edma-common.o
> > +obj-$(CONFIG_MCF_EDMA) += mcf-edma.o fsl-edma-common.o
> > obj-$(CONFIG_FSL_RAID) += fsl_raid.o
> > obj-$(CONFIG_HSU_DMA) += hsu/
> > obj-$(CONFIG_IMG_MDC_DMA) += img-mdc-dma.o
> > diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c
> > index 948a3ee51bbb..5a830a238a0c 100644
> > --- a/drivers/dma/fsl-edma-common.c
> > +++ b/drivers/dma/fsl-edma-common.c
> > @@ -102,8 +102,16 @@ static void fsl_edma_enable_request(struct fsl_edma_chan *fsl_chan)
> > struct edma_regs *regs = &fsl_chan->edma->regs;
> > u32 ch = fsl_chan->vchan.chan.chan_id;
> >
> > - edma_writeb(fsl_chan->edma, EDMA_SEEI_SEEI(ch), regs->seei);
> > - edma_writeb(fsl_chan->edma, ch, regs->serq);
> > + if (fsl_chan->edma->version == v1) {
> > + edma_writeb(fsl_chan->edma, EDMA_SEEI_SEEI(ch), regs->seei);
> > + edma_writeb(fsl_chan->edma, ch, regs->serq);
> > + } else {
> > + /* ColdFire is big endian, and accesses natively
> > + * big endian I/O peripherals
> > + */
> > + iowrite8(EDMA_SEEI_SEEI(ch), regs->seei);
> > + iowrite8(ch, regs->serq);
> > + }
> > }
> >
> > void fsl_edma_disable_request(struct fsl_edma_chan *fsl_chan)
> > @@ -111,8 +119,16 @@ void fsl_edma_disable_request(struct fsl_edma_chan *fsl_chan)
> > struct edma_regs *regs = &fsl_chan->edma->regs;
> > u32 ch = fsl_chan->vchan.chan.chan_id;
> >
> > - edma_writeb(fsl_chan->edma, ch, regs->cerq);
> > - edma_writeb(fsl_chan->edma, EDMA_CEEI_CEEI(ch), regs->ceei);
> > + if (fsl_chan->edma->version == v1) {
> > + edma_writeb(fsl_chan->edma, ch, regs->cerq);
> > + edma_writeb(fsl_chan->edma, EDMA_CEEI_CEEI(ch), regs->ceei);
> > + } else {
> > + /* ColdFire is big endian, and accesses natively
> > + * big endian I/O peripherals
> > + */
> > + iowrite8(ch, regs->cerq);
> > + iowrite8(EDMA_CEEI_CEEI(ch), regs->ceei);
> > + }
> > }
> > EXPORT_SYMBOL_GPL(fsl_edma_disable_request);
> >
> > diff --git a/drivers/dma/mcf-edma.c b/drivers/dma/mcf-edma.c
> > new file mode 100644
> > index 000000000000..31e5317a8f90
> > --- /dev/null
> > +++ b/drivers/dma/mcf-edma.c
> > @@ -0,0 +1,315 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// Copyright (c) 2013-2014 Freescale Semiconductor, Inc
>
> Same comment as to 1/3 - if this is derivative work...
>
Well, in this case the driver is brand new, i maintained the
Freescale Copyright too, since i copied some code from fsl-edma.c.
> > +// Copyright (c) 2017 Sysam, Angelo Dureghello <angelo@sysam.it>
> > +
> > +#include <linux/module.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/dmaengine.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/platform_data/dma-mcf-edma.h>
> > +
> > +#include "fsl-edma-common.h"
> > +
> > +#define EDMA_CHANNELS 64
> > +#define EDMA_MASK_CH(x) ((x) & GENMASK(5, 0))
> > +
> > +static irqreturn_t mcf_edma_tx_handler(int irq, void *dev_id)
> > +{
> > + struct fsl_edma_engine *mcf_edma = dev_id;
> > + struct edma_regs *regs = &mcf_edma->regs;
> > + unsigned int ch;
> > + struct fsl_edma_chan *mcf_chan;
> > + u64 intmap;
> > +
> > + intmap = ioread32(regs->inth);
> > + intmap <<= 32;
> > + intmap |= ioread32(regs->intl);
> > + if (!intmap)
> > + return IRQ_NONE;
> > +
> > + for (ch = 0; ch < mcf_edma->n_chans; ch++) {
> > + if (intmap & BIT(ch)) {
> > + iowrite8(EDMA_MASK_CH(ch), regs->cint);
> > +
> > + mcf_chan = &mcf_edma->chans[ch];
> > +
> > + spin_lock(&mcf_chan->vchan.lock);
> > + if (!mcf_chan->edesc->iscyclic) {
> > + list_del(&mcf_chan->edesc->vdesc.node);
> > + vchan_cookie_complete(&mcf_chan->edesc->vdesc);
> > + mcf_chan->edesc = NULL;
> > + mcf_chan->status = DMA_COMPLETE;
> > + mcf_chan->idle = true;
> > + } else {
> > + vchan_cyclic_callback(&mcf_chan->edesc->vdesc);
> > + }
> > +
> > + if (!mcf_chan->edesc)
> > + fsl_edma_xfer_desc(mcf_chan);
> > +
> > + spin_unlock(&mcf_chan->vchan.lock);
> > + }
> > + }
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +static irqreturn_t mcf_edma_err_handler(int irq, void *dev_id)
> > +{
> > + struct fsl_edma_engine *mcf_edma = dev_id;
> > + struct edma_regs *regs = &mcf_edma->regs;
> > + unsigned int err, ch;
> > +
> > + err = ioread32(regs->errl);
> > + if (!err)
> > + return IRQ_NONE;
> > +
> > + for (ch = 0; ch < (EDMA_CHANNELS / 2); ch++) {
> > + if (err & BIT(ch)) {
> > + fsl_edma_disable_request(&mcf_edma->chans[ch]);
> > + iowrite8(EDMA_CERR_CERR(ch), regs->cerr);
> > + mcf_edma->chans[ch].status = DMA_ERROR;
> > + mcf_edma->chans[ch].idle = true;
> > + }
> > + }
> > +
> > + err = ioread32(regs->errh);
> > + if (!err)
> > + return IRQ_NONE;
> > +
> > + for (ch = (EDMA_CHANNELS / 2); ch < EDMA_CHANNELS; ch++) {
> > + if (err & (BIT(ch - (EDMA_CHANNELS / 2)))) {
> > + fsl_edma_disable_request(&mcf_edma->chans[ch]);
> > + iowrite8(EDMA_CERR_CERR(ch), regs->cerr);
> > + mcf_edma->chans[ch].status = DMA_ERROR;
> > + mcf_edma->chans[ch].idle = true;
> > + }
> > + }
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +static int mcf_edma_irq_init(struct platform_device *pdev,
> > + struct fsl_edma_engine *mcf_edma)
> > +{
> > + int ret = 0, i;
> > + struct resource *res;
> > +
> > + res = platform_get_resource_byname(pdev,
> > + IORESOURCE_IRQ, "edma-tx-00-15");
> > + if (!res)
> > + return -1;
> > +
> > + for (ret = 0, i = res->start; i <= res->end; ++i)
> > + ret |= request_irq(i, mcf_edma_tx_handler, 0, "eDMA", mcf_edma);
> > + if (ret)
> > + return ret;
> > +
> > + res = platform_get_resource_byname(pdev,
> > + IORESOURCE_IRQ, "edma-tx-16-55");
> > + if (!res)
> > + return -1;
> > +
> > + for (ret = 0, i = res->start; i <= res->end; ++i)
> > + ret |= request_irq(i, mcf_edma_tx_handler, 0, "eDMA", mcf_edma);
> > + if (ret)
> > + return ret;
> > +
> > + ret = platform_get_irq_byname(pdev, "edma-tx-56-63");
> > + if (ret != -ENXIO) {
> > + ret = request_irq(ret, mcf_edma_tx_handler,
> > + 0, "eDMA", mcf_edma);
> > + if (ret)
> > + return ret;
> > + }
> > +
> > + ret = platform_get_irq_byname(pdev, "edma-err");
> > + if (ret != -ENXIO) {
> > + ret = request_irq(ret, mcf_edma_err_handler,
> > + 0, "eDMA", mcf_edma);
> > + if (ret)
> > + return ret;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static void mcf_edma_irq_free(struct platform_device *pdev,
> > + struct fsl_edma_engine *mcf_edma)
> > +{
> > + int irq;
> > + struct resource *res;
> > +
> > + res = platform_get_resource_byname(pdev,
> > + IORESOURCE_IRQ, "edma-tx-00-15");
> > + if (res) {
> > + for (irq = res->start; irq <= res->end; irq++)
> > + free_irq(irq, mcf_edma);
> > + }
> > +
> > + res = platform_get_resource_byname(pdev,
> > + IORESOURCE_IRQ, "edma-tx-16-55");
> > + if (res) {
> > + for (irq = res->start; irq <= res->end; irq++)
> > + free_irq(irq, mcf_edma);
> > + }
> > +
> > + irq = platform_get_irq_byname(pdev, "edma-tx-56-63");
> > + if (irq != -ENXIO)
> > + free_irq(irq, mcf_edma);
> > +
> > + irq = platform_get_irq_byname(pdev, "edma-err");
> > + if (irq != -ENXIO)
> > + free_irq(irq, mcf_edma);
> > +}
> > +
> > +static int mcf_edma_probe(struct platform_device *pdev)
> > +{
> > + struct mcf_edma_platform_data *pdata;
> > + struct fsl_edma_engine *mcf_edma;
> > + struct fsl_edma_chan *mcf_chan;
> > + struct edma_regs *regs;
> > + struct resource *res;
> > + int ret, i, len, chans;
> > +
> > + pdata = dev_get_platdata(&pdev->dev);
> > + if (!pdata)
> > + return PTR_ERR(pdata);
> > +
> > + chans = pdata->dma_channels;
> > + len = sizeof(*mcf_edma) + sizeof(*mcf_chan) * chans;
> > + mcf_edma = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
> > + if (!mcf_edma)
> > + return -ENOMEM;
> > +
> > + mcf_edma->n_chans = chans;
> > +
> > + /* Set up version for ColdFire edma */
> > + mcf_edma->version = v2;
> > + mcf_edma->big_endian = 1;
> > +
> > + if (!mcf_edma->n_chans) {
> > + dev_info(&pdev->dev, "setting default channel number to 64");
> > + mcf_edma->n_chans = 64;
> > + }
> > +
> > + mutex_init(&mcf_edma->fsl_edma_mutex);
> > +
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +
> > + mcf_edma->membase = devm_ioremap_resource(&pdev->dev, res);
> > + if (IS_ERR(mcf_edma->membase))
> > + return PTR_ERR(mcf_edma->membase);
> > +
> > + fsl_edma_setup_regs(mcf_edma);
> > + regs = &mcf_edma->regs;
> > +
> > + INIT_LIST_HEAD(&mcf_edma->dma_dev.channels);
> > + for (i = 0; i < mcf_edma->n_chans; i++) {
> > + struct fsl_edma_chan *mcf_chan = &mcf_edma->chans[i];
> > +
> > + mcf_chan->edma = mcf_edma;
> > + mcf_chan->slave_id = i;
> > + mcf_chan->idle = true;
> > + mcf_chan->vchan.desc_free = fsl_edma_free_desc;
> > + vchan_init(&mcf_chan->vchan, &mcf_edma->dma_dev);
> > + iowrite32(0x0, ®s->tcd[i].csr);
> > + }
> > +
> > + iowrite32(~0, regs->inth);
> > + iowrite32(~0, regs->intl);
> > +
> > + ret = mcf_edma_irq_init(pdev, mcf_edma);
> > + if (ret)
> > + return ret;
> > +
> > + dma_cap_set(DMA_PRIVATE, mcf_edma->dma_dev.cap_mask);
> > + dma_cap_set(DMA_SLAVE, mcf_edma->dma_dev.cap_mask);
> > + dma_cap_set(DMA_CYCLIC, mcf_edma->dma_dev.cap_mask);
> > +
> > + mcf_edma->dma_dev.dev = &pdev->dev;
> > + mcf_edma->dma_dev.device_alloc_chan_resources =
> > + fsl_edma_alloc_chan_resources;
> > + mcf_edma->dma_dev.device_free_chan_resources =
> > + fsl_edma_free_chan_resources;
> > + mcf_edma->dma_dev.device_config = fsl_edma_slave_config;
> > + mcf_edma->dma_dev.device_prep_dma_cyclic =
> > + fsl_edma_prep_dma_cyclic;
> > + mcf_edma->dma_dev.device_prep_slave_sg = fsl_edma_prep_slave_sg;
> > + mcf_edma->dma_dev.device_tx_status = fsl_edma_tx_status;
> > + mcf_edma->dma_dev.device_pause = fsl_edma_pause;
> > + mcf_edma->dma_dev.device_resume = fsl_edma_resume;
> > + mcf_edma->dma_dev.device_terminate_all = fsl_edma_terminate_all;
> > + mcf_edma->dma_dev.device_issue_pending = fsl_edma_issue_pending;
> > +
> > + mcf_edma->dma_dev.src_addr_widths = FSL_EDMA_BUSWIDTHS;
> > + mcf_edma->dma_dev.dst_addr_widths = FSL_EDMA_BUSWIDTHS;
> > + mcf_edma->dma_dev.directions =
> > + BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
> > +
> > + mcf_edma->dma_dev.filter.fn = mcf_edma_filter_fn;
> > + mcf_edma->dma_dev.filter.map = pdata->slave_map;
> > + mcf_edma->dma_dev.filter.mapcnt = pdata->slavecnt;
> > +
> > + platform_set_drvdata(pdev, mcf_edma);
> > +
> > + ret = dma_async_device_register(&mcf_edma->dma_dev);
> > + if (ret) {
> > + dev_err(&pdev->dev,
> > + "Can't register Freescale eDMA engine. (%d)\n", ret);
> > + return ret;
> > + }
> > +
> > + /* Enable round robin arbitration */
> > + iowrite32(EDMA_CR_ERGA | EDMA_CR_ERCA, regs->cr);
> > +
> > + return 0;
> > +}
> > +
> > +static int mcf_edma_remove(struct platform_device *pdev)
> > +{
> > + struct fsl_edma_engine *mcf_edma = platform_get_drvdata(pdev);
> > +
> > + mcf_edma_irq_free(pdev, mcf_edma);
> > + fsl_edma_cleanup_vchan(&mcf_edma->dma_dev);
> > + dma_async_device_unregister(&mcf_edma->dma_dev);
> > +
> > + return 0;
> > +}
> > +
> > +static struct platform_driver mcf_edma_driver = {
> > + .driver = {
> > + .name = "mcf-edma",
> > + },
> > + .probe = mcf_edma_probe,
> > + .remove = mcf_edma_remove,
> > +};
> > +
> > +bool mcf_edma_filter_fn(struct dma_chan *chan, void *param)
> > +{
> > + if (chan->device->dev->driver == &mcf_edma_driver.driver) {
> > + struct fsl_edma_chan *mcf_chan = to_fsl_edma_chan(chan);
> > +
> > + return (mcf_chan->slave_id == (int)param);
> > + }
> > +
> > + return false;
> > +}
> > +EXPORT_SYMBOL(mcf_edma_filter_fn);
> > +
> > +static int __init mcf_edma_init(void)
> > +{
> > + return platform_driver_register(&mcf_edma_driver);
> > +}
> > +subsys_initcall(mcf_edma_init);
> > +
> > +static void __exit mcf_edma_exit(void)
> > +{
> > + platform_driver_unregister(&mcf_edma_driver);
> > +}
> > +module_exit(mcf_edma_exit);
> > +
> > +MODULE_ALIAS("platform:mcf-edma");
> > +MODULE_DESCRIPTION("Freescale eDMA engine driver, ColdFire family");
> > +MODULE_LICENSE("GPL v2");
> > diff --git a/include/linux/platform_data/dma-mcf-edma.h b/include/linux/platform_data/dma-mcf-edma.h
> > new file mode 100644
> > index 000000000000..9a1819acb28f
> > --- /dev/null
> > +++ b/include/linux/platform_data/dma-mcf-edma.h
> > @@ -0,0 +1,38 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Freescale eDMA platform data, ColdFire SoC's family.
> > + *
> > + * Copyright (c) 2017 Angelo Dureghello <angelo@sysam.it>
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#ifndef __MACH_MCF_EDMA_H__
> > +#define __MACH_MCF_EDMA_H__
>
> The guard should rather match current location, e.g.
> __LINUX_PLATFORM_DATA_MCF_EDMA_H__
>
Ack.
> Tested-by: Krzysztof Kozlowski <krzk@kernel.org>
>
> Best regards,
> Krzysztof
> --
> To unsubscribe from this list: send the line "unsubscribe dmaengine" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Regards,
Angelo
next reply other threads:[~2018-08-06 21:01 UTC|newest]
Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-08-06 21:01 Angelo Dureghello [this message]
2018-08-06 21:01 ` [PATCH v8 3/3] dmaengine: fsl-edma: add ColdFire mcf5441x edma support Angelo Dureghello
2018-08-06 21:01 ` Angelo Dureghello
-- strict thread matches above, loose matches on Subject: below --
2018-08-10 8:43 [v8,1/3] dmaengine: fsl-edma: extract common fsl-edma code (no changes in behavior intended) Angelo Dureghello
2018-08-10 8:43 ` [PATCH v8 1/3] " Angelo Dureghello
2018-08-10 8:43 ` Angelo Dureghello
2018-08-10 8:05 [v8,1/3] " Stefan Agner
2018-08-10 8:05 ` [PATCH v8 1/3] " Stefan Agner
2018-08-10 8:05 ` Stefan Agner
2018-08-09 22:37 [v8,1/3] " Angelo Dureghello
2018-08-09 22:37 ` [PATCH v8 1/3] " Angelo Dureghello
2018-08-09 22:37 ` Angelo Dureghello
2018-08-07 17:47 [v8,1/3] " Stefan Agner
2018-08-07 17:47 ` [PATCH v8 1/3] " Stefan Agner
2018-08-07 17:47 ` Stefan Agner
2018-08-07 12:14 [v8,1/3] " Krzysztof Kozlowski
2018-08-07 12:14 ` [PATCH v8 1/3] " Krzysztof Kozlowski
2018-08-07 12:14 ` Krzysztof Kozlowski
2018-08-07 8:08 [v8,1/3] " Stefan Agner
2018-08-07 8:08 ` [PATCH v8 1/3] " Stefan Agner
2018-08-07 8:08 ` Stefan Agner
2018-08-07 8:01 [v8,2/3] dmaengine: fsl-edma: add edma version and configurable registers Stefan Agner
2018-08-07 8:01 ` [PATCH v8 2/3] " Stefan Agner
2018-08-07 8:01 ` Stefan Agner
2018-08-07 6:02 [v8,1/3] dmaengine: fsl-edma: extract common fsl-edma code (no changes in behavior intended) Krzysztof Kozlowski
2018-08-07 6:02 ` [PATCH v8 1/3] " Krzysztof Kozlowski
2018-08-07 6:02 ` Krzysztof Kozlowski
2018-08-06 20:40 [v8,1/3] " Angelo Dureghello
2018-08-06 20:40 ` [PATCH v8 1/3] " Angelo Dureghello
2018-08-06 20:40 ` Angelo Dureghello
2018-08-06 20:31 [v8,2/3] dmaengine: fsl-edma: add edma version and configurable registers Angelo Dureghello
2018-08-06 20:31 ` [PATCH v8 2/3] " Angelo Dureghello
2018-08-06 20:31 ` Angelo Dureghello
2018-08-06 20:23 [v8,3/3] dmaengine: fsl-edma: add ColdFire mcf5441x edma support Angelo Dureghello
2018-08-06 20:23 ` [PATCH v8 3/3] " Angelo Dureghello
2018-08-06 20:23 ` Angelo Dureghello
2018-08-06 12:21 [v8,3/3] " Stefan Agner
2018-08-06 12:21 ` [PATCH v8 3/3] " Stefan Agner
2018-08-06 12:21 ` Stefan Agner
2018-08-06 8:09 [v8,3/3] " Krzysztof Kozlowski
2018-08-06 8:09 ` [PATCH v8 3/3] " Krzysztof Kozlowski
2018-08-06 8:09 ` Krzysztof Kozlowski
2018-08-06 7:59 [v8,2/3] dmaengine: fsl-edma: add edma version and configurable registers Krzysztof Kozlowski
2018-08-06 7:59 ` [PATCH v8 2/3] " Krzysztof Kozlowski
2018-08-06 7:59 ` Krzysztof Kozlowski
2018-08-06 7:43 [v8,1/3] dmaengine: fsl-edma: extract common fsl-edma code (no changes in behavior intended) Krzysztof Kozlowski
2018-08-06 7:43 ` [PATCH v8 1/3] " Krzysztof Kozlowski
2018-08-06 7:43 ` Krzysztof Kozlowski
2018-08-03 19:32 [v8,3/3] dmaengine: fsl-edma: add ColdFire mcf5441x edma support Angelo Dureghello
2018-08-03 19:32 ` [PATCH v8 3/3] " Angelo Dureghello
2018-08-03 19:32 ` Angelo Dureghello
2018-08-03 19:32 [v8,2/3] dmaengine: fsl-edma: add edma version and configurable registers Angelo Dureghello
2018-08-03 19:32 ` [PATCH v8 2/3] " Angelo Dureghello
2018-08-03 19:32 ` Angelo Dureghello
2018-08-03 19:32 [v8,1/3] dmaengine: fsl-edma: extract common fsl-edma code (no changes in behavior intended) Angelo Dureghello
2018-08-03 19:32 ` [PATCH v8 1/3] " Angelo Dureghello
2018-08-03 19:32 ` Angelo Dureghello
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180806210110.GD6092@jerusalem \
--to=angelo@sysam.it \
--cc=dmaengine@vger.kernel.org \
--cc=krzk@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-m68k@vger.kernel.org \
--cc=stefan@agner.ch \
--cc=vinod.koul@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.