Re: [PATCH v3 4/7] dma: dmamux: Introduce RZN1 DMA router support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Miquel,

Thank you for the patch.

On Fri, Feb 25, 2022 at 12:09 PM Miquel Raynal
<miquel.raynal@xxxxxxxxxxx> wrote:
>
> The Renesas RZN1 DMA IP is a based on a DW core, with eg. an additional
> dmamux register located in the system control area which can take up to
> 32 requests (16 per DMA controller). Each DMA channel can be wired to
> two different peripherals.
>
> We need two additional information from the 'dmas' property: the channel
> (bit in the dmamux register) that must be accessed and the value of the
> mux for this channel.
>
> Signed-off-by: Miquel Raynal <miquel.raynal@xxxxxxxxxxx>
> ---
>  drivers/dma/dw/Kconfig       |   8 ++
>  drivers/dma/dw/Makefile      |   2 +
>  drivers/dma/dw/rzn1-dmamux.c | 152 +++++++++++++++++++++++++++++++++++
>  3 files changed, 162 insertions(+)
>  create mode 100644 drivers/dma/dw/rzn1-dmamux.c
>
> diff --git a/drivers/dma/dw/Kconfig b/drivers/dma/dw/Kconfig
> index db25f9b7778c..dd53d4a9fa92 100644
> --- a/drivers/dma/dw/Kconfig
> +++ b/drivers/dma/dw/Kconfig
> @@ -16,6 +16,14 @@ config DW_DMAC
>           Support the Synopsys DesignWare AHB DMA controller. This
>           can be integrated in chips such as the Intel Cherrytrail.
>
> +config RZN1_DMAMUX
> +       tristate "Renesas RZ/N1 DMAMUX driver"
> +       depends on DW_DMAC
Maybe dependencies for ARCH_RZN1and COMPILE_TEST too?

> +       help
> +         Support the Renesas RZ/N1 DMAMUX which is located in front of
> +         the Synopsys DesignWare AHB DMA controller located on Renesas
> +         SoCs.
> +
>  config DW_DMAC_PCI
>         tristate "Synopsys DesignWare AHB DMA PCI driver"
>         depends on PCI
> diff --git a/drivers/dma/dw/Makefile b/drivers/dma/dw/Makefile
> index a6f358ad8591..8025f75e589c 100644
> --- a/drivers/dma/dw/Makefile
> +++ b/drivers/dma/dw/Makefile
> @@ -7,5 +7,7 @@ obj-$(CONFIG_DW_DMAC)           += dw_dmac.o
>  dw_dmac-y                      := platform.o
>  dw_dmac-$(CONFIG_OF)           += of.o
>
> +obj-$(CONFIG_RZN1_DMAMUX)      += rzn1-dmamux.o
> +
>  obj-$(CONFIG_DW_DMAC_PCI)      += dw_dmac_pci.o
>  dw_dmac_pci-y                  := pci.o
> diff --git a/drivers/dma/dw/rzn1-dmamux.c b/drivers/dma/dw/rzn1-dmamux.c
> new file mode 100644
> index 000000000000..bc4e2e7c3d18
> --- /dev/null
> +++ b/drivers/dma/dw/rzn1-dmamux.c
> @@ -0,0 +1,152 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2022 Schneider-Electric
> + * Author: Miquel Raynal <miquel.raynal@xxxxxxxxxxx
> + * Based on TI crossbar driver written by Peter Ujfalusi <peter.ujfalusi@xxxxxx>
> + */
> +#include <linux/slab.h>
> +#include <linux/err.h>
> +#include <linux/init.h>
> +#include <linux/list.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
can you please check if the above four includes are really required.

> +#include <linux/of_device.h>
> +#include <linux/of_dma.h>
> +#include <linux/soc/renesas/r9a06g032-sysctrl.h>
> +
headers need to be sorted.

