[PATCH] mailbox: avoid timer start from callback
From: Jassi Brar If the txdone is done by polling, it is possible for msg_submit() to start the timer while txdone_hrtimer() callback is running. If the timer needs recheduling, it could already be enqueued by the time hrtimer_forward_now() is called, leading hrtimer to loudly complain. WARNING: CPU: 3 PID: 74 at kernel/time/hrtimer.c:932 hrtimer_forward+0xc4/0x110 CPU: 3 PID: 74 Comm: kworker/u8:1 Not tainted 5.9.0-rc2-00236-gd3520067d01c-dirty #5 Hardware name: Libre Computer AML-S805X-AC (DT) Workqueue: events_freezable_power_ thermal_zone_device_check pstate: 2085 (nzCv daIf -PAN -UAO BTYPE=--) pc : hrtimer_forward+0xc4/0x110 lr : txdone_hrtimer+0xf8/0x118 [...] This can be fixed by not starting the timer from the callback path. Which requires the timer reloading as long as any message is queued on the channel, and not just when current tx is not done yet. Signed-off-by: Jassi Brar --- drivers/mailbox/mailbox.c | 12 +++- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c index 0b821a5b2db8..a093a6ecaa66 100644 --- a/drivers/mailbox/mailbox.c +++ b/drivers/mailbox/mailbox.c @@ -82,9 +82,12 @@ static void msg_submit(struct mbox_chan *chan) exit: spin_unlock_irqrestore(>lock, flags); - if (!err && (chan->txdone_method & TXDONE_BY_POLL)) - /* kick start the timer immediately to avoid delays */ - hrtimer_start(>mbox->poll_hrt, 0, HRTIMER_MODE_REL); + /* kick start the timer immediately to avoid delays */ + if (!err && (chan->txdone_method & TXDONE_BY_POLL)) { + /* but only if not already active */ + if (!hrtimer_active(>mbox->poll_hrt)) + hrtimer_start(>mbox->poll_hrt, 0, HRTIMER_MODE_REL); + } } static void tx_tick(struct mbox_chan *chan, int r) @@ -122,11 +125,10 @@ static enum hrtimer_restart txdone_hrtimer(struct hrtimer *hrtimer) struct mbox_chan *chan = >chans[i]; if (chan->active_req && chan->cl) { + resched = true; txdone = chan->mbox->ops->last_tx_done(chan); if (txdone) tx_tick(chan, 0); - else - resched = true; } } -- 2.25.1
[PATCH] firmware: arm_scmi: fix timeout value for send_message
From: Jassi Brar Currently scmi_do_xfer() submits a message to mailbox api and waits for an apparently very short time. This works if there are not many messages in the queue already. However, if many clients share a channel and/or each client submits many messages in a row, the timeout value becomes too short and returns error even if the mailbox is working fine according to the load. The timeout occurs when the message is still in the api/queue awaiting its turn to ride the bus. Fix this by increasing the timeout value enough (500ms?) so that it fails only if there is an actual problem in the transmission (like a lockup or crash). [If we want to capture a situation when the remote didn't respond within expected latency, then the timeout should not start here, but from tx_prepare callback ... just before the message physically gets on the channel] Signed-off-by: Jassi Brar --- drivers/firmware/arm_scmi/driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index dbec767222e9..46ddafe7ffc0 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -303,7 +303,7 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer) } if (xfer->hdr.poll_completion) { - ktime_t stop = ktime_add_ns(ktime_get(), SCMI_MAX_POLL_TO_NS); + ktime_t stop = ktime_add_ns(ktime_get(), 500 * 1000 * NSEC_PER_USEC); spin_until_cond(scmi_xfer_done_no_timeout(cinfo, xfer, stop)); @@ -313,7 +313,7 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer) ret = -ETIMEDOUT; } else { /* And we wait for the response. */ - timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms); + timeout = msecs_to_jiffies(500); if (!wait_for_completion_timeout(>done, timeout)) { dev_err(dev, "timed out in resp(caller: %pS)\n", (void *)_RET_IP_); -- 2.25.1
[PATCH v4 2/2] dmaengine: milbeaut-hdmac: Add HDMAC driver for Milbeaut platforms
From: Jassi Brar Driver for Socionext Milbeaut HDMAC controller. The controller has upto 8 floating channels, that need a predefined slave-id to work from a set of slaves. Signed-off-by: Jassi Brar --- drivers/dma/Kconfig | 10 + drivers/dma/Makefile | 1 + drivers/dma/milbeaut-hdmac.c | 581 +++ 3 files changed, 592 insertions(+) create mode 100644 drivers/dma/milbeaut-hdmac.c diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 7af874b69ffb..d312ebbafbee 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -342,6 +342,16 @@ config MCF_EDMA minimal intervention from a host processor. This module can be found on Freescale ColdFire mcf5441x SoCs. +config MILBEAUT_HDMAC + tristate "Milbeaut AHB DMA support" + depends on ARCH_MILBEAUT || COMPILE_TEST + depends on OF + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + help + Say yes here to support the Socionext Milbeaut + HDMAC device. + 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 f5ce8665e944..5f0df3611414 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o obj-$(CONFIG_INTEL_MIC_X100_DMA) += mic_x100_dma.o obj-$(CONFIG_K3_DMA) += k3dma.o obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o +obj-$(CONFIG_MILBEAUT_HDMAC) += milbeaut-hdmac.o obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o obj-$(CONFIG_MOXART_DMA) += moxart-dma.o diff --git a/drivers/dma/milbeaut-hdmac.c b/drivers/dma/milbeaut-hdmac.c new file mode 100644 index ..2bb33535ab9e --- /dev/null +++ b/drivers/dma/milbeaut-hdmac.c @@ -0,0 +1,581 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2019 Linaro Ltd. +// Copyright (C) 2019 Socionext Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "virt-dma.h" + +#define MLB_HDMAC_DMACR0x0 /* global */ +#define MLB_HDMAC_DE BIT(31) +#define MLB_HDMAC_DS BIT(30) +#define MLB_HDMAC_PR BIT(28) +#define MLB_HDMAC_DH GENMASK(27, 24) + +#define MLB_HDMAC_CH_STRIDE0x10 + +#define MLB_HDMAC_DMACA0x0 /* channel */ +#define MLB_HDMAC_EB BIT(31) +#define MLB_HDMAC_PB BIT(30) +#define MLB_HDMAC_ST BIT(29) +#define MLB_HDMAC_IS GENMASK(28, 24) +#define MLB_HDMAC_BT GENMASK(23, 20) +#define MLB_HDMAC_BC GENMASK(19, 16) +#define MLB_HDMAC_TC GENMASK(15, 0) +#define MLB_HDMAC_DMACB0x4 +#define MLB_HDMAC_TT GENMASK(31, 30) +#define MLB_HDMAC_MS GENMASK(29, 28) +#define MLB_HDMAC_TW GENMASK(27, 26) +#define MLB_HDMAC_FS BIT(25) +#define MLB_HDMAC_FD BIT(24) +#define MLB_HDMAC_RC BIT(23) +#define MLB_HDMAC_RS BIT(22) +#define MLB_HDMAC_RD BIT(21) +#define MLB_HDMAC_EI BIT(20) +#define MLB_HDMAC_CI BIT(19) +#define HDMAC_PAUSE0x7 +#define MLB_HDMAC_SS GENMASK(18, 16) +#define MLB_HDMAC_SP GENMASK(15, 12) +#define MLB_HDMAC_DP GENMASK(11, 8) +#define MLB_HDMAC_DMACSA 0x8 +#define MLB_HDMAC_DMACDA 0xc + +#define MLB_HDMAC_BUSWIDTHS(BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \ + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \ + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES)) + +struct milbeaut_hdmac_desc { + struct virt_dma_desc vd; + struct scatterlist *sgl; + unsigned int sg_len; + unsigned int sg_cur; + enum dma_transfer_direction dir; +}; + +struct milbeaut_hdmac_chan { + struct virt_dma_chan vc; + struct milbeaut_hdmac_device *mdev; + struct milbeaut_hdmac_desc *md; + void __iomem *reg_ch_base; + unsigned int slave_id; + struct dma_slave_config cfg; +}; + +struct milbeaut_hdmac_device { + struct dma_device ddev; + struct clk *clk; + void __iomem *reg_base; + struct milbeaut_hdmac_chan channels[0]; +}; + +static struct milbeaut_hdmac_chan * +to_milbeaut_hdmac_chan(struct virt_dma_chan *vc) +{ + return container_of(vc, struct milbeaut_hdmac_chan, vc); +} + +static struct milbeaut_hdmac_desc * +to_milbeaut_hdmac_desc(struct virt_dma_desc *vd) +{ + return container_of(vd, struct milbeaut_hdmac_desc, vd); +} + +/* mc->vc.lock must be held by caller */ +static struct milbeaut_hdmac_desc * +milbeaut_hdmac_next_desc(struct milbeaut_hdmac_chan *mc) +{ + struct virt_dma_desc *vd; + + vd = vchan_next_desc(>vc); + if (!vd) { + mc->md = NULL; + return NULL; + } + +
[PATCH v4 1/2] dt-bindings: milbeaut-m10v-hdmac: Add Socionext Milbeaut HDMAC bindings
From: Jassi Brar Document the devicetree bindings for Socionext Milbeaut HDMAC controller. Controller has upto 8 floating channels, that need a predefined slave-id to work from a set of slaves. Reviewed-by: Rob Herring Signed-off-by: Jassi Brar --- .../bindings/dma/milbeaut-m10v-hdmac.txt | 32 +++ 1 file changed, 32 insertions(+) create mode 100644 Documentation/devicetree/bindings/dma/milbeaut-m10v-hdmac.txt diff --git a/Documentation/devicetree/bindings/dma/milbeaut-m10v-hdmac.txt b/Documentation/devicetree/bindings/dma/milbeaut-m10v-hdmac.txt new file mode 100644 index ..1f0875bd5abc --- /dev/null +++ b/Documentation/devicetree/bindings/dma/milbeaut-m10v-hdmac.txt @@ -0,0 +1,32 @@ +* Milbeaut AHB DMA Controller + +Milbeaut AHB DMA controller has transfer capability below. + - device to memory transfer + - memory to device transfer + +Required property: +- compatible: Should be "socionext,milbeaut-m10v-hdmac" +- reg: Should contain DMA registers location and length. +- interrupts: Should contain all of the per-channel DMA interrupts. + Number of channels is configurable - 2, 4 or 8, so + the number of interrupts specified should be {2,4,8}. +- #dma-cells: Should be 1. Specify the ID of the slave. +- clocks: Phandle to the clock used by the HDMAC module. + + +Example: + + hdmac1: dma-controller@1e11 { + compatible = "socionext,milbeaut-m10v-hdmac"; + reg = <0x1e11 0x1>; + interrupts = <0 132 4>, +<0 133 4>, +<0 134 4>, +<0 135 4>, +<0 136 4>, +<0 137 4>, +<0 138 4>, +<0 139 4>; + #dma-cells = <1>; + clocks = <_clk>; + }; -- 2.20.1
[PATCH v4 0/2] Add support for AHB DMA controller on Milbeaut series
From: Jassi Brar The following series adds AHB DMA (HDMAC) controller support on Milbeaut series. This controller is capable of Mem<->MEM and DEV<->MEM transfer. But only DEV<->MEM is currently supported. Changes since v3: # Drop unused variables # Add controller init instruction Changes since v2: # Spelling mistake fix # Bug fix prep_slave - made local copy of sgl Jassi Brar (2): dt-bindings: milbeaut-m10v-hdmac: Add Socionext Milbeaut HDMAC bindings dmaengine: milbeaut-hdmac: Add HDMAC driver for Milbeaut platforms .../bindings/dma/milbeaut-m10v-hdmac.txt | 32 + drivers/dma/Kconfig | 10 + drivers/dma/Makefile | 1 + drivers/dma/milbeaut-hdmac.c | 581 ++ 4 files changed, 624 insertions(+) create mode 100644 Documentation/devicetree/bindings/dma/milbeaut-m10v-hdmac.txt create mode 100644 drivers/dma/milbeaut-hdmac.c -- 2.20.1
[PATCH v3 2/2] dmaengine: milbeaut-xdmac: Add XDMAC driver for Milbeaut platforms
From: Jassi Brar Driver for Socionext Milbeaut XDMAC controller. The controller only supports Mem-To-Mem transfers over upto 8 configurable channels. Signed-off-by: Jassi Brar --- drivers/dma/Kconfig | 10 + drivers/dma/Makefile | 1 + drivers/dma/milbeaut-xdmac.c | 418 +++ 3 files changed, 429 insertions(+) create mode 100644 drivers/dma/milbeaut-xdmac.c diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index d312ebbafbee..a34cd5a72a7b 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -352,6 +352,16 @@ config MILBEAUT_HDMAC Say yes here to support the Socionext Milbeaut HDMAC device. +config MILBEAUT_XDMAC + tristate "Milbeaut AXI DMA support" + depends on ARCH_MILBEAUT || COMPILE_TEST + depends on OF + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + help + Say yes here to support the Socionext Milbeaut + XDMAC device. + 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 5f0df3611414..e3a8fdf80c76 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_INTEL_MIC_X100_DMA) += mic_x100_dma.o obj-$(CONFIG_K3_DMA) += k3dma.o obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o obj-$(CONFIG_MILBEAUT_HDMAC) += milbeaut-hdmac.o +obj-$(CONFIG_MILBEAUT_XDMAC) += milbeaut-xdmac.o obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o obj-$(CONFIG_MOXART_DMA) += moxart-dma.o diff --git a/drivers/dma/milbeaut-xdmac.c b/drivers/dma/milbeaut-xdmac.c new file mode 100644 index ..3d5b1926a58d --- /dev/null +++ b/drivers/dma/milbeaut-xdmac.c @@ -0,0 +1,418 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2019 Linaro Ltd. +// Copyright (C) 2019 Socionext Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "virt-dma.h" + +/* global register */ +#define M10V_XDACS 0x00 + +/* channel local register */ +#define M10V_XDTBC 0x10 +#define M10V_XDSSA 0x14 +#define M10V_XDDSA 0x18 +#define M10V_XDSAC 0x1C +#define M10V_XDDAC 0x20 +#define M10V_XDDCC 0x24 +#define M10V_XDDES 0x28 +#define M10V_XDDPC 0x2C +#define M10V_XDDSD 0x30 + +#define M10V_XDACS_XE BIT(28) + +#define M10V_DEFBS 0x3 +#define M10V_DEFBL 0xf + +#define M10V_XDSAC_SBS GENMASK(17, 16) +#define M10V_XDSAC_SBL GENMASK(11, 8) + +#define M10V_XDDAC_DBS GENMASK(17, 16) +#define M10V_XDDAC_DBL GENMASK(11, 8) + +#define M10V_XDDES_CE BIT(28) +#define M10V_XDDES_SE BIT(24) +#define M10V_XDDES_SA BIT(15) +#define M10V_XDDES_TF GENMASK(23, 20) +#define M10V_XDDES_EI BIT(1) +#define M10V_XDDES_TI BIT(0) + +#define M10V_XDDSD_IS_MASK GENMASK(3, 0) +#define M10V_XDDSD_IS_NORMAL 0x8 + +#define MLB_XDMAC_BUSWIDTHS(BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \ +BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \ +BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | \ +BIT(DMA_SLAVE_BUSWIDTH_8_BYTES)) + +struct milbeaut_xdmac_desc { + struct virt_dma_desc vd; + size_t len; + dma_addr_t src; + dma_addr_t dst; +}; + +struct milbeaut_xdmac_chan { + struct virt_dma_chan vc; + struct milbeaut_xdmac_desc *md; + void __iomem *reg_ch_base; +}; + +struct milbeaut_xdmac_device { + struct dma_device ddev; + void __iomem *reg_base; + struct milbeaut_xdmac_chan channels[0]; +}; + +static struct milbeaut_xdmac_chan * +to_milbeaut_xdmac_chan(struct virt_dma_chan *vc) +{ + return container_of(vc, struct milbeaut_xdmac_chan, vc); +} + +static struct milbeaut_xdmac_desc * +to_milbeaut_xdmac_desc(struct virt_dma_desc *vd) +{ + return container_of(vd, struct milbeaut_xdmac_desc, vd); +} + +/* mc->vc.lock must be held by caller */ +static struct milbeaut_xdmac_desc * +milbeaut_xdmac_next_desc(struct milbeaut_xdmac_chan *mc) +{ + struct virt_dma_desc *vd; + + vd = vchan_next_desc(>vc); + if (!vd) { + mc->md = NULL; + return NULL; + } + + list_del(>node); + + mc->md = to_milbeaut_xdmac_desc(vd); + + return mc->md; +} + +/* mc->vc.lock must be held by caller */ +static void milbeaut_chan_start(struct milbeaut_xdmac_chan *mc, + struct milbeaut_xdmac_desc *md) +{ + u32 val; + + /* Setup the channel */ + val = md->len - 1; + writel_relaxed(val, mc->reg_ch_base + M10V_XDTBC); + + val = md->src; + writel_relaxed(val, mc->reg_ch_base + M10V_XDSSA); + + val = md->dst; + writel_relaxed(val, mc->reg_ch_base + M10V_XDDSA); + + val = readl_relaxed(mc->reg_ch_base + M10V_XDSAC); + val &= ~(M10V_XDSAC_SBS | M10V_XDSAC_SBL); + val |= FIELD_PREP(M10V_XDSAC_SBS,
[PATCH v3 1/2] dt-bindings: milbeaut-m10v-xdmac: Add Socionext Milbeaut XDMAC bindings
From: Jassi Brar Document the devicetree bindings for Socionext Milbeaut XDMAC controller. Controller only supports Mem->Mem transfers. Number of physical channels are determined by the number of irqs registered. Reviewed-by: Rob Herring Signed-off-by: Jassi Brar --- .../bindings/dma/milbeaut-m10v-xdmac.txt | 24 +++ 1 file changed, 24 insertions(+) create mode 100644 Documentation/devicetree/bindings/dma/milbeaut-m10v-xdmac.txt diff --git a/Documentation/devicetree/bindings/dma/milbeaut-m10v-xdmac.txt b/Documentation/devicetree/bindings/dma/milbeaut-m10v-xdmac.txt new file mode 100644 index ..305791804062 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/milbeaut-m10v-xdmac.txt @@ -0,0 +1,24 @@ +* Milbeaut AXI DMA Controller + +Milbeaut AXI DMA controller has only memory to memory transfer capability. + +* DMA controller + +Required property: +- compatible: Should be "socionext,milbeaut-m10v-xdmac" +- reg: Should contain DMA registers location and length. +- interrupts: Should contain all of the per-channel DMA interrupts. +Number of channels is configurable - 2, 4 or 8, so +the number of interrupts specified should be {2,4,8}. +- #dma-cells: Should be 1. + +Example: + xdmac0: dma-controller@1c25 { + compatible = "socionext,milbeaut-m10v-xdmac"; + reg = <0x1c25 0x1000>; + interrupts = <0 17 0x4>, +<0 18 0x4>, +<0 19 0x4>, +<0 20 0x4>; + #dma-cells = <1>; + }; -- 2.20.1
[PATCH v3 0/2] Add support for AXI DMA controller on Milbeaut series
From: Jassi Brar The following series adds AXI DMA (XDMAC) controller support on Milbeaut series. This controller is capable of only Mem<->MEM transfers. Number of channels is configurable {2,4,8} Changes Since v2: # Drop unused variable Changes Since v1: # Spelling mistake fix Jassi Brar (2): dt-bindings: milbeaut-m10v-xdmac: Add Socionext Milbeaut XDMAC bindings dmaengine: milbeaut-xdmac: Add XDMAC driver for Milbeaut platforms .../bindings/dma/milbeaut-m10v-xdmac.txt | 24 + drivers/dma/Kconfig | 10 + drivers/dma/Makefile | 1 + drivers/dma/milbeaut-xdmac.c | 418 ++ 4 files changed, 453 insertions(+) create mode 100644 Documentation/devicetree/bindings/dma/milbeaut-m10v-xdmac.txt create mode 100644 drivers/dma/milbeaut-xdmac.c -- 2.20.1
[PATCH v3 1/2] dt-bindings: milbeaut-m10v-hdmac: Add Socionext Milbeaut HDMAC bindings
From: Jassi Brar Document the devicetree bindings for Socionext Milbeaut HDMAC controller. Controller has upto 8 floating channels, that need a predefined slave-id to work from a set of slaves. Reviewed-by: Rob Herring Signed-off-by: Jassi Brar --- .../bindings/dma/milbeaut-m10v-hdmac.txt | 32 +++ 1 file changed, 32 insertions(+) create mode 100644 Documentation/devicetree/bindings/dma/milbeaut-m10v-hdmac.txt diff --git a/Documentation/devicetree/bindings/dma/milbeaut-m10v-hdmac.txt b/Documentation/devicetree/bindings/dma/milbeaut-m10v-hdmac.txt new file mode 100644 index ..1f0875bd5abc --- /dev/null +++ b/Documentation/devicetree/bindings/dma/milbeaut-m10v-hdmac.txt @@ -0,0 +1,32 @@ +* Milbeaut AHB DMA Controller + +Milbeaut AHB DMA controller has transfer capability below. + - device to memory transfer + - memory to device transfer + +Required property: +- compatible: Should be "socionext,milbeaut-m10v-hdmac" +- reg: Should contain DMA registers location and length. +- interrupts: Should contain all of the per-channel DMA interrupts. + Number of channels is configurable - 2, 4 or 8, so + the number of interrupts specified should be {2,4,8}. +- #dma-cells: Should be 1. Specify the ID of the slave. +- clocks: Phandle to the clock used by the HDMAC module. + + +Example: + + hdmac1: dma-controller@1e11 { + compatible = "socionext,milbeaut-m10v-hdmac"; + reg = <0x1e11 0x1>; + interrupts = <0 132 4>, +<0 133 4>, +<0 134 4>, +<0 135 4>, +<0 136 4>, +<0 137 4>, +<0 138 4>, +<0 139 4>; + #dma-cells = <1>; + clocks = <_clk>; + }; -- 2.17.1
[PATCH v3 2/2] dmaengine: milbeaut-hdmac: Add HDMAC driver for Milbeaut platforms
From: Jassi Brar Driver for Socionext Milbeaut HDMAC controller. The controller has upto 8 floating channels, that need a predefined slave-id to work from a set of slaves. Signed-off-by: Jassi Brar --- drivers/dma/Kconfig | 10 + drivers/dma/Makefile | 1 + drivers/dma/milbeaut-hdmac.c | 583 +++ 3 files changed, 594 insertions(+) create mode 100644 drivers/dma/milbeaut-hdmac.c diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 03fa0c58cef3..66979f27f0f3 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -348,6 +348,16 @@ config MCF_EDMA minimal intervention from a host processor. This module can be found on Freescale ColdFire mcf5441x SoCs. +config MILBEAUT_HDMAC + tristate "Milbeaut AHB DMA support" + depends on ARCH_MILBEAUT || COMPILE_TEST + depends on OF + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + help + Say yes here to support the Socionext Milbeaut + HDMAC device. + 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 5bddf6f8790f..e4aed0730dea 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o obj-$(CONFIG_INTEL_MIC_X100_DMA) += mic_x100_dma.o obj-$(CONFIG_K3_DMA) += k3dma.o obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o +obj-$(CONFIG_MILBEAUT_HDMAC) += milbeaut-hdmac.o obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o obj-$(CONFIG_MOXART_DMA) += moxart-dma.o diff --git a/drivers/dma/milbeaut-hdmac.c b/drivers/dma/milbeaut-hdmac.c new file mode 100644 index ..600ffd0cfa26 --- /dev/null +++ b/drivers/dma/milbeaut-hdmac.c @@ -0,0 +1,583 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2019 Linaro Ltd. +// Copyright (C) 2019 Socionext Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "virt-dma.h" + +#define MLB_HDMAC_DMACR0x0 /* global */ +#define MLB_HDMAC_DE BIT(31) +#define MLB_HDMAC_DS BIT(30) +#define MLB_HDMAC_PR BIT(28) +#define MLB_HDMAC_DH GENMASK(27, 24) + +#define MLB_HDMAC_CH_STRIDE0x10 + +#define MLB_HDMAC_DMACA0x0 /* channel */ +#define MLB_HDMAC_EB BIT(31) +#define MLB_HDMAC_PB BIT(30) +#define MLB_HDMAC_ST BIT(29) +#define MLB_HDMAC_IS GENMASK(28, 24) +#define MLB_HDMAC_BT GENMASK(23, 20) +#define MLB_HDMAC_BC GENMASK(19, 16) +#define MLB_HDMAC_TC GENMASK(15, 0) +#define MLB_HDMAC_DMACB0x4 +#define MLB_HDMAC_TT GENMASK(31, 30) +#define MLB_HDMAC_MS GENMASK(29, 28) +#define MLB_HDMAC_TW GENMASK(27, 26) +#define MLB_HDMAC_FS BIT(25) +#define MLB_HDMAC_FD BIT(24) +#define MLB_HDMAC_RC BIT(23) +#define MLB_HDMAC_RS BIT(22) +#define MLB_HDMAC_RD BIT(21) +#define MLB_HDMAC_EI BIT(20) +#define MLB_HDMAC_CI BIT(19) +#define HDMAC_PAUSE0x7 +#define MLB_HDMAC_SS GENMASK(18, 16) +#define MLB_HDMAC_SP GENMASK(15, 12) +#define MLB_HDMAC_DP GENMASK(11, 8) +#define MLB_HDMAC_DMACSA 0x8 +#define MLB_HDMAC_DMACDA 0xc + +#define MLB_HDMAC_BUSWIDTHS(BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \ + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \ + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES)) + +struct milbeaut_hdmac_desc { + struct virt_dma_desc vd; + struct scatterlist *sgl; + unsigned int sg_len; + unsigned int sg_cur; + enum dma_transfer_direction dir; +}; + +struct milbeaut_hdmac_chan { + struct virt_dma_chan vc; + struct milbeaut_hdmac_device *mdev; + struct milbeaut_hdmac_desc *md; + void __iomem *reg_ch_base; + unsigned int slave_id; + struct dma_slave_config cfg; +}; + +struct milbeaut_hdmac_device { + struct dma_device ddev; + struct clk *clk; + void __iomem *reg_base; + struct milbeaut_hdmac_chan channels[0]; +}; + +static struct milbeaut_hdmac_chan * +to_milbeaut_hdmac_chan(struct virt_dma_chan *vc) +{ + return container_of(vc, struct milbeaut_hdmac_chan, vc); +} + +static struct milbeaut_hdmac_desc * +to_milbeaut_hdmac_desc(struct virt_dma_desc *vd) +{ + return container_of(vd, struct milbeaut_hdmac_desc, vd); +} + +/* mc->vc.lock must be held by caller */ +static struct milbeaut_hdmac_desc * +milbeaut_hdmac_next_desc(struct milbeaut_hdmac_chan *mc) +{ + struct virt_dma_desc *vd; + + vd = vchan_next_desc(>vc); + if (!vd) { + mc->md = NULL; + return NULL; + } + +
[PATCH v2 2/2] dmaengine: milbeaut-xdmac: Add XDMAC driver for Milbeaut platforms
From: Jassi Brar Driver for Socionext Milbeaut XDMAC controller. The controller only supports Mem-To-Mem transfers over upto 8 configurable channels. Signed-off-by: Jassi Brar --- drivers/dma/Kconfig | 10 + drivers/dma/Makefile | 1 + drivers/dma/milbeaut-xdmac.c | 426 +++ 3 files changed, 437 insertions(+) create mode 100644 drivers/dma/milbeaut-xdmac.c diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 66979f27f0f3..e0e3b21a0c4c 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -358,6 +358,16 @@ config MILBEAUT_HDMAC Say yes here to support the Socionext Milbeaut HDMAC device. +config MILBEAUT_XDMAC + tristate "Milbeaut AXI DMA support" + depends on ARCH_MILBEAUT || COMPILE_TEST + depends on OF + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + help + Say yes here to support the Socionext Milbeaut + XDMAC device. + 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 e4aed0730dea..41e06a845b01 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_INTEL_MIC_X100_DMA) += mic_x100_dma.o obj-$(CONFIG_K3_DMA) += k3dma.o obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o obj-$(CONFIG_MILBEAUT_HDMAC) += milbeaut-hdmac.o +obj-$(CONFIG_MILBEAUT_XDMAC) += milbeaut-xdmac.o obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o obj-$(CONFIG_MOXART_DMA) += moxart-dma.o diff --git a/drivers/dma/milbeaut-xdmac.c b/drivers/dma/milbeaut-xdmac.c new file mode 100644 index ..f2e04541d031 --- /dev/null +++ b/drivers/dma/milbeaut-xdmac.c @@ -0,0 +1,426 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2019 Linaro Ltd. +// Copyright (C) 2019 Socionext Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "virt-dma.h" + +/* global register */ +#define M10V_XDACS 0x00 + +/* channel local register */ +#define M10V_XDTBC 0x10 +#define M10V_XDSSA 0x14 +#define M10V_XDDSA 0x18 +#define M10V_XDSAC 0x1C +#define M10V_XDDAC 0x20 +#define M10V_XDDCC 0x24 +#define M10V_XDDES 0x28 +#define M10V_XDDPC 0x2C +#define M10V_XDDSD 0x30 + +#define M10V_XDACS_XE BIT(28) + +#define M10V_DEFBS 0x3 +#define M10V_DEFBL 0xf + +#define M10V_XDSAC_SBS GENMASK(17, 16) +#define M10V_XDSAC_SBL GENMASK(11, 8) + +#define M10V_XDDAC_DBS GENMASK(17, 16) +#define M10V_XDDAC_DBL GENMASK(11, 8) + +#define M10V_XDDES_CE BIT(28) +#define M10V_XDDES_SE BIT(24) +#define M10V_XDDES_SA BIT(15) +#define M10V_XDDES_TF GENMASK(23, 20) +#define M10V_XDDES_EI BIT(1) +#define M10V_XDDES_TI BIT(0) + +#define M10V_XDDSD_IS_MASK GENMASK(3, 0) +#define M10V_XDDSD_IS_NORMAL 0x8 + +#define MLB_XDMAC_BUSWIDTHS(BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \ +BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \ +BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | \ +BIT(DMA_SLAVE_BUSWIDTH_8_BYTES)) + +struct milbeaut_xdmac_desc { + struct virt_dma_desc vd; + size_t len; + dma_addr_t src; + dma_addr_t dst; +}; + +struct milbeaut_xdmac_chan { + struct virt_dma_chan vc; + struct milbeaut_xdmac_device *mdev; + struct milbeaut_xdmac_desc *md; + void __iomem *reg_ch_base; + int irq; + struct dma_slave_config cfg; +}; + +struct milbeaut_xdmac_device { + struct dma_device ddev; + void __iomem *reg_base; + struct milbeaut_xdmac_chan channels[0]; +}; + +static struct milbeaut_xdmac_chan * +to_milbeaut_xdmac_chan(struct virt_dma_chan *vc) +{ + return container_of(vc, struct milbeaut_xdmac_chan, vc); +} + +static struct milbeaut_xdmac_desc * +to_milbeaut_xdmac_desc(struct virt_dma_desc *vd) +{ + return container_of(vd, struct milbeaut_xdmac_desc, vd); +} + +/* mc->vc.lock must be held by caller */ +static struct milbeaut_xdmac_desc * +milbeaut_xdmac_next_desc(struct milbeaut_xdmac_chan *mc) +{ + struct virt_dma_desc *vd; + + vd = vchan_next_desc(>vc); + if (!vd) { + mc->md = NULL; + return NULL; + } + + list_del(>node); + + mc->md = to_milbeaut_xdmac_desc(vd); + + return mc->md; +} + +/* mc->vc.lock must be held by caller */ +static void milbeaut_chan_start(struct milbeaut_xdmac_chan *mc, + struct milbeaut_xdmac_desc *md) +{ + u32 val; + + /* Setup the channel */ + val = md->len - 1; + writel_relaxed(val, mc->reg_ch_base + M10V_XDTBC); + + val = md->src; + writel_relaxed(val, mc->reg_ch_base + M10V_XDSSA); + + val = md->dst; + writel_relaxed(val, mc->reg_ch_base + M10V_XDDSA); + + val = readl_relaxed(mc->reg_ch_base + M10V_XDSAC); +
[PATCH v3 0/2] Add support for AHB DMA controller on Milbeaut series
From: Jassi Brar The following series adds AHB DMA (HDMAC) controller support on Milbeaut series. This controller is capable of Mem<->MEM and DEV<->MEM transfer. But only DEV<->MEM is currently supported. Changes since v2: # Spelling mistake fix # Bug fix prep_slave - made local copy of sgl Jassi Brar (2): dt-bindings: milbeaut-m10v-hdmac: Add Socionext Milbeaut HDMAC bindings dmaengine: milbeaut-hdmac: Add HDMAC driver for Milbeaut platforms .../bindings/dma/milbeaut-m10v-hdmac.txt | 32 + drivers/dma/Kconfig | 10 + drivers/dma/Makefile | 1 + drivers/dma/milbeaut-hdmac.c | 583 ++ 4 files changed, 626 insertions(+) create mode 100644 Documentation/devicetree/bindings/dma/milbeaut-m10v-hdmac.txt create mode 100644 drivers/dma/milbeaut-hdmac.c -- 2.17.1
[PATCH v2 1/2] dt-bindings: milbeaut-m10v-xdmac: Add Socionext Milbeaut XDMAC bindings
From: Jassi Brar Document the devicetree bindings for Socionext Milbeaut XDMAC controller. Controller only supports Mem->Mem transfers. Number of physical channels are determined by the number of irqs registered. Reviewed-by: Rob Herring Signed-off-by: Jassi Brar --- .../bindings/dma/milbeaut-m10v-xdmac.txt | 24 +++ 1 file changed, 24 insertions(+) create mode 100644 Documentation/devicetree/bindings/dma/milbeaut-m10v-xdmac.txt diff --git a/Documentation/devicetree/bindings/dma/milbeaut-m10v-xdmac.txt b/Documentation/devicetree/bindings/dma/milbeaut-m10v-xdmac.txt new file mode 100644 index ..305791804062 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/milbeaut-m10v-xdmac.txt @@ -0,0 +1,24 @@ +* Milbeaut AXI DMA Controller + +Milbeaut AXI DMA controller has only memory to memory transfer capability. + +* DMA controller + +Required property: +- compatible: Should be "socionext,milbeaut-m10v-xdmac" +- reg: Should contain DMA registers location and length. +- interrupts: Should contain all of the per-channel DMA interrupts. +Number of channels is configurable - 2, 4 or 8, so +the number of interrupts specified should be {2,4,8}. +- #dma-cells: Should be 1. + +Example: + xdmac0: dma-controller@1c25 { + compatible = "socionext,milbeaut-m10v-xdmac"; + reg = <0x1c25 0x1000>; + interrupts = <0 17 0x4>, +<0 18 0x4>, +<0 19 0x4>, +<0 20 0x4>; + #dma-cells = <1>; + }; -- 2.17.1
[PATCH v2 0/2] Add support for AXI DMA controller on Milbeaut series
From: Jassi Brar The following series adds AXI DMA (XDMAC) controller support on Milbeaut series. This controller is capable of only Mem<->MEM transfers. Number of channels is configurable {2,4,8} Changes Since v1: # Spelling mistake fix Jassi Brar (2): dt-bindings: milbeaut-m10v-xdmac: Add Socionext Milbeaut XDMAC bindings dmaengine: milbeaut-xdmac: Add XDMAC driver for Milbeaut platforms .../bindings/dma/milbeaut-m10v-xdmac.txt | 24 + drivers/dma/Kconfig | 10 + drivers/dma/Makefile | 1 + drivers/dma/milbeaut-xdmac.c | 426 ++ 4 files changed, 461 insertions(+) create mode 100644 Documentation/devicetree/bindings/dma/milbeaut-m10v-xdmac.txt create mode 100644 drivers/dma/milbeaut-xdmac.c -- 2.17.1
[PATCH 2/2] dmaengine: milbeaut-xdmac: Add XDMAC driver for Milbeaut platforms
From: Jassi Brar Driver for Socionext Milbeaut XDMAC controller. The controller only supports Mem-To-Mem transfers over upto 8 configurable channels. Signed-off-by: Jassi Brar --- drivers/dma/Kconfig | 10 + drivers/dma/Makefile | 1 + drivers/dma/milbeaut-xdmac.c | 426 +++ 3 files changed, 437 insertions(+) create mode 100644 drivers/dma/milbeaut-xdmac.c diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 66979f27f0f3..e0e3b21a0c4c 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -358,6 +358,16 @@ config MILBEAUT_HDMAC Say yes here to support the Socionext Milbeaut HDMAC device. +config MILBEAUT_XDMAC + tristate "Milbeaut AXI DMA support" + depends on ARCH_MILBEAUT || COMPILE_TEST + depends on OF + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + help + Say yes here to support the Socionext Milbeaut + XDMAC device. + 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 e4aed0730dea..41e06a845b01 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_INTEL_MIC_X100_DMA) += mic_x100_dma.o obj-$(CONFIG_K3_DMA) += k3dma.o obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o obj-$(CONFIG_MILBEAUT_HDMAC) += milbeaut-hdmac.o +obj-$(CONFIG_MILBEAUT_XDMAC) += milbeaut-xdmac.o obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o obj-$(CONFIG_MOXART_DMA) += moxart-dma.o diff --git a/drivers/dma/milbeaut-xdmac.c b/drivers/dma/milbeaut-xdmac.c new file mode 100644 index ..f2e04541d031 --- /dev/null +++ b/drivers/dma/milbeaut-xdmac.c @@ -0,0 +1,426 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2019 Linaro Ltd. +// Copyright (C) 2019 Socionext Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "virt-dma.h" + +/* global register */ +#define M10V_XDACS 0x00 + +/* channel local register */ +#define M10V_XDTBC 0x10 +#define M10V_XDSSA 0x14 +#define M10V_XDDSA 0x18 +#define M10V_XDSAC 0x1C +#define M10V_XDDAC 0x20 +#define M10V_XDDCC 0x24 +#define M10V_XDDES 0x28 +#define M10V_XDDPC 0x2C +#define M10V_XDDSD 0x30 + +#define M10V_XDACS_XE BIT(28) + +#define M10V_DEFBS 0x3 +#define M10V_DEFBL 0xf + +#define M10V_XDSAC_SBS GENMASK(17, 16) +#define M10V_XDSAC_SBL GENMASK(11, 8) + +#define M10V_XDDAC_DBS GENMASK(17, 16) +#define M10V_XDDAC_DBL GENMASK(11, 8) + +#define M10V_XDDES_CE BIT(28) +#define M10V_XDDES_SE BIT(24) +#define M10V_XDDES_SA BIT(15) +#define M10V_XDDES_TF GENMASK(23, 20) +#define M10V_XDDES_EI BIT(1) +#define M10V_XDDES_TI BIT(0) + +#define M10V_XDDSD_IS_MASK GENMASK(3, 0) +#define M10V_XDDSD_IS_NORMAL 0x8 + +#define MLB_XDMAC_BUSWIDTHS(BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \ +BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \ +BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | \ +BIT(DMA_SLAVE_BUSWIDTH_8_BYTES)) + +struct milbeaut_xdmac_desc { + struct virt_dma_desc vd; + size_t len; + dma_addr_t src; + dma_addr_t dst; +}; + +struct milbeaut_xdmac_chan { + struct virt_dma_chan vc; + struct milbeaut_xdmac_device *mdev; + struct milbeaut_xdmac_desc *md; + void __iomem *reg_ch_base; + int irq; + struct dma_slave_config cfg; +}; + +struct milbeaut_xdmac_device { + struct dma_device ddev; + void __iomem *reg_base; + struct milbeaut_xdmac_chan channels[0]; +}; + +static struct milbeaut_xdmac_chan * +to_milbeaut_xdmac_chan(struct virt_dma_chan *vc) +{ + return container_of(vc, struct milbeaut_xdmac_chan, vc); +} + +static struct milbeaut_xdmac_desc * +to_milbeaut_xdmac_desc(struct virt_dma_desc *vd) +{ + return container_of(vd, struct milbeaut_xdmac_desc, vd); +} + +/* mc->vc.lock must be held by caller */ +static struct milbeaut_xdmac_desc * +milbeaut_xdmac_next_desc(struct milbeaut_xdmac_chan *mc) +{ + struct virt_dma_desc *vd; + + vd = vchan_next_desc(>vc); + if (!vd) { + mc->md = NULL; + return NULL; + } + + list_del(>node); + + mc->md = to_milbeaut_xdmac_desc(vd); + + return mc->md; +} + +/* mc->vc.lock must be held by caller */ +static void milbeaut_chan_start(struct milbeaut_xdmac_chan *mc, + struct milbeaut_xdmac_desc *md) +{ + u32 val; + + /* Setup the channel */ + val = md->len - 1; + writel_relaxed(val, mc->reg_ch_base + M10V_XDTBC); + + val = md->src; + writel_relaxed(val, mc->reg_ch_base + M10V_XDSSA); + + val = md->dst; + writel_relaxed(val, mc->reg_ch_base + M10V_XDDSA); + + val = readl_relaxed(mc->reg_ch_base + M10V_XDSAC); +
[PATCH 1/2] dt-bindings: milbeaut-m10v-xdmac: Add Socionext Milbeaut XDMAC bindings
From: Jassi Brar Document the devicetree bindings for Socionext Milbeaut XDMAC controller. Controller only supports Mem->Mem transfers. Number of physical channels are determined by the number of irqs registered. Signed-off-by: Jassi Brar --- .../bindings/dma/milbeaut-m10v-xdmac.txt | 24 +++ 1 file changed, 24 insertions(+) create mode 100644 Documentation/devicetree/bindings/dma/milbeaut-m10v-xdmac.txt diff --git a/Documentation/devicetree/bindings/dma/milbeaut-m10v-xdmac.txt b/Documentation/devicetree/bindings/dma/milbeaut-m10v-xdmac.txt new file mode 100644 index ..1f15512e3f19 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/milbeaut-m10v-xdmac.txt @@ -0,0 +1,24 @@ +* Milbeaut AXI DMA Controller + +Milbeaut AXI DMA controller has only memory to memory transfer capability. + +* DMA controller + +Required property: +- compatible: Should be "socionext,milbeaut-m10v-xdmac" +- reg: Should contain DMA registers location and length. +- interrupts: Should contain all of the per-channel DMA interrupts. +Number of channels is configurable - 2, 4 or 8, so +the number of interrupts specfied should be {2,4,8}. +- #dma-cells: Should be 1. + +Example: + xdmac0: dma-controller@1c25 { + compatible = "socionext,milbeaut-m10v-xdmac"; + reg = <0x1c25 0x1000>; + interrupts = <0 17 0x4>, +<0 18 0x4>, +<0 19 0x4>, +<0 20 0x4>; + #dma-cells = <1>; + }; -- 2.17.1
[PATCH 0/2] Add support for AXI DMA controller on Milbeaut series
From: Jassi Brar The following series adds AXI DMA (XDMAC) controller support on Milbeaut series. This controller is capable of only Mem<->MEM transfers. Number of channels is configurable {2,4,8} Jassi Brar (2): dt-bindings: milbeaut-m10v-xdmac: Add Socionext Milbeaut XDMAC bindings dmaengine: milbeaut-xdmac: Add XDMAC driver for Milbeaut platforms .../bindings/dma/milbeaut-m10v-xdmac.txt | 24 + drivers/dma/Kconfig | 10 + drivers/dma/Makefile | 1 + drivers/dma/milbeaut-xdmac.c | 426 ++ 4 files changed, 461 insertions(+) create mode 100644 Documentation/devicetree/bindings/dma/milbeaut-m10v-xdmac.txt create mode 100644 drivers/dma/milbeaut-xdmac.c -- 2.17.1
[PATCH v2 2/2] dmaengine: milbeaut-hdmac: Add HDMAC driver for Milbeaut platforms
From: Jassi Brar Driver for Socionext Milbeaut HDMAC controller. The controller has upto 8 floating channels, that need a predefined slave-id to work from a set of slaves. Signed-off-by: Jassi Brar --- drivers/dma/Kconfig | 10 + drivers/dma/Makefile | 1 + drivers/dma/milbeaut-hdmac.c | 571 +++ 3 files changed, 582 insertions(+) create mode 100644 drivers/dma/milbeaut-hdmac.c diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 03fa0c58cef3..66979f27f0f3 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -348,6 +348,16 @@ config MCF_EDMA minimal intervention from a host processor. This module can be found on Freescale ColdFire mcf5441x SoCs. +config MILBEAUT_HDMAC + tristate "Milbeaut AHB DMA support" + depends on ARCH_MILBEAUT || COMPILE_TEST + depends on OF + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + help + Say yes here to support the Socionext Milbeaut + HDMAC device. + 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 5bddf6f8790f..e4aed0730dea 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o obj-$(CONFIG_INTEL_MIC_X100_DMA) += mic_x100_dma.o obj-$(CONFIG_K3_DMA) += k3dma.o obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o +obj-$(CONFIG_MILBEAUT_HDMAC) += milbeaut-hdmac.o obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o obj-$(CONFIG_MOXART_DMA) += moxart-dma.o diff --git a/drivers/dma/milbeaut-hdmac.c b/drivers/dma/milbeaut-hdmac.c new file mode 100644 index ..25ba0a692c94 --- /dev/null +++ b/drivers/dma/milbeaut-hdmac.c @@ -0,0 +1,571 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2019 Linaro Ltd. +// Copyright (C) 2019 Socionext Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "virt-dma.h" + +#define MLB_HDMAC_DMACR0x0 /* global */ +#define MLB_HDMAC_DE BIT(31) +#define MLB_HDMAC_DS BIT(30) +#define MLB_HDMAC_PR BIT(28) +#define MLB_HDMAC_DH GENMASK(27, 24) + +#define MLB_HDMAC_CH_STRIDE0x10 + +#define MLB_HDMAC_DMACA0x0 /* channel */ +#define MLB_HDMAC_EB BIT(31) +#define MLB_HDMAC_PB BIT(30) +#define MLB_HDMAC_ST BIT(29) +#define MLB_HDMAC_IS GENMASK(28, 24) +#define MLB_HDMAC_BT GENMASK(23, 20) +#define MLB_HDMAC_BC GENMASK(19, 16) +#define MLB_HDMAC_TC GENMASK(15, 0) +#define MLB_HDMAC_DMACB0x4 +#define MLB_HDMAC_TT GENMASK(31, 30) +#define MLB_HDMAC_MS GENMASK(29, 28) +#define MLB_HDMAC_TW GENMASK(27, 26) +#define MLB_HDMAC_FS BIT(25) +#define MLB_HDMAC_FD BIT(24) +#define MLB_HDMAC_RC BIT(23) +#define MLB_HDMAC_RS BIT(22) +#define MLB_HDMAC_RD BIT(21) +#define MLB_HDMAC_EI BIT(20) +#define MLB_HDMAC_CI BIT(19) +#define HDMAC_PAUSE0x7 +#define MLB_HDMAC_SS GENMASK(18, 16) +#define MLB_HDMAC_SP GENMASK(15, 12) +#define MLB_HDMAC_DP GENMASK(11, 8) +#define MLB_HDMAC_DMACSA 0x8 +#define MLB_HDMAC_DMACDA 0xc + +#define MLB_HDMAC_BUSWIDTHS(BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \ + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \ + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES)) + +struct milbeaut_hdmac_desc { + struct virt_dma_desc vd; + struct scatterlist *sgl; + unsigned int sg_len; + unsigned int sg_cur; + enum dma_transfer_direction dir; +}; + +struct milbeaut_hdmac_chan { + struct virt_dma_chan vc; + struct milbeaut_hdmac_device *mdev; + struct milbeaut_hdmac_desc *md; + void __iomem *reg_ch_base; + unsigned int slave_id; + struct dma_slave_config cfg; +}; + +struct milbeaut_hdmac_device { + struct dma_device ddev; + struct clk *clk; + void __iomem *reg_base; + struct milbeaut_hdmac_chan channels[0]; +}; + +static struct milbeaut_hdmac_chan * +to_milbeaut_hdmac_chan(struct virt_dma_chan *vc) +{ + return container_of(vc, struct milbeaut_hdmac_chan, vc); +} + +static struct milbeaut_hdmac_desc * +to_milbeaut_hdmac_desc(struct virt_dma_desc *vd) +{ + return container_of(vd, struct milbeaut_hdmac_desc, vd); +} + +/* mc->vc.lock must be held by caller */ +static struct milbeaut_hdmac_desc * +milbeaut_hdmac_next_desc(struct milbeaut_hdmac_chan *mc) +{ + struct virt_dma_desc *vd; + + vd = vchan_next_desc(>vc); + if (!vd) { + mc->md = NULL; + return NULL; + } + +
[PATCH v2 1/2] dt-bindings: milbeaut-m10v-hdmac: Add Socionext Milbeaut HDMAC bindings
From: Jassi Brar Document the devicetree bindings for Socionext Milbeaut HDMAC controller. Controller has upto 8 floating channels, that need a predefined slave-id to work from a set of slaves. Signed-off-by: Jassi Brar --- .../bindings/dma/milbeaut-m10v-hdmac.txt | 32 +++ 1 file changed, 32 insertions(+) create mode 100644 Documentation/devicetree/bindings/dma/milbeaut-m10v-hdmac.txt diff --git a/Documentation/devicetree/bindings/dma/milbeaut-m10v-hdmac.txt b/Documentation/devicetree/bindings/dma/milbeaut-m10v-hdmac.txt new file mode 100644 index ..f0960724f1c7 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/milbeaut-m10v-hdmac.txt @@ -0,0 +1,32 @@ +* Milbeaut AHB DMA Controller + +Milbeaut AHB DMA controller has transfer capability bellow. + - device to memory transfer + - memory to device transfer + +Required property: +- compatible: Should be "socionext,milbeaut-m10v-hdmac" +- reg: Should contain DMA registers location and length. +- interrupts: Should contain all of the per-channel DMA interrupts. + Number of channels is configurable - 2, 4 or 8, so + the number of interrupts specfied should be {2,4,8}. +- #dma-cells: Should be 1. Specify the ID of the slave. +- clocks: Phandle to the clock used by the HDMAC module. + + +Example: + + hdmac1: dma-controller@1e11 { + compatible = "socionext,milbeaut-m10v-hdmac"; + reg = <0x1e11 0x1>; + interrupts = <0 132 4>, +<0 133 4>, +<0 134 4>, +<0 135 4>, +<0 136 4>, +<0 137 4>, +<0 138 4>, +<0 139 4>; + #dma-cells = <1>; + clocks = <_clk>; + }; -- 2.17.1
[PATCH v2 0/2] Add support for AHB DMA controller on Milbeaut series
From: Jassi Brar Changes since v1: 1) Drop uncessary headers from driver 2) Some Cosmetic changes. 3) Define macro for magic numbers 4) Specify constraints on number of channels/irq in DT bindings Jassi Brar (2): dt-bindings: milbeaut-m10v-hdmac: Add Socionext Milbeaut HDMAC bindings dmaengine: milbeaut-hdmac: Add HDMAC driver for Milbeaut platforms .../bindings/dma/milbeaut-m10v-hdmac.txt | 32 + drivers/dma/Kconfig | 10 + drivers/dma/Makefile | 1 + drivers/dma/milbeaut-hdmac.c | 571 ++ 4 files changed, 614 insertions(+) create mode 100644 Documentation/devicetree/bindings/dma/milbeaut-m10v-hdmac.txt create mode 100644 drivers/dma/milbeaut-hdmac.c -- 2.17.1
[PATCH 0/2] Add support for AHB DMA controller on Milbeaut series
From: Jassi Brar The following series adds AHB DMA (HDMAC) controller support on Milbeaut series. This controller is capable of Mem<->MEM and DEV<->MEM transfer. But only DEV<->MEM is currently supported. Jassi Brar (2): dt-bindings: milbeaut-hdmac: Add Socionext Milbeaut HDMAC bindings dmaengine: milbeaut-hdmac: Add HDMAC driver for Milbeaut platforms .../bindings/dma/milbeaut-m10v-hdmac.txt | 54 ++ drivers/dma/Kconfig | 10 + drivers/dma/Makefile | 1 + drivers/dma/milbeaut-hdmac.c | 572 ++ 4 files changed, 637 insertions(+) create mode 100644 Documentation/devicetree/bindings/dma/milbeaut-m10v-hdmac.txt create mode 100644 drivers/dma/milbeaut-hdmac.c -- 2.17.1
[PATCH 2/2] dmaengine: milbeaut-hdmac: Add HDMAC driver for Milbeaut platforms
From: Jassi Brar Driver for Socionext Milbeaut HDMAC controller. The controller has upto 8 floating channels, that need a predefined slave-id to work from a set of slaves. Signed-off-by: Jassi Brar --- drivers/dma/Kconfig | 10 + drivers/dma/Makefile | 1 + drivers/dma/milbeaut-hdmac.c | 572 +++ 3 files changed, 583 insertions(+) create mode 100644 drivers/dma/milbeaut-hdmac.c diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 703275cc29de..15a1d5263ca1 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -347,6 +347,16 @@ config MCF_EDMA minimal intervention from a host processor. This module can be found on Freescale ColdFire mcf5441x SoCs. +config MILBEAUT_HDMAC + tristate "Milbeaut AHB DMA support" + depends on ARCH_MILBEAUT || COMPILE_TEST + depends on OF + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + help + Say yes here to support the Socionext Milbeaut + HDMAC device. + 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 6126e1c3a875..d0a9f46726e8 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o obj-$(CONFIG_INTEL_MIC_X100_DMA) += mic_x100_dma.o obj-$(CONFIG_K3_DMA) += k3dma.o obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o +obj-$(CONFIG_MILBEAUT_HDMAC) += milbeaut-hdmac.o obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o obj-$(CONFIG_MOXART_DMA) += moxart-dma.o diff --git a/drivers/dma/milbeaut-hdmac.c b/drivers/dma/milbeaut-hdmac.c new file mode 100644 index ..9c9fabdf8cdc --- /dev/null +++ b/drivers/dma/milbeaut-hdmac.c @@ -0,0 +1,572 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2019 Linaro Ltd. +// Copyright (C) 2019 Socionext Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "virt-dma.h" + +#define MLB_HDMAC_DMACR0x0 /* global */ +#define MLB_HDMAC_DE BIT(31) +#define MLB_HDMAC_DS BIT(30) +#define MLB_HDMAC_PR BIT(28) +#define MLB_HDMAC_DH GENMASK(27, 24) + +#define MLB_HDMAC_CH_STRIDE0x10 + +#define MLB_HDMAC_DMACA0x0 /* channel */ +#define MLB_HDMAC_EB BIT(31) +#define MLB_HDMAC_PB BIT(30) +#define MLB_HDMAC_ST BIT(29) +#define MLB_HDMAC_IS GENMASK(28, 24) +#define MLB_HDMAC_BT GENMASK(23, 20) +#define MLB_HDMAC_BC GENMASK(19, 16) +#define MLB_HDMAC_TC GENMASK(15, 0) +#define MLB_HDMAC_DMACB0x4 +#define MLB_HDMAC_TT GENMASK(31, 30) +#define MLB_HDMAC_MS GENMASK(29, 28) +#define MLB_HDMAC_TW GENMASK(27, 26) +#define MLB_HDMAC_FS BIT(25) +#define MLB_HDMAC_FD BIT(24) +#define MLB_HDMAC_RC BIT(23) +#define MLB_HDMAC_RS BIT(22) +#define MLB_HDMAC_RD BIT(21) +#define MLB_HDMAC_EI BIT(20) +#define MLB_HDMAC_CI BIT(19) +#define MLB_HDMAC_SS GENMASK(18, 16) +#define MLB_HDMAC_SP GENMASK(15, 12) +#define MLB_HDMAC_DP GENMASK(11, 8) +#define MLB_HDMAC_DMACSA 0x8 +#define MLB_HDMAC_DMACDA 0xc + +#define MLB_HDMAC_BUSWIDTHS(BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \ + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \ + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES)) + +struct milbeaut_hdmac_desc { + struct virt_dma_desc vd; + struct scatterlist *sgl; + unsigned int sg_len; + unsigned int sg_cur; + enum dma_transfer_direction dir; +}; + +struct milbeaut_hdmac_chan { + struct virt_dma_chan vc; + struct milbeaut_hdmac_device *mdev; + struct milbeaut_hdmac_desc *md; + void __iomem *reg_ch_base; + unsigned int slave_id; + struct dma_slave_config cfg; +}; + +struct milbeaut_hdmac_device { + struct dma_device ddev; + struct clk *clk; + void __iomem *reg_base; + struct milbeaut_hdmac_chan channels[0]; +}; + +static struct milbeaut_hdmac_chan * +to_milbeaut_hdmac_chan(struct virt_dma_chan *vc) +{ + return container_of(vc, struct milbeaut_hdmac_chan, vc); +} + +static struct milbeaut_hdmac_desc * +to_milbeaut_hdmac_desc(struct virt_dma_desc *vd) +{ + return container_of(vd, struct milbeaut_hdmac_desc, vd); +} + +/* mc->vc.lock must be held by caller */ +static struct milbeaut_hdmac_desc * +milbeaut_hdmac_next_desc(struct milbeaut_hdmac_chan *mc) +{ + struct virt_dma_desc *vd; + + vd = vchan_next_desc(>vc); + if (!vd) { + mc->md = NULL; + return NULL; + } + + list_del(>node); + +
[PATCH 1/2] dt-bindings: milbeaut-m10v-hdmac: Add Socionext Milbeaut HDMAC bindings
From: Jassi Brar Document the devicetree bindings for Socionext Milbeaut HDMAC controller. Controller has upto 8 floating channels, that need a predefined slave-id to work from a set of slaves. Signed-off-by: Jassi Brar --- .../bindings/dma/milbeaut-m10v-hdmac.txt | 54 +++ 1 file changed, 54 insertions(+) create mode 100644 Documentation/devicetree/bindings/dma/milbeaut-m10v-hdmac.txt diff --git a/Documentation/devicetree/bindings/dma/milbeaut-m10v-hdmac.txt b/Documentation/devicetree/bindings/dma/milbeaut-m10v-hdmac.txt new file mode 100644 index ..a104fcb9e73d --- /dev/null +++ b/Documentation/devicetree/bindings/dma/milbeaut-m10v-hdmac.txt @@ -0,0 +1,51 @@ +* Milbeaut AHB DMA Controller + +Milbeaut AHB DMA controller has transfer capability bellow. + - memory to memory transfer + - device to memory transfer + - memory to device transfer + +Required property: +- compatible: Should be "socionext,milbeaut-m10v-hdmac" +- reg: Should contain DMA registers location and length. +- interrupts: Should contain all of the per-channel DMA interrupts. +- #dma-cells: Should be 1. Specify the ID of the slave. +- clocks: Phandle to the clock used by the HDMAC module. + + +Example: + + hdmac1: hdmac@1e11 { + compatible = "socionext,milbeaut-m10v-hdmac"; + reg = <0x1e11 0x1>; + interrupts = <0 132 4>, +<0 133 4>, +<0 134 4>, +<0 135 4>, +<0 136 4>, +<0 137 4>, +<0 138 4>, +<0 139 4>; + #dma-cells = <1>; + clocks = <_clk>; + }; + +* DMA client + +Clients have to specify the DMA requests with phandles in a list. + +Required properties: +- dmas: List of one or more DMA request specifiers. One DMA request specifier +consists of a phandle to the DMA controller followed by the integer +specifying the request line. +- dma-names:List of string identifiers for the DMA requests. For the correct +names, have a look at the specific client driver. + +Example: + + sni_spi1: spi@1e800100 { + ... + dmas = < 22>, < 21>; + dma-names = "tx", "rx"; + ... + }; -- 2.17.1
[RFC 2/3] mailbox: Introduce a new common API
From: Jassi Brar Introduce common framework for client/protocol drivers and controller drivers of Inter-Processor-Communication (IPC). Client driver developers should have a look at include/linux/mailbox_client.h to understand the part of the API exposed to client drivers. Similarly controller driver developers should have a look at include/linux/mailbox_controller.h Signed-off-by: Jassi Brar --- drivers/mailbox/Makefile |4 + drivers/mailbox/mailbox.c | 470 include/linux/mailbox.h| 20 ++ include/linux/mailbox_client.h | 88 +++ include/linux/mailbox_controller.h | 105 5 files changed, 687 insertions(+) create mode 100644 drivers/mailbox/mailbox.c create mode 100644 include/linux/mailbox.h create mode 100644 include/linux/mailbox_client.h create mode 100644 include/linux/mailbox_controller.h diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 543ad6a..fefef7e 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -1 +1,5 @@ +# Generic MAILBOX API + +obj-$(CONFIG_MAILBOX) += mailbox.o + obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c new file mode 100644 index 000..c5ec93e --- /dev/null +++ b/drivers/mailbox/mailbox.c @@ -0,0 +1,470 @@ +/* + * Copyright (C) 2013 Linaro Ltd + * Author: Jaswinder Singh + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * The length of circular buffer for queuing messages from a client. + * 'msg_count' tracks the number of buffered messages while 'msg_free' + * is the index where the next message would be buffered. + * We shouldn't need it too big because every transferr is interrupt + * triggered and if we have lots of data to transfer, the interrupt + * latencies are going to be the bottleneck, not the buffer length. + * Besides, ipc_send_message could be called from atomic context and + * the client could also queue another message from the notifier 'txcb' + * of the last transfer done. + */ +#define MBOX_TX_QUEUE_LEN 10 + +#define TXDONE_BY_IRQ (1 << 0) /* controller has remote RTR irq */ +#define TXDONE_BY_POLL (1 << 1) /* controller can read status of last TX */ +#define TXDONE_BY_ACK (1 << 2) /* S/W ACK recevied by Client ticks the TX */ + +struct ipc_chan { + char chan_name[32]; /* controller_name:link_name */ + unsigned txdone_method; + + /* Cached values from controller */ + struct ipc_link *link; + struct ipc_link_ops *link_ops; + + /* Cached values from client */ + void (*rxcb)(void *data); + void (*txcb)(request_token_t t, enum xfer_result r); + bool tx_block; + unsigned long tx_tout; + struct completion tx_complete; + + request_token_t active_token; + unsigned msg_count, msg_free; + void *msg_data[MBOX_TX_QUEUE_LEN]; + /* Timer shared by all links of a controller */ + struct tx_poll_timer *timer; + bool assigned; + /* Serialize access to the channel */ + spinlock_t lock; + /* Hook to add to the global list of channels */ + struct list_head node; + /* Notifier to all clients waiting on aquiring this channel */ + struct blocking_notifier_head avail; +}; + +/* + * If the controller supports only TXDONE_BY_POLL, this + * timer polls all the links for txdone. + */ +struct tx_poll_timer { + struct timer_list poll; + unsigned period; +}; + +static struct list_head ipc_channels; +static DEFINE_MUTEX(chpool_mutex); + +static request_token_t _add_to_rbuf(struct ipc_chan *chan, void *data) +{ + request_token_t idx; + unsigned long flags; + + spin_lock_irqsave(>lock, flags); + + /* See if there is any space left */ + if (chan->msg_count == MBOX_TX_QUEUE_LEN) { + spin_unlock_irqrestore(>lock, flags); + return 0; + } + + idx = chan->msg_free; + chan->msg_data[idx] = data; + chan->msg_count++; + + if (idx == MBOX_TX_QUEUE_LEN - 1) + chan->msg_free = 0; + else + chan->msg_free++; + + spin_unlock_irqrestore(>lock, flags); + + return idx + 1; +} + +static void _msg_submit(struct ipc_chan *chan) +{ + struct ipc_link *link = chan->link; + unsigned count, idx; + unsigned long flags; + void *data; + int err; + + spin_lock_irqsave(>lock, flags); + + if (!chan->msg_count || chan->active_token) { + spin_unlock_irqrestore(>lock, flags); + return; + } + + count = chan->msg_count; + idx = chan->msg_free; + if (idx >= count) +
[RFC 3/3] mailbox: pl320: Introduce common API driver
From: Jassi Brar Convert the PL320 controller driver to work with the common mailbox API. Also convert the only user of PL320, highbank-cpufreq.c to work with thee API. Drop the obsoleted driver pl320-ipc.c Signed-off-by: Jassi Brar --- drivers/cpufreq/highbank-cpufreq.c | 22 +++- drivers/mailbox/Makefile |2 +- drivers/mailbox/{pl320-ipc.c => pl320.c} | 194 -- include/linux/pl320-ipc.h| 17 --- 4 files changed, 125 insertions(+), 110 deletions(-) rename drivers/mailbox/{pl320-ipc.c => pl320.c} (51%) delete mode 100644 include/linux/pl320-ipc.h diff --git a/drivers/cpufreq/highbank-cpufreq.c b/drivers/cpufreq/highbank-cpufreq.c index 3118b87..5c057e0 100644 --- a/drivers/cpufreq/highbank-cpufreq.c +++ b/drivers/cpufreq/highbank-cpufreq.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #define HB_CPUFREQ_CHANGE_NOTE 0x8001 @@ -29,8 +29,26 @@ static int hb_voltage_change(unsigned int freq) { u32 msg[HB_CPUFREQ_IPC_LEN] = {HB_CPUFREQ_CHANGE_NOTE, freq / 100}; + struct ipc_client cl; + int ret = -ETIMEDOUT; + void *chan; - return pl320_ipc_transmit(msg); + cl.rxcb = NULL; + cl.txcb = NULL; + cl.tx_block = true; + cl.tx_tout = 1000; /* 1 sec */ + cl.cntlr_data = NULL; + cl.knows_txdone = false; + cl.chan_name = "pl320:A9_to_M3"; + + chan = ipc_request_channel(); + + if (ipc_send_message(chan, (void *)msg)) + ret = msg[1]; /* PL320 updates buffer with FIFO after ACK */ + + ipc_free_channel(chan); + + return ret; } static int hb_cpufreq_clk_notify(struct notifier_block *nb, diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index fefef7e..7b897f3 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -2,4 +2,4 @@ obj-$(CONFIG_MAILBOX) += mailbox.o -obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o +obj-$(CONFIG_PL320_MBOX) += pl320.o diff --git a/drivers/mailbox/pl320-ipc.c b/drivers/mailbox/pl320.c similarity index 51% rename from drivers/mailbox/pl320-ipc.c rename to drivers/mailbox/pl320.c index f3755e0..98b40f4 100644 --- a/drivers/mailbox/pl320-ipc.c +++ b/drivers/mailbox/pl320.c @@ -25,8 +25,9 @@ #include #include #include - -#include +#include +#include +#include #define IPCMxSOURCE(m) ((m) * 0x40) #define IPCMxDSET(m) (((m) * 0x40) + 0x004) @@ -44,114 +45,86 @@ #define MBOX_MASK(n) (1 << (n)) #define IPC_TX_MBOX1 -#define IPC_RX_MBOX2 #define CHAN_MASK(n) (1 << (n)) #define A9_SOURCE 1 #define M3_SOURCE 0 -static void __iomem *ipc_base; -static int ipc_irq; -static DEFINE_MUTEX(ipc_m1_lock); -static DECLARE_COMPLETION(ipc_completion); -static ATOMIC_NOTIFIER_HEAD(ipc_notifier); +struct pl320_con { + u32 *data; + int ipc_irq; + struct device *dev; + struct ipc_link link; + void __iomem *ipc_base; + struct ipc_controller ipc_con; +}; -static inline void set_destination(int source, int mbox) +static inline struct pl320_con *to_pl320(struct ipc_link *l) { - __raw_writel(CHAN_MASK(source), ipc_base + IPCMxDSET(mbox)); - __raw_writel(CHAN_MASK(source), ipc_base + IPCMxMSET(mbox)); -} + if (!l) + return NULL; -static inline void clear_destination(int source, int mbox) -{ - __raw_writel(CHAN_MASK(source), ipc_base + IPCMxDCLEAR(mbox)); - __raw_writel(CHAN_MASK(source), ipc_base + IPCMxMCLEAR(mbox)); + return container_of(l, struct pl320_con, link); } -static void __ipc_send(int mbox, u32 *data) +static irqreturn_t ipc_handler(int irq, void *p) { - int i; - for (i = 0; i < 7; i++) - __raw_writel(data[i], ipc_base + IPCMxDR(mbox, i)); - __raw_writel(0x1, ipc_base + IPCMxSEND(mbox)); -} + struct ipc_link *link = (struct ipc_link *)p; + struct pl320_con *pl320 = to_pl320(link); + void __iomem *ipc_base = pl320->ipc_base; + u32 irq_stat; -static u32 __ipc_rcv(int mbox, u32 *data) -{ - int i; - for (i = 0; i < 7; i++) - data[i] = __raw_readl(ipc_base + IPCMxDR(mbox, i)); - return data[1]; -} + irq_stat = __raw_readl(ipc_base + IPCMMIS(1)); + if (irq_stat & MBOX_MASK(IPC_TX_MBOX)) { + u32 *data = pl320->data; + int i; -/* blocking implmentation from the A9 side, not usuable in interrupts! */ -int pl320_ipc_transmit(u32 *data) -{ - int ret; + __raw_writel(0, ipc_base + IPCMxSEND(IPC_TX_MBOX)); + + /* +* The PL320 driver specifies that the send buffer +* will be overwritten by same fifo upon TX ACK. +*/ + for (i = 0; i < 7; i++) + data[i] = __raw_readl(ipc_base +
[RFC 2/3] mailbox: Introduce a new common API
From: Jassi Brar jaswinder.si...@linaro.org Introduce common framework for client/protocol drivers and controller drivers of Inter-Processor-Communication (IPC). Client driver developers should have a look at include/linux/mailbox_client.h to understand the part of the API exposed to client drivers. Similarly controller driver developers should have a look at include/linux/mailbox_controller.h Signed-off-by: Jassi Brar jaswinder.si...@linaro.org --- drivers/mailbox/Makefile |4 + drivers/mailbox/mailbox.c | 470 include/linux/mailbox.h| 20 ++ include/linux/mailbox_client.h | 88 +++ include/linux/mailbox_controller.h | 105 5 files changed, 687 insertions(+) create mode 100644 drivers/mailbox/mailbox.c create mode 100644 include/linux/mailbox.h create mode 100644 include/linux/mailbox_client.h create mode 100644 include/linux/mailbox_controller.h diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 543ad6a..fefef7e 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -1 +1,5 @@ +# Generic MAILBOX API + +obj-$(CONFIG_MAILBOX) += mailbox.o + obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c new file mode 100644 index 000..c5ec93e --- /dev/null +++ b/drivers/mailbox/mailbox.c @@ -0,0 +1,470 @@ +/* + * Copyright (C) 2013 Linaro Ltd + * Author: Jaswinder Singh jassisinghb...@gmail.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/interrupt.h +#include linux/spinlock.h +#include linux/mutex.h +#include linux/delay.h +#include linux/slab.h +#include linux/err.h +#include linux/module.h +#include linux/mailbox_client.h +#include linux/mailbox_controller.h + +/* + * The length of circular buffer for queuing messages from a client. + * 'msg_count' tracks the number of buffered messages while 'msg_free' + * is the index where the next message would be buffered. + * We shouldn't need it too big because every transferr is interrupt + * triggered and if we have lots of data to transfer, the interrupt + * latencies are going to be the bottleneck, not the buffer length. + * Besides, ipc_send_message could be called from atomic context and + * the client could also queue another message from the notifier 'txcb' + * of the last transfer done. + */ +#define MBOX_TX_QUEUE_LEN 10 + +#define TXDONE_BY_IRQ (1 0) /* controller has remote RTR irq */ +#define TXDONE_BY_POLL (1 1) /* controller can read status of last TX */ +#define TXDONE_BY_ACK (1 2) /* S/W ACK recevied by Client ticks the TX */ + +struct ipc_chan { + char chan_name[32]; /* controller_name:link_name */ + unsigned txdone_method; + + /* Cached values from controller */ + struct ipc_link *link; + struct ipc_link_ops *link_ops; + + /* Cached values from client */ + void (*rxcb)(void *data); + void (*txcb)(request_token_t t, enum xfer_result r); + bool tx_block; + unsigned long tx_tout; + struct completion tx_complete; + + request_token_t active_token; + unsigned msg_count, msg_free; + void *msg_data[MBOX_TX_QUEUE_LEN]; + /* Timer shared by all links of a controller */ + struct tx_poll_timer *timer; + bool assigned; + /* Serialize access to the channel */ + spinlock_t lock; + /* Hook to add to the global list of channels */ + struct list_head node; + /* Notifier to all clients waiting on aquiring this channel */ + struct blocking_notifier_head avail; +}; + +/* + * If the controller supports only TXDONE_BY_POLL, this + * timer polls all the links for txdone. + */ +struct tx_poll_timer { + struct timer_list poll; + unsigned period; +}; + +static struct list_head ipc_channels; +static DEFINE_MUTEX(chpool_mutex); + +static request_token_t _add_to_rbuf(struct ipc_chan *chan, void *data) +{ + request_token_t idx; + unsigned long flags; + + spin_lock_irqsave(chan-lock, flags); + + /* See if there is any space left */ + if (chan-msg_count == MBOX_TX_QUEUE_LEN) { + spin_unlock_irqrestore(chan-lock, flags); + return 0; + } + + idx = chan-msg_free; + chan-msg_data[idx] = data; + chan-msg_count++; + + if (idx == MBOX_TX_QUEUE_LEN - 1) + chan-msg_free = 0; + else + chan-msg_free++; + + spin_unlock_irqrestore(chan-lock, flags); + + return idx + 1; +} + +static void _msg_submit(struct ipc_chan *chan) +{ + struct ipc_link *link = chan-link; + unsigned count, idx; + unsigned long flags; + void *data; + int err; + + spin_lock_irqsave(chan-lock, flags); + + if
[RFC 3/3] mailbox: pl320: Introduce common API driver
From: Jassi Brar jaswinder.si...@linaro.org Convert the PL320 controller driver to work with the common mailbox API. Also convert the only user of PL320, highbank-cpufreq.c to work with thee API. Drop the obsoleted driver pl320-ipc.c Signed-off-by: Jassi Brar jaswinder.si...@linaro.org --- drivers/cpufreq/highbank-cpufreq.c | 22 +++- drivers/mailbox/Makefile |2 +- drivers/mailbox/{pl320-ipc.c = pl320.c} | 194 -- include/linux/pl320-ipc.h| 17 --- 4 files changed, 125 insertions(+), 110 deletions(-) rename drivers/mailbox/{pl320-ipc.c = pl320.c} (51%) delete mode 100644 include/linux/pl320-ipc.h diff --git a/drivers/cpufreq/highbank-cpufreq.c b/drivers/cpufreq/highbank-cpufreq.c index 3118b87..5c057e0 100644 --- a/drivers/cpufreq/highbank-cpufreq.c +++ b/drivers/cpufreq/highbank-cpufreq.c @@ -19,7 +19,7 @@ #include linux/cpu.h #include linux/err.h #include linux/of.h -#include linux/pl320-ipc.h +#include linux/mailbox_client.h #include linux/platform_device.h #define HB_CPUFREQ_CHANGE_NOTE 0x8001 @@ -29,8 +29,26 @@ static int hb_voltage_change(unsigned int freq) { u32 msg[HB_CPUFREQ_IPC_LEN] = {HB_CPUFREQ_CHANGE_NOTE, freq / 100}; + struct ipc_client cl; + int ret = -ETIMEDOUT; + void *chan; - return pl320_ipc_transmit(msg); + cl.rxcb = NULL; + cl.txcb = NULL; + cl.tx_block = true; + cl.tx_tout = 1000; /* 1 sec */ + cl.cntlr_data = NULL; + cl.knows_txdone = false; + cl.chan_name = pl320:A9_to_M3; + + chan = ipc_request_channel(cl); + + if (ipc_send_message(chan, (void *)msg)) + ret = msg[1]; /* PL320 updates buffer with FIFO after ACK */ + + ipc_free_channel(chan); + + return ret; } static int hb_cpufreq_clk_notify(struct notifier_block *nb, diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index fefef7e..7b897f3 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -2,4 +2,4 @@ obj-$(CONFIG_MAILBOX) += mailbox.o -obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o +obj-$(CONFIG_PL320_MBOX) += pl320.o diff --git a/drivers/mailbox/pl320-ipc.c b/drivers/mailbox/pl320.c similarity index 51% rename from drivers/mailbox/pl320-ipc.c rename to drivers/mailbox/pl320.c index f3755e0..98b40f4 100644 --- a/drivers/mailbox/pl320-ipc.c +++ b/drivers/mailbox/pl320.c @@ -25,8 +25,9 @@ #include linux/spinlock.h #include linux/device.h #include linux/amba/bus.h - -#include linux/pl320-ipc.h +#include linux/slab.h +#include linux/platform_device.h +#include linux/mailbox_controller.h #define IPCMxSOURCE(m) ((m) * 0x40) #define IPCMxDSET(m) (((m) * 0x40) + 0x004) @@ -44,114 +45,86 @@ #define MBOX_MASK(n) (1 (n)) #define IPC_TX_MBOX1 -#define IPC_RX_MBOX2 #define CHAN_MASK(n) (1 (n)) #define A9_SOURCE 1 #define M3_SOURCE 0 -static void __iomem *ipc_base; -static int ipc_irq; -static DEFINE_MUTEX(ipc_m1_lock); -static DECLARE_COMPLETION(ipc_completion); -static ATOMIC_NOTIFIER_HEAD(ipc_notifier); +struct pl320_con { + u32 *data; + int ipc_irq; + struct device *dev; + struct ipc_link link; + void __iomem *ipc_base; + struct ipc_controller ipc_con; +}; -static inline void set_destination(int source, int mbox) +static inline struct pl320_con *to_pl320(struct ipc_link *l) { - __raw_writel(CHAN_MASK(source), ipc_base + IPCMxDSET(mbox)); - __raw_writel(CHAN_MASK(source), ipc_base + IPCMxMSET(mbox)); -} + if (!l) + return NULL; -static inline void clear_destination(int source, int mbox) -{ - __raw_writel(CHAN_MASK(source), ipc_base + IPCMxDCLEAR(mbox)); - __raw_writel(CHAN_MASK(source), ipc_base + IPCMxMCLEAR(mbox)); + return container_of(l, struct pl320_con, link); } -static void __ipc_send(int mbox, u32 *data) +static irqreturn_t ipc_handler(int irq, void *p) { - int i; - for (i = 0; i 7; i++) - __raw_writel(data[i], ipc_base + IPCMxDR(mbox, i)); - __raw_writel(0x1, ipc_base + IPCMxSEND(mbox)); -} + struct ipc_link *link = (struct ipc_link *)p; + struct pl320_con *pl320 = to_pl320(link); + void __iomem *ipc_base = pl320-ipc_base; + u32 irq_stat; -static u32 __ipc_rcv(int mbox, u32 *data) -{ - int i; - for (i = 0; i 7; i++) - data[i] = __raw_readl(ipc_base + IPCMxDR(mbox, i)); - return data[1]; -} + irq_stat = __raw_readl(ipc_base + IPCMMIS(1)); + if (irq_stat MBOX_MASK(IPC_TX_MBOX)) { + u32 *data = pl320-data; + int i; -/* blocking implmentation from the A9 side, not usuable in interrupts! */ -int pl320_ipc_transmit(u32 *data) -{ - int ret; + __raw_writel(0, ipc_base + IPCMxSEND(IPC_TX_MBOX)); + + /* +