* [PATCH 0/4] PL08x DT bindings and LPC18xx DMA support
@ 2015-07-11 12:12 Joachim Eastwood
2015-07-11 12:12 ` [PATCH 1/4] dmaengine: pl08x: support dt channel assignment Joachim Eastwood
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Joachim Eastwood @ 2015-07-11 12:12 UTC (permalink / raw)
To: linux-arm-kernel
Hi Vinod,
This is the non-RFC version of the patch set with only a few changes.
Hope this can go in for 4.3. Changes to the DT for LPC18xx/43xx will
go thru arm-soc once this get accepted.
This patch set aims to add support for DMA on the NXP LPC18xx/43xx
(Cortex-M3/M4) platform. The platform has a PL080 controller with a
mux in front of the DMA request lines. This setup is quite common
and can be found on most other, if not all, NXP LPC devices.
Patch set adds DT support for the PL08x dmaengine driver and a DMA
router driver for the LPC18xx/43xx DMA multiplexer.
DT support for the PL08x was originally written by Linus Walleij and
can be found on the link below.
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-September/286866.html
Changes since RFC:
- remove some useless headers from dmamux driver.
- turn a dev_info into dev_dbg in dmamux driver.
The following changes has since been made to the pl08x dt patch by
Linus:
- move AHB master setting into dma specifier as
suggested by Arnd [1].
- remove channel sub-nodes from driver and dt doc.
- dynamically allocate dma channels in xlate
function as outlined by Arnd [2].
- address some minor comments from Arnd in [1].
- minor misc clean ups (white space + include order).
Patch set successfully tested on 8250 UART (TX) with DMA support on
Embedded Artists' LPC4357 Developer's Kit.
[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2014-September/287834.html
[2] http://lists.infradead.org/pipermail/linux-arm-kernel/2014-September/286150.html
Joachim Eastwood (2):
dmaengine: add driver for lpc18xx dmamux
doc: dt: dma: add bindings for lpc1850-dmamux
Linus Walleij (2):
dmaengine: pl08x: support dt channel assignment
doc: dt: dma: add binding doc for pl08x
.../devicetree/bindings/dma/arm-pl08x.txt | 54 ++++++
.../devicetree/bindings/dma/lpc1850-dmamux.txt | 54 ++++++
drivers/dma/Kconfig | 9 +
drivers/dma/Makefile | 1 +
drivers/dma/amba-pl08x.c | 192 ++++++++++++++++++++-
drivers/dma/lpc18xx-dmamux.c | 183 ++++++++++++++++++++
6 files changed, 490 insertions(+), 3 deletions(-)
create mode 100644 Documentation/devicetree/bindings/dma/arm-pl08x.txt
create mode 100644 Documentation/devicetree/bindings/dma/lpc1850-dmamux.txt
create mode 100644 drivers/dma/lpc18xx-dmamux.c
--
1.8.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/4] dmaengine: pl08x: support dt channel assignment
2015-07-11 12:12 [PATCH 0/4] PL08x DT bindings and LPC18xx DMA support Joachim Eastwood
@ 2015-07-11 12:12 ` Joachim Eastwood
2015-07-11 12:12 ` [PATCH 2/4] doc: dt: dma: add binding doc for pl08x Joachim Eastwood
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Joachim Eastwood @ 2015-07-11 12:12 UTC (permalink / raw)
To: linux-arm-kernel
From: Linus Walleij <linus.walleij@linaro.org>
Add support for assigning DMA channels from a device tree.
[je: remove channel sub-node parsing, dynamic channel creation on xlate]
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Joachim Eastwood <manabian@gmail.com>
---
drivers/dma/amba-pl08x.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 189 insertions(+), 3 deletions(-)
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 5de3cf453f35..9b42c0588550 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -83,6 +83,8 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_dma.h>
#include <linux/pm_runtime.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
@@ -2030,10 +2032,188 @@ static inline void init_pl08x_debugfs(struct pl08x_driver_data *pl08x)
}
#endif
+#ifdef CONFIG_OF
+static struct dma_chan *pl08x_find_chan_id(struct pl08x_driver_data *pl08x,
+ u32 id)
+{
+ struct pl08x_dma_chan *chan;
+
+ list_for_each_entry(chan, &pl08x->slave.channels, vc.chan.device_node) {
+ if (chan->signal == id)
+ return &chan->vc.chan;
+ }
+
+ return NULL;
+}
+
+static struct dma_chan *pl08x_of_xlate(struct of_phandle_args *dma_spec,
+ struct of_dma *ofdma)
+{
+ struct pl08x_driver_data *pl08x = ofdma->of_dma_data;
+ struct pl08x_channel_data *data;
+ struct pl08x_dma_chan *chan;
+ struct dma_chan *dma_chan;
+
+ if (!pl08x)
+ return NULL;
+
+ if (dma_spec->args_count != 2)
+ return NULL;
+
+ dma_chan = pl08x_find_chan_id(pl08x, dma_spec->args[0]);
+ if (dma_chan)
+ return dma_get_slave_channel(dma_chan);
+
+ chan = devm_kzalloc(pl08x->slave.dev, sizeof(*chan) + sizeof(*data),
+ GFP_KERNEL);
+ if (!chan)
+ return NULL;
+
+ data = (void *)&chan[1];
+ data->bus_id = "(none)";
+ data->periph_buses = dma_spec->args[1];
+
+ chan->cd = data;
+ chan->host = pl08x;
+ chan->slave = true;
+ chan->name = data->bus_id;
+ chan->state = PL08X_CHAN_IDLE;
+ chan->signal = dma_spec->args[0];
+ chan->vc.desc_free = pl08x_desc_free;
+
+ vchan_init(&chan->vc, &pl08x->slave);
+
+ return dma_get_slave_channel(&chan->vc.chan);
+}
+
+static int pl08x_of_probe(struct amba_device *adev,
+ struct pl08x_driver_data *pl08x,
+ struct device_node *np)
+{
+ struct pl08x_platform_data *pd;
+ u32 cctl_memcpy = 0;
+ u32 val;
+ int ret;
+
+ pd = devm_kzalloc(&adev->dev, sizeof(*pd), GFP_KERNEL);
+ if (!pd)
+ return -ENOMEM;
+
+ /* Eligible bus masters for fetching LLIs */
+ if (of_property_read_bool(np, "lli-bus-interface-ahb1"))
+ pd->lli_buses |= PL08X_AHB1;
+ if (of_property_read_bool(np, "lli-bus-interface-ahb2"))
+ pd->lli_buses |= PL08X_AHB2;
+ if (!pd->lli_buses) {
+ dev_info(&adev->dev, "no bus masters for LLIs stated, assume all\n");
+ pd->lli_buses |= PL08X_AHB1 | PL08X_AHB2;
+ }
+
+ /* Eligible bus masters for memory access */
+ if (of_property_read_bool(np, "mem-bus-interface-ahb1"))
+ pd->mem_buses |= PL08X_AHB1;
+ if (of_property_read_bool(np, "mem-bus-interface-ahb2"))
+ pd->mem_buses |= PL08X_AHB2;
+ if (!pd->mem_buses) {
+ dev_info(&adev->dev, "no bus masters for memory stated, assume all\n");
+ pd->mem_buses |= PL08X_AHB1 | PL08X_AHB2;
+ }
+
+ /* Parse the memcpy channel properties */
+ ret = of_property_read_u32(np, "memcpy-burst-size", &val);
+ if (ret) {
+ dev_info(&adev->dev, "no memcpy burst size specified, using 1 byte\n");
+ val = 1;
+ }
+ switch (val) {
+ default:
+ dev_err(&adev->dev, "illegal burst size for memcpy, set to 1\n");
+ /* Fall through */
+ case 1:
+ cctl_memcpy |= PL080_BSIZE_1 << PL080_CONTROL_SB_SIZE_SHIFT |
+ PL080_BSIZE_1 << PL080_CONTROL_DB_SIZE_SHIFT;
+ break;
+ case 4:
+ cctl_memcpy |= PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
+ PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT;
+ break;
+ case 8:
+ cctl_memcpy |= PL080_BSIZE_8 << PL080_CONTROL_SB_SIZE_SHIFT |
+ PL080_BSIZE_8 << PL080_CONTROL_DB_SIZE_SHIFT;
+ break;
+ case 16:
+ cctl_memcpy |= PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT |
+ PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT;
+ break;
+ case 32:
+ cctl_memcpy |= PL080_BSIZE_32 << PL080_CONTROL_SB_SIZE_SHIFT |
+ PL080_BSIZE_32 << PL080_CONTROL_DB_SIZE_SHIFT;
+ break;
+ case 64:
+ cctl_memcpy |= PL080_BSIZE_64 << PL080_CONTROL_SB_SIZE_SHIFT |
+ PL080_BSIZE_64 << PL080_CONTROL_DB_SIZE_SHIFT;
+ break;
+ case 128:
+ cctl_memcpy |= PL080_BSIZE_128 << PL080_CONTROL_SB_SIZE_SHIFT |
+ PL080_BSIZE_128 << PL080_CONTROL_DB_SIZE_SHIFT;
+ break;
+ case 256:
+ cctl_memcpy |= PL080_BSIZE_256 << PL080_CONTROL_SB_SIZE_SHIFT |
+ PL080_BSIZE_256 << PL080_CONTROL_DB_SIZE_SHIFT;
+ break;
+ }
+
+ ret = of_property_read_u32(np, "memcpy-bus-width", &val);
+ if (ret) {
+ dev_info(&adev->dev, "no memcpy bus width specified, using 8 bits\n");
+ val = 8;
+ }
+ switch (val) {
+ default:
+ dev_err(&adev->dev, "illegal bus width for memcpy, set to 8 bits\n");
+ /* Fall through */
+ case 8:
+ cctl_memcpy |= PL080_WIDTH_8BIT << PL080_CONTROL_SWIDTH_SHIFT |
+ PL080_WIDTH_8BIT << PL080_CONTROL_DWIDTH_SHIFT;
+ break;
+ case 16:
+ cctl_memcpy |= PL080_WIDTH_16BIT << PL080_CONTROL_SWIDTH_SHIFT |
+ PL080_WIDTH_16BIT << PL080_CONTROL_DWIDTH_SHIFT;
+ break;
+ case 32:
+ cctl_memcpy |= PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
+ PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT;
+ break;
+ }
+
+ /* This is currently the only thing making sense */
+ cctl_memcpy |= PL080_CONTROL_PROT_SYS;
+
+ /* Set up memcpy channel */
+ pd->memcpy_channel.bus_id = "memcpy";
+ pd->memcpy_channel.cctl_memcpy = cctl_memcpy;
+ /* Use the buses that can access memory, obviously */
+ pd->memcpy_channel.periph_buses = pd->mem_buses;
+
+ pl08x->pd = pd;
+
+ return of_dma_controller_register(adev->dev.of_node, pl08x_of_xlate,
+ pl08x);
+}
+#else
+static inline int pl08x_of_probe(struct amba_device *adev,
+ struct pl08x_driver_data *pl08x,
+ struct device_node *np)
+{
+ return -EINVAL;
+}
+#endif
+
static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
{
struct pl08x_driver_data *pl08x;
const struct vendor_data *vd = id->data;
+ struct device_node *np = adev->dev.of_node;
u32 tsfr_size;
int ret = 0;
int i;
@@ -2093,9 +2273,15 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
/* Get the platform data */
pl08x->pd = dev_get_platdata(&adev->dev);
if (!pl08x->pd) {
- dev_err(&adev->dev, "no platform data supplied\n");
- ret = -EINVAL;
- goto out_no_platdata;
+ if (np) {
+ ret = pl08x_of_probe(adev, pl08x, np);
+ if (ret)
+ goto out_no_platdata;
+ } else {
+ dev_err(&adev->dev, "no platform data supplied\n");
+ ret = -EINVAL;
+ goto out_no_platdata;
+ }
}
/* Assign useful pointers to the driver state */
--
1.8.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/4] doc: dt: dma: add binding doc for pl08x
2015-07-11 12:12 [PATCH 0/4] PL08x DT bindings and LPC18xx DMA support Joachim Eastwood
2015-07-11 12:12 ` [PATCH 1/4] dmaengine: pl08x: support dt channel assignment Joachim Eastwood
@ 2015-07-11 12:12 ` Joachim Eastwood
2015-07-11 12:12 ` [PATCH 3/4] dmaengine: add driver for lpc18xx dmamux Joachim Eastwood
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Joachim Eastwood @ 2015-07-11 12:12 UTC (permalink / raw)
To: linux-arm-kernel
From: Linus Walleij <linus.walleij@linaro.org>
This introduces device tree bindings for the PL08x DMA controllers
when used with fixed signal assignment per channel, i.e. if each
channel on the PL08x is assigned precisely one burst/single signal
set.
[je: remove channel sub-node parsing, use cell value to assign AHB]
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Joachim Eastwood <manabian@gmail.com>
---
.../devicetree/bindings/dma/arm-pl08x.txt | 54 ++++++++++++++++++++++
1 file changed, 54 insertions(+)
create mode 100644 Documentation/devicetree/bindings/dma/arm-pl08x.txt
diff --git a/Documentation/devicetree/bindings/dma/arm-pl08x.txt b/Documentation/devicetree/bindings/dma/arm-pl08x.txt
new file mode 100644
index 000000000000..8a0097a029d3
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/arm-pl08x.txt
@@ -0,0 +1,54 @@
+* ARM PrimeCells PL080 and PL081 and derivatives DMA controller
+
+Required properties:
+- compatible: "arm,pl080", "arm,primecell";
+ "arm,pl081", "arm,primecell";
+- reg: Address range of the PL08x registers
+- interrupt: The PL08x interrupt number
+- clocks: The clock running the IP core clock
+- clock-names: Must contain "apb_pclk"
+- lli-bus-interface-ahb1: if AHB master 1 is eligible for fetching LLIs
+- lli-bus-interface-ahb2: if AHB master 2 is eligible for fetching LLIs
+- mem-bus-interface-ahb1: if AHB master 1 is eligible for fetching memory contents
+- mem-bus-interface-ahb2: if AHB master 2 is eligible for fetching memory contents
+- #dma-cells: must be <2>. First cell should contain the DMA request,
+ second cell should contain either 1 or 2 depending on
+ which AHB master that is used.
+
+Optional properties:
+- dma-channels: contains the total number of DMA channels supported by the DMAC
+- dma-requests: contains the total number of DMA requests supported by the DMAC
+- memcpy-burst-size: the size of the bursts for memcpy: 1, 4, 8, 16, 32
+ 64, 128 or 256 bytes are legal values
+- memcpy-bus-width: the bus width used for memcpy: 8, 16 or 32 are legal
+ values
+
+Clients
+Required properties:
+- dmas: List of DMA controller phandle, request channel and AHB master id
+- dma-names: Names of the aforementioned requested channels
+
+Example:
+
+dmac0: dma-controller at 10130000 {
+ compatible = "arm,pl080", "arm,primecell";
+ reg = <0x10130000 0x1000>;
+ interrupt-parent = <&vica>;
+ interrupts = <15>;
+ clocks = <&hclkdma0>;
+ clock-names = "apb_pclk";
+ lli-bus-interface-ahb1;
+ lli-bus-interface-ahb2;
+ mem-bus-interface-ahb2;
+ memcpy-burst-size = <256>;
+ memcpy-bus-width = <32>;
+ #dma-cells = <2>;
+};
+
+device at 40008000 {
+ ...
+ dmas = <&dmac0 0 2
+ &dmac0 1 2>;
+ dma-names = "tx", "rx";
+ ...
+};
--
1.8.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/4] dmaengine: add driver for lpc18xx dmamux
2015-07-11 12:12 [PATCH 0/4] PL08x DT bindings and LPC18xx DMA support Joachim Eastwood
2015-07-11 12:12 ` [PATCH 1/4] dmaengine: pl08x: support dt channel assignment Joachim Eastwood
2015-07-11 12:12 ` [PATCH 2/4] doc: dt: dma: add binding doc for pl08x Joachim Eastwood
@ 2015-07-11 12:12 ` Joachim Eastwood
2015-07-11 12:12 ` [PATCH 4/4] doc: dt: dma: add bindings for lpc1850-dmamux Joachim Eastwood
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Joachim Eastwood @ 2015-07-11 12:12 UTC (permalink / raw)
To: linux-arm-kernel
Add support for DMA on NXP LPC18xx/43xx platforms which has
a multiplexer in front of the PL080 dma request lines.
The mux is a single register in the LPC18xx/43xx CREG block
and can multiplex up to 4 request lines to each of the 16
lines on the PL080.
Signed-off-by: Joachim Eastwood <manabian@gmail.com>
---
drivers/dma/Kconfig | 9 +++
drivers/dma/Makefile | 1 +
drivers/dma/lpc18xx-dmamux.c | 183 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 193 insertions(+)
create mode 100644 drivers/dma/lpc18xx-dmamux.c
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 88d474b78076..9d5a77cb9715 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -63,6 +63,15 @@ config AMBA_PL08X
Platform has a PL08x DMAC device
which can provide DMA engine support
+config LPC18XX_DMAMUX
+ bool "NXP LPC18xx/43xx DMA MUX for PL080"
+ depends on ARCH_LPC18XX || COMPILE_TEST
+ depends on OF && AMBA_PL08X
+ select MFD_SYSCON
+ help
+ Enable support for DMA on NXP LPC18xx/43xx platforms
+ with PL080 and multiplexed DMA request lines.
+
config INTEL_IOATDMA
tristate "Intel I/OAT DMA support"
depends on PCI && X86
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 6a4d6f2827da..800cb2d20be8 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_TI_EDMA) += edma.o
obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
obj-$(CONFIG_TEGRA20_APB_DMA) += tegra20-apb-dma.o
obj-$(CONFIG_S3C24XX_DMAC) += s3c24xx-dma.o
+obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o
obj-$(CONFIG_PL330_DMA) += pl330.o
obj-$(CONFIG_PCH_DMA) += pch_dma.o
obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o
diff --git a/drivers/dma/lpc18xx-dmamux.c b/drivers/dma/lpc18xx-dmamux.c
new file mode 100644
index 000000000000..761f32687055
--- /dev/null
+++ b/drivers/dma/lpc18xx-dmamux.c
@@ -0,0 +1,183 @@
+/*
+ * DMA Router driver for LPC18xx/43xx DMA MUX
+ *
+ * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
+ *
+ * Based on TI DMA Crossbar driver by:
+ * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * 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.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_device.h>
+#include <linux/of_dma.h>
+#include <linux/regmap.h>
+#include <linux/spinlock.h>
+
+/* CREG register offset and macros for mux manipulation */
+#define LPC18XX_CREG_DMAMUX 0x11c
+#define LPC18XX_DMAMUX_VAL(v, n) ((v) << (n * 2))
+#define LPC18XX_DMAMUX_MASK(n) (0x3 << (n * 2))
+#define LPC18XX_DMAMUX_MAX_VAL 0x3
+
+struct lpc18xx_dmamux {
+ u32 value;
+ bool busy;
+};
+
+struct lpc18xx_dmamux_data {
+ struct dma_router dmarouter;
+ struct lpc18xx_dmamux *muxes;
+ u32 dma_master_requests;
+ u32 dma_mux_requests;
+ struct regmap *reg;
+ spinlock_t lock;
+};
+
+static void lpc18xx_dmamux_free(struct device *dev, void *route_data)
+{
+ struct lpc18xx_dmamux_data *dmamux = dev_get_drvdata(dev);
+ struct lpc18xx_dmamux *mux = route_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dmamux->lock, flags);
+ mux->busy = false;
+ spin_unlock_irqrestore(&dmamux->lock, flags);
+}
+
+static void *lpc18xx_dmamux_reserve(struct of_phandle_args *dma_spec,
+ struct of_dma *ofdma)
+{
+ struct platform_device *pdev = of_find_device_by_node(ofdma->of_node);
+ struct lpc18xx_dmamux_data *dmamux = platform_get_drvdata(pdev);
+ unsigned long flags;
+ unsigned mux;
+
+ if (dma_spec->args_count != 3) {
+ dev_err(&pdev->dev, "invalid number of dma mux args\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ mux = dma_spec->args[0];
+ if (mux >= dmamux->dma_master_requests) {
+ dev_err(&pdev->dev, "invalid mux number: %d\n",
+ dma_spec->args[0]);
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (dma_spec->args[1] > LPC18XX_DMAMUX_MAX_VAL) {
+ dev_err(&pdev->dev, "invalid dma mux value: %d\n",
+ dma_spec->args[1]);
+ return ERR_PTR(-EINVAL);
+ }
+
+ /* The of_node_put() will be done in the core for the node */
+ dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", 0);
+ if (!dma_spec->np) {
+ dev_err(&pdev->dev, "can't get dma master\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ spin_lock_irqsave(&dmamux->lock, flags);
+ if (dmamux->muxes[mux].busy) {
+ spin_unlock_irqrestore(&dmamux->lock, flags);
+ dev_err(&pdev->dev, "dma request %u busy with %u.%u\n",
+ mux, mux, dmamux->muxes[mux].value);
+ of_node_put(dma_spec->np);
+ return ERR_PTR(-EBUSY);
+ }
+
+ dmamux->muxes[mux].busy = true;
+ dmamux->muxes[mux].value = dma_spec->args[1];
+
+ regmap_update_bits(dmamux->reg, LPC18XX_CREG_DMAMUX,
+ LPC18XX_DMAMUX_MASK(mux),
+ LPC18XX_DMAMUX_VAL(dmamux->muxes[mux].value, mux));
+ spin_unlock_irqrestore(&dmamux->lock, flags);
+
+ dma_spec->args[1] = dma_spec->args[2];
+ dma_spec->args_count = 2;
+
+ dev_dbg(&pdev->dev, "mapping dmamux %u.%u to dma request %u\n", mux,
+ dmamux->muxes[mux].value, mux);
+
+ return &dmamux->muxes[mux];
+}
+
+static int lpc18xx_dmamux_probe(struct platform_device *pdev)
+{
+ struct device_node *dma_np, *np = pdev->dev.of_node;
+ struct lpc18xx_dmamux_data *dmamux;
+ int ret;
+
+ dmamux = devm_kzalloc(&pdev->dev, sizeof(*dmamux), GFP_KERNEL);
+ if (!dmamux)
+ return -ENOMEM;
+
+ dmamux->reg = syscon_regmap_lookup_by_compatible("nxp,lpc1850-creg");
+ if (IS_ERR(dmamux->reg)) {
+ dev_err(&pdev->dev, "syscon lookup failed\n");
+ return PTR_ERR(dmamux->reg);
+ }
+
+ ret = of_property_read_u32(np, "dma-requests",
+ &dmamux->dma_mux_requests);
+ if (ret) {
+ dev_err(&pdev->dev, "missing dma-requests property\n");
+ return ret;
+ }
+
+ dma_np = of_parse_phandle(np, "dma-masters", 0);
+ if (!dma_np) {
+ dev_err(&pdev->dev, "can't get dma master\n");
+ return -ENODEV;
+ }
+
+ ret = of_property_read_u32(dma_np, "dma-requests",
+ &dmamux->dma_master_requests);
+ of_node_put(dma_np);
+ if (ret) {
+ dev_err(&pdev->dev, "missing master dma-requests property\n");
+ return ret;
+ }
+
+ dmamux->muxes = devm_kcalloc(&pdev->dev, dmamux->dma_master_requests,
+ sizeof(struct lpc18xx_dmamux),
+ GFP_KERNEL);
+ if (!dmamux->muxes)
+ return -ENOMEM;
+
+ spin_lock_init(&dmamux->lock);
+ platform_set_drvdata(pdev, dmamux);
+ dmamux->dmarouter.dev = &pdev->dev;
+ dmamux->dmarouter.route_free = lpc18xx_dmamux_free;
+
+ return of_dma_router_register(np, lpc18xx_dmamux_reserve,
+ &dmamux->dmarouter);
+}
+
+static const struct of_device_id lpc18xx_dmamux_match[] = {
+ { .compatible = "nxp,lpc1850-dmamux" },
+ {},
+};
+
+static struct platform_driver lpc18xx_dmamux_driver = {
+ .probe = lpc18xx_dmamux_probe,
+ .driver = {
+ .name = "lpc18xx-dmamux",
+ .of_match_table = lpc18xx_dmamux_match,
+ },
+};
+
+static int __init lpc18xx_dmamux_init(void)
+{
+ return platform_driver_register(&lpc18xx_dmamux_driver);
+}
+arch_initcall(lpc18xx_dmamux_init);
--
1.8.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/4] doc: dt: dma: add bindings for lpc1850-dmamux
2015-07-11 12:12 [PATCH 0/4] PL08x DT bindings and LPC18xx DMA support Joachim Eastwood
` (2 preceding siblings ...)
2015-07-11 12:12 ` [PATCH 3/4] dmaengine: add driver for lpc18xx dmamux Joachim Eastwood
@ 2015-07-11 12:12 ` Joachim Eastwood
2015-08-10 9:08 ` [PATCH 0/4] PL08x DT bindings and LPC18xx DMA support Linus Walleij
2015-08-18 16:42 ` Vinod Koul
5 siblings, 0 replies; 7+ messages in thread
From: Joachim Eastwood @ 2015-07-11 12:12 UTC (permalink / raw)
To: linux-arm-kernel
Add device tree bindings documentation for the
lpc1850-dmamux DMA router.
Signed-off-by: Joachim Eastwood <manabian@gmail.com>
---
.../devicetree/bindings/dma/lpc1850-dmamux.txt | 54 ++++++++++++++++++++++
1 file changed, 54 insertions(+)
create mode 100644 Documentation/devicetree/bindings/dma/lpc1850-dmamux.txt
diff --git a/Documentation/devicetree/bindings/dma/lpc1850-dmamux.txt b/Documentation/devicetree/bindings/dma/lpc1850-dmamux.txt
new file mode 100644
index 000000000000..87740adb2995
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/lpc1850-dmamux.txt
@@ -0,0 +1,54 @@
+NXP LPC18xx/43xx DMA MUX (DMA request router)
+
+Required properties:
+- compatible: "nxp,lpc1850-dmamux"
+- reg: Memory map for accessing module
+- #dma-cells: Should be set to <3>.
+ * 1st cell contain the master dma request signal
+ * 2nd cell contain the mux value (0-3) for the peripheral
+ * 3rd cell contain either 1 or 2 depending on the AHB
+ master used.
+- dma-requests: Number of DMA requests for the mux
+- dma-masters: phandle pointing to the DMA controller
+
+The DMA controller node need to have the following poroperties:
+- dma-requests: Number of DMA requests the controller can handle
+
+Example:
+
+dmac: dma at 40002000 {
+ compatible = "nxp,lpc1850-gpdma", "arm,pl080", "arm,primecell";
+ arm,primecell-periphid = <0x00041080>;
+ reg = <0x40002000 0x1000>;
+ interrupts = <2>;
+ clocks = <&ccu1 CLK_CPU_DMA>;
+ clock-names = "apb_pclk";
+ #dma-cells = <2>;
+ dma-channels = <8>;
+ dma-requests = <16>;
+ lli-bus-interface-ahb1;
+ lli-bus-interface-ahb2;
+ mem-bus-interface-ahb1;
+ mem-bus-interface-ahb2;
+ memcpy-burst-size = <256>;
+ memcpy-bus-width = <32>;
+};
+
+dmamux: dma-mux {
+ compatible = "nxp,lpc1850-dmamux";
+ #dma-cells = <3>;
+ dma-requests = <64>;
+ dma-masters = <&dmac>;
+};
+
+uart0: serial at 40081000 {
+ compatible = "nxp,lpc1850-uart", "ns16550a";
+ reg = <0x40081000 0x1000>;
+ reg-shift = <2>;
+ interrupts = <24>;
+ clocks = <&ccu2 CLK_APB0_UART0>, <&ccu1 CLK_CPU_UART0>;
+ clock-names = "uartclk", "reg";
+ dmas = <&dmamux 1 1 2
+ &dmamux 2 1 2>;
+ dma-names = "tx", "rx";
+};
--
1.8.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 0/4] PL08x DT bindings and LPC18xx DMA support
2015-07-11 12:12 [PATCH 0/4] PL08x DT bindings and LPC18xx DMA support Joachim Eastwood
` (3 preceding siblings ...)
2015-07-11 12:12 ` [PATCH 4/4] doc: dt: dma: add bindings for lpc1850-dmamux Joachim Eastwood
@ 2015-08-10 9:08 ` Linus Walleij
2015-08-18 16:42 ` Vinod Koul
5 siblings, 0 replies; 7+ messages in thread
From: Linus Walleij @ 2015-08-10 9:08 UTC (permalink / raw)
To: linux-arm-kernel
On Sat, Jul 11, 2015 at 2:12 PM, Joachim Eastwood <manabian@gmail.com> wrote:
> Hi Vinod,
>
> This is the non-RFC version of the patch set with only a few changes.
> Hope this can go in for 4.3. Changes to the DT for LPC18xx/43xx will
> go thru arm-soc once this get accepted.
What's happening with this patch set? I was planning to base some
Nomadik development on it, and can't see anything wrong with it.
Reviewed-by: Linus Walleij <linus.walleij@linaro.org> for the parts
I didn't write myself.
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 0/4] PL08x DT bindings and LPC18xx DMA support
2015-07-11 12:12 [PATCH 0/4] PL08x DT bindings and LPC18xx DMA support Joachim Eastwood
` (4 preceding siblings ...)
2015-08-10 9:08 ` [PATCH 0/4] PL08x DT bindings and LPC18xx DMA support Linus Walleij
@ 2015-08-18 16:42 ` Vinod Koul
5 siblings, 0 replies; 7+ messages in thread
From: Vinod Koul @ 2015-08-18 16:42 UTC (permalink / raw)
To: linux-arm-kernel
On Sat, Jul 11, 2015 at 02:12:03PM +0200, Joachim Eastwood wrote:
> Hi Vinod,
>
> This is the non-RFC version of the patch set with only a few changes.
> Hope this can go in for 4.3. Changes to the DT for LPC18xx/43xx will
> go thru arm-soc once this get accepted.
>
>
> This patch set aims to add support for DMA on the NXP LPC18xx/43xx
> (Cortex-M3/M4) platform. The platform has a PL080 controller with a
> mux in front of the DMA request lines. This setup is quite common
> and can be found on most other, if not all, NXP LPC devices.
>
> Patch set adds DT support for the PL08x dmaengine driver and a DMA
> router driver for the LPC18xx/43xx DMA multiplexer.
Applied, thanks
--
~Vinod
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2015-08-18 16:42 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-07-11 12:12 [PATCH 0/4] PL08x DT bindings and LPC18xx DMA support Joachim Eastwood
2015-07-11 12:12 ` [PATCH 1/4] dmaengine: pl08x: support dt channel assignment Joachim Eastwood
2015-07-11 12:12 ` [PATCH 2/4] doc: dt: dma: add binding doc for pl08x Joachim Eastwood
2015-07-11 12:12 ` [PATCH 3/4] dmaengine: add driver for lpc18xx dmamux Joachim Eastwood
2015-07-11 12:12 ` [PATCH 4/4] doc: dt: dma: add bindings for lpc1850-dmamux Joachim Eastwood
2015-08-10 9:08 ` [PATCH 0/4] PL08x DT bindings and LPC18xx DMA support Linus Walleij
2015-08-18 16:42 ` Vinod Koul
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).