> +#define RZN1_DMAMUX_LINES 64
> +#define RZN1_DMAMUX_SPLIT 16
> +
> +struct rzn1_dmamux_data {
> +       struct dma_router dmarouter;
> +       u32 used_chans;
> +       struct mutex lock;
> +};
> +
> +struct rzn1_dmamux_map {
> +       unsigned int req_idx;
> +};
> +
> +static void rzn1_dmamux_free(struct device *dev, void *route_data)
> +{
> +       struct rzn1_dmamux_data *dmamux = dev_get_drvdata(dev);
> +       struct rzn1_dmamux_map *map = route_data;
> +
> +       dev_dbg(dev, "Unmapping DMAMUX request %u\n", map->req_idx);
> +
> +       mutex_lock(&dmamux->lock);
> +       dmamux->used_chans &= ~BIT(map->req_idx);
> +       mutex_unlock(&dmamux->lock);
> +
> +       kfree(map);
> +}
> +
> +static void *rzn1_dmamux_route_allocate(struct of_phandle_args *dma_spec,
> +                                       struct of_dma *ofdma)
> +{
> +       struct platform_device *pdev = of_find_device_by_node(ofdma->of_node);
> +       struct rzn1_dmamux_data *dmamux = platform_get_drvdata(pdev);
> +       struct rzn1_dmamux_map *map;
> +       unsigned int dmac_idx, chan, val;
> +       u32 mask;
> +       int ret;
> +
> +       map = kzalloc(sizeof(*map), GFP_KERNEL);
> +       if (!map)
> +               return ERR_PTR(-ENOMEM);
> +
map needs to be freed in the error path.

> +       if (dma_spec->args_count != 6)
> +               return ERR_PTR(-EINVAL);
> +
> +       chan = dma_spec->args[0];
> +       map->req_idx = dma_spec->args[4];
> +       val = dma_spec->args[5];
> +       dma_spec->args_count -= 2;
> +
> +       if (chan >= RZN1_DMAMUX_SPLIT) {
> +               dev_err(&pdev->dev, "Invalid DMA request line: %u\n", chan);
> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       if (map->req_idx >= RZN1_DMAMUX_LINES ||
> +           (map->req_idx % RZN1_DMAMUX_SPLIT) != chan) {
> +               dev_err(&pdev->dev, "Invalid MUX request line: %u\n", map->req_idx);
> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       dmac_idx = map->req_idx < RZN1_DMAMUX_SPLIT ? 0 : 1;
> +       dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", dmac_idx);
> +       if (!dma_spec->np) {
> +               dev_err(&pdev->dev, "Can't get DMA master\n");
> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       dev_dbg(&pdev->dev, "Mapping DMAMUX request %u to DMAC%u request %u\n",
> +               map->req_idx, dmac_idx, chan);
> +
> +       mask = BIT(map->req_idx);
> +       mutex_lock(&dmamux->lock);
> +       dmamux->used_chans |= mask;
> +       ret = r9a06g032_sysctrl_set_dmamux(mask, val ? mask : 0);
> +       mutex_unlock(&dmamux->lock);
> +       if (ret) {
> +               rzn1_dmamux_free(&pdev->dev, map);
> +               return ERR_PTR(ret);
> +       }
> +
> +       return map;
> +}
> +
> +static const struct of_device_id rzn1_dmac_match[] __maybe_unused = {
any reason for using __maybe_unused?

> +       { .compatible = "renesas,rzn1-dma" },
> +       {},
"," not required.

> +};
> +
> +static int rzn1_dmamux_probe(struct platform_device *pdev)
> +{
> +       struct device_node *mux_node = pdev->dev.of_node;
> +       const struct of_device_id *match;
> +       struct device_node *dmac_node;
> +       struct rzn1_dmamux_data *dmamux;
> +
> +       dmamux = devm_kzalloc(&pdev->dev, sizeof(*dmamux), GFP_KERNEL);
> +       if (!dmamux)
> +               return -ENOMEM;
> +
> +       mutex_init(&dmamux->lock);
> +
> +       dmac_node = of_parse_phandle(mux_node, "dma-masters", 0);
> +       if (!dmac_node)
> +               return dev_err_probe(&pdev->dev, -ENODEV, "Can't get DMA master node\n");
> +
> +       match = of_match_node(rzn1_dmac_match, dmac_node);
> +       of_node_put(dmac_node);
> +       if (!match)
> +               return dev_err_probe(&pdev->dev, -EINVAL, "DMA master is not supported\n");
> +
> +       dmamux->dmarouter.dev = &pdev->dev;
> +       dmamux->dmarouter.route_free = rzn1_dmamux_free;
> +
> +       platform_set_drvdata(pdev, dmamux);
> +
> +       return of_dma_router_register(mux_node, rzn1_dmamux_route_allocate,
> +                                     &dmamux->dmarouter);
> +}
> +
> +static const struct of_device_id rzn1_dmamux_match[] = {
> +       { .compatible = "renesas,rzn1-dmamux" },
> +       {},
"," not required.

> +};
> +
> +static struct platform_driver rzn1_dmamux_driver = {
> +       .driver = {
> +               .name = "renesas,rzn1-dmamux",
> +               .of_match_table = rzn1_dmamux_match,
> +       },
> +       .probe  = rzn1_dmamux_probe,
> +};
> +module_platform_driver(rzn1_dmamux_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Miquel Raynal <miquel.raynal@xxxxxxxxxxx");
> +MODULE_DESCRIPTION("Renesas RZ/N1 DMAMUX driver");
> --
> 2.27.0
>

Cheers,
Prabhakar



[Index of Archives]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux PCI]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux