Commit 65163d16 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'dmaengine-fix-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine

Pull dmaengine updates from Vinod Koul:
 "New support:
   - Loongson LS2X APB DMA controller
   - sf-pdma: mpfs-pdma support
   - Qualcomm X1E80100 GPI dma controller support

  Updates:
   - Xilinx XDMA updates to support interleaved DMA transfers
   - TI PSIL threads for AM62P and J722S and cfg register regions
     description
   - axi-dmac Improving the cyclic DMA transfers
   - Tegra Support dma-channel-mask property
   - Remaining platform remove callback returning void conversions

 Driver fixes for:
   - Xilinx xdma driver operator precedence and initialization fix
   - Excess kernel-doc warning fix in imx-sdma xilinx xdma drivers
   - format-overflow warning fix for rz-dmac, sh usb dmac drivers
   - 'output may be truncated' fix for shdma, fsl-qdma and dw-edma
     drivers"

* tag 'dmaengine-fix-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine: (58 commits)
  dmaengine: dw-edma: increase size of 'name' in debugfs code
  dmaengine: fsl-qdma: increase size of 'irq_name'
  dmaengine: shdma: increase size of 'dev_id'
  dmaengine: xilinx: xdma: Fix kernel-doc warnings
  dmaengine: usb-dmac: Avoid format-overflow warning
  dmaengine: sh: rz-dmac: Avoid format-overflow warning
  dmaengine: imx-sdma: fix Excess kernel-doc warnings
  dmaengine: xilinx: xdma: Fix initialization location of desc in xdma_channel_isr()
  dmaengine: xilinx: xdma: Fix operator precedence in xdma_prep_interleaved_dma()
  dmaengine: xilinx: xdma: statify xdma_prep_interleaved_dma
  dmaengine: xilinx: xdma: Workaround truncation compilation error
  dmaengine: pl330: issue_pending waits until WFP state
  dmaengine: xilinx: xdma: Implement interleaved DMA transfers
  dmaengine: xilinx: xdma: Prepare the introduction of interleaved DMA transfers
  dmaengine: xilinx: xdma: Add transfer error reporting
  dmaengine: xilinx: xdma: Add error checking in xdma_channel_isr()
  dmaengine: xilinx: xdma: Rework xdma_terminate_all()
  dmaengine: xilinx: xdma: Ease dma_pool alignment requirements
  dmaengine: xilinx: xdma: Add necessary macro definitions
  dmaengine: xilinx: xdma: Get rid of unused code
  ...
parents 80fc600f cb95a4fa
...@@ -19,19 +19,4 @@ properties: ...@@ -19,19 +19,4 @@ properties:
additionalProperties: true additionalProperties: true
examples:
- |
dma: dma-controller@48000000 {
compatible = "ti,omap-sdma";
reg = <0x48000000 0x1000>;
interrupts = <0 12 0x4>,
<0 13 0x4>,
<0 14 0x4>,
<0 15 0x4>;
#dma-cells = <1>;
dma-channels = <32>;
dma-requests = <127>;
dma-channel-mask = <0xfffe>;
};
... ...
...@@ -40,15 +40,4 @@ required: ...@@ -40,15 +40,4 @@ required:
additionalProperties: true additionalProperties: true
examples:
- |
sdma_xbar: dma-router@4a002b78 {
compatible = "ti,dra7-dma-crossbar";
reg = <0x4a002b78 0xfc>;
#dma-cells = <1>;
dma-requests = <205>;
ti,dma-safe-map = <0>;
dma-masters = <&sdma>;
};
... ...
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/dma/loongson,ls2x-apbdma.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Loongson LS2X APB DMA controller
description:
The Loongson LS2X APB DMA controller is used for transferring data
between system memory and the peripherals on the APB bus.
maintainers:
- Binbin Zhou <zhoubinbin@loongson.cn>
allOf:
- $ref: dma-controller.yaml#
properties:
compatible:
oneOf:
- const: loongson,ls2k1000-apbdma
- items:
- const: loongson,ls2k0500-apbdma
- const: loongson,ls2k1000-apbdma
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
'#dma-cells':
const: 1
required:
- compatible
- reg
- interrupts
- clocks
- '#dma-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/clock/loongson,ls2k-clk.h>
dma-controller@1fe00c00 {
compatible = "loongson,ls2k1000-apbdma";
reg = <0x1fe00c00 0x8>;
interrupt-parent = <&liointc1>;
interrupts = <12 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk LOONGSON2_APB_CLK>;
#dma-cells = <1>;
};
...
...@@ -53,6 +53,9 @@ properties: ...@@ -53,6 +53,9 @@ properties:
ADMA_CHn_CTRL register. ADMA_CHn_CTRL register.
const: 1 const: 1
dma-channel-mask:
maxItems: 1
required: required:
- compatible - compatible
- reg - reg
......
...@@ -32,6 +32,8 @@ properties: ...@@ -32,6 +32,8 @@ properties:
- qcom,sm8350-gpi-dma - qcom,sm8350-gpi-dma
- qcom,sm8450-gpi-dma - qcom,sm8450-gpi-dma
- qcom,sm8550-gpi-dma - qcom,sm8550-gpi-dma
- qcom,sm8650-gpi-dma
- qcom,x1e80100-gpi-dma
- const: qcom,sm6350-gpi-dma - const: qcom,sm6350-gpi-dma
- items: - items:
- enum: - enum:
......
...@@ -16,7 +16,7 @@ properties: ...@@ -16,7 +16,7 @@ properties:
compatible: compatible:
items: items:
- enum: - enum:
- renesas,r9a07g043-dmac # RZ/G2UL - renesas,r9a07g043-dmac # RZ/G2UL and RZ/Five
- renesas,r9a07g044-dmac # RZ/G2{L,LC} - renesas,r9a07g044-dmac # RZ/G2{L,LC}
- renesas,r9a07g054-dmac # RZ/V2L - renesas,r9a07g054-dmac # RZ/V2L
- const: renesas,rz-dmac - const: renesas,rz-dmac
......
...@@ -29,6 +29,7 @@ properties: ...@@ -29,6 +29,7 @@ properties:
compatible: compatible:
items: items:
- enum: - enum:
- microchip,mpfs-pdma
- sifive,fu540-c000-pdma - sifive,fu540-c000-pdma
- const: sifive,pdma0 - const: sifive,pdma0
description: description:
......
...@@ -37,11 +37,11 @@ properties: ...@@ -37,11 +37,11 @@ properties:
reg: reg:
minItems: 3 minItems: 3
maxItems: 5 maxItems: 9
reg-names: reg-names:
minItems: 3 minItems: 3
maxItems: 5 maxItems: 9
"#dma-cells": "#dma-cells":
const: 3 const: 3
...@@ -141,7 +141,10 @@ allOf: ...@@ -141,7 +141,10 @@ allOf:
ti,sci-rm-range-tchan: false ti,sci-rm-range-tchan: false
reg: reg:
maxItems: 3 items:
- description: BCDMA Control /Status Registers region
- description: RX Channel Realtime Registers region
- description: Ring Realtime Registers region
reg-names: reg-names:
items: items:
...@@ -161,14 +164,29 @@ allOf: ...@@ -161,14 +164,29 @@ allOf:
properties: properties:
reg: reg:
minItems: 5 minItems: 5
items:
- description: BCDMA Control /Status Registers region
- description: Block Copy Channel Realtime Registers region
- description: RX Channel Realtime Registers region
- description: TX Channel Realtime Registers region
- description: Ring Realtime Registers region
- description: Ring Configuration Registers region
- description: TX Channel Configuration Registers region
- description: RX Channel Configuration Registers region
- description: Block Copy Channel Configuration Registers region
reg-names: reg-names:
minItems: 5
items: items:
- const: gcfg - const: gcfg
- const: bchanrt - const: bchanrt
- const: rchanrt - const: rchanrt
- const: tchanrt - const: tchanrt
- const: ringrt - const: ringrt
- const: ring
- const: tchan
- const: rchan
- const: bchan
required: required:
- ti,sci-rm-range-bchan - ti,sci-rm-range-bchan
...@@ -184,7 +202,11 @@ allOf: ...@@ -184,7 +202,11 @@ allOf:
ti,sci-rm-range-bchan: false ti,sci-rm-range-bchan: false
reg: reg:
maxItems: 4 items:
- description: BCDMA Control /Status Registers region
- description: RX Channel Realtime Registers region
- description: TX Channel Realtime Registers region
- description: Ring Realtime Registers region
reg-names: reg-names:
items: items:
...@@ -220,8 +242,13 @@ examples: ...@@ -220,8 +242,13 @@ examples:
<0x0 0x4c000000 0x0 0x20000>, <0x0 0x4c000000 0x0 0x20000>,
<0x0 0x4a820000 0x0 0x20000>, <0x0 0x4a820000 0x0 0x20000>,
<0x0 0x4aa40000 0x0 0x20000>, <0x0 0x4aa40000 0x0 0x20000>,
<0x0 0x4bc00000 0x0 0x100000>; <0x0 0x4bc00000 0x0 0x100000>,
reg-names = "gcfg", "bchanrt", "rchanrt", "tchanrt", "ringrt"; <0x0 0x48600000 0x0 0x8000>,
<0x0 0x484a4000 0x0 0x2000>,
<0x0 0x484c2000 0x0 0x2000>,
<0x0 0x48420000 0x0 0x2000>;
reg-names = "gcfg", "bchanrt", "rchanrt", "tchanrt", "ringrt",
"ring", "tchan", "rchan", "bchan";
msi-parent = <&inta_main_dmss>; msi-parent = <&inta_main_dmss>;
#dma-cells = <3>; #dma-cells = <3>;
......
...@@ -45,14 +45,28 @@ properties: ...@@ -45,14 +45,28 @@ properties:
The second cell is the ASEL value for the channel The second cell is the ASEL value for the channel
reg: reg:
maxItems: 4 minItems: 4
items:
- description: Packet DMA Control /Status Registers region
- description: RX Channel Realtime Registers region
- description: TX Channel Realtime Registers region
- description: Ring Realtime Registers region
- description: Ring Configuration Registers region
- description: TX Configuration Registers region
- description: RX Configuration Registers region
- description: RX Flow Configuration Registers region
reg-names: reg-names:
minItems: 4
items: items:
- const: gcfg - const: gcfg
- const: rchanrt - const: rchanrt
- const: tchanrt - const: tchanrt
- const: ringrt - const: ringrt
- const: ring
- const: tchan
- const: rchan
- const: rflow
msi-parent: true msi-parent: true
...@@ -136,8 +150,14 @@ examples: ...@@ -136,8 +150,14 @@ examples:
reg = <0x0 0x485c0000 0x0 0x100>, reg = <0x0 0x485c0000 0x0 0x100>,
<0x0 0x4a800000 0x0 0x20000>, <0x0 0x4a800000 0x0 0x20000>,
<0x0 0x4aa00000 0x0 0x40000>, <0x0 0x4aa00000 0x0 0x40000>,
<0x0 0x4b800000 0x0 0x400000>; <0x0 0x4b800000 0x0 0x400000>,
reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt"; <0x0 0x485e0000 0x0 0x20000>,
<0x0 0x484a0000 0x0 0x4000>,
<0x0 0x484c0000 0x0 0x2000>,
<0x0 0x48430000 0x0 0x4000>;
reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt",
"ring", "tchan", "rchan", "rflow";
msi-parent = <&inta_main_dmss>; msi-parent = <&inta_main_dmss>;
#dma-cells = <2>; #dma-cells = <2>;
......
...@@ -69,13 +69,24 @@ properties: ...@@ -69,13 +69,24 @@ properties:
- ti,j721e-navss-mcu-udmap - ti,j721e-navss-mcu-udmap
reg: reg:
maxItems: 3 minItems: 3
items:
- description: UDMA-P Control /Status Registers region
- description: RX Channel Realtime Registers region
- description: TX Channel Realtime Registers region
- description: TX Configuration Registers region
- description: RX Configuration Registers region
- description: RX Flow Configuration Registers region
reg-names: reg-names:
minItems: 3
items: items:
- const: gcfg - const: gcfg
- const: rchanrt - const: rchanrt
- const: tchanrt - const: tchanrt
- const: tchan
- const: rchan
- const: rflow
msi-parent: true msi-parent: true
...@@ -158,8 +169,11 @@ examples: ...@@ -158,8 +169,11 @@ examples:
compatible = "ti,am654-navss-main-udmap"; compatible = "ti,am654-navss-main-udmap";
reg = <0x0 0x31150000 0x0 0x100>, reg = <0x0 0x31150000 0x0 0x100>,
<0x0 0x34000000 0x0 0x100000>, <0x0 0x34000000 0x0 0x100000>,
<0x0 0x35000000 0x0 0x100000>; <0x0 0x35000000 0x0 0x100000>,
reg-names = "gcfg", "rchanrt", "tchanrt"; <0x0 0x30b00000 0x0 0x20000>,
<0x0 0x30c00000 0x0 0x8000>,
<0x0 0x30d00000 0x0 0x4000>;
reg-names = "gcfg", "rchanrt", "tchanrt", "tchan", "rchan", "rflow";
#dma-cells = <1>; #dma-cells = <1>;
ti,ringacc = <&ringacc>; ti,ringacc = <&ringacc>;
......
...@@ -12639,6 +12639,13 @@ S: Maintained ...@@ -12639,6 +12639,13 @@ S: Maintained
F: Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml F: Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml
F: drivers/gpio/gpio-loongson-64bit.c F: drivers/gpio/gpio-loongson-64bit.c
LOONGSON LS2X APB DMA DRIVER
M: Binbin Zhou <zhoubinbin@loongson.cn>
L: dmaengine@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/dma/loongson,ls2x-apbdma.yaml
F: drivers/dma/ls2x-apb-dma.c
LOONGSON LS2X I2C DRIVER LOONGSON LS2X I2C DRIVER
M: Binbin Zhou <zhoubinbin@loongson.cn> M: Binbin Zhou <zhoubinbin@loongson.cn>
L: linux-i2c@vger.kernel.org L: linux-i2c@vger.kernel.org
......
...@@ -378,6 +378,20 @@ config LPC18XX_DMAMUX ...@@ -378,6 +378,20 @@ config LPC18XX_DMAMUX
Enable support for DMA on NXP LPC18xx/43xx platforms Enable support for DMA on NXP LPC18xx/43xx platforms
with PL080 and multiplexed DMA request lines. with PL080 and multiplexed DMA request lines.
config LS2X_APB_DMA
tristate "Loongson LS2X APB DMA support"
depends on LOONGARCH || COMPILE_TEST
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
help
Support for the Loongson LS2X APB DMA controller driver. The
DMA controller is having single DMA channel which can be
configured for different peripherals like audio, nand, sdio
etc which is in APB bus.
This DMA controller transfers data from memory to peripheral fifo.
It does not support memory to memory data transfer.
config MCF_EDMA config MCF_EDMA
tristate "Freescale eDMA engine support, ColdFire mcf5441x SoCs" tristate "Freescale eDMA engine support, ColdFire mcf5441x SoCs"
depends on M5441x || COMPILE_TEST depends on M5441x || COMPILE_TEST
......
...@@ -48,6 +48,7 @@ obj-$(CONFIG_INTEL_IOATDMA) += ioat/ ...@@ -48,6 +48,7 @@ obj-$(CONFIG_INTEL_IOATDMA) += ioat/
obj-y += idxd/ obj-y += idxd/
obj-$(CONFIG_K3_DMA) += k3dma.o obj-$(CONFIG_K3_DMA) += k3dma.o
obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o
obj-$(CONFIG_LS2X_APB_DMA) += ls2x-apb-dma.o
obj-$(CONFIG_MILBEAUT_HDMAC) += milbeaut-hdmac.o obj-$(CONFIG_MILBEAUT_HDMAC) += milbeaut-hdmac.o
obj-$(CONFIG_MILBEAUT_XDMAC) += milbeaut-xdmac.o obj-$(CONFIG_MILBEAUT_XDMAC) += milbeaut-xdmac.o
obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o
......
...@@ -57,6 +57,8 @@ ...@@ -57,6 +57,8 @@
#define REG_BUS_WIDTH(ch) (0x8040 + (ch) * 0x200) #define REG_BUS_WIDTH(ch) (0x8040 + (ch) * 0x200)
#define BUS_WIDTH_WORD_SIZE GENMASK(3, 0)
#define BUS_WIDTH_FRAME_SIZE GENMASK(7, 4)
#define BUS_WIDTH_8BIT 0x00 #define BUS_WIDTH_8BIT 0x00
#define BUS_WIDTH_16BIT 0x01 #define BUS_WIDTH_16BIT 0x01
#define BUS_WIDTH_32BIT 0x02 #define BUS_WIDTH_32BIT 0x02
...@@ -740,7 +742,8 @@ static int admac_device_config(struct dma_chan *chan, ...@@ -740,7 +742,8 @@ static int admac_device_config(struct dma_chan *chan,
struct admac_data *ad = adchan->host; struct admac_data *ad = adchan->host;
bool is_tx = admac_chan_direction(adchan->no) == DMA_MEM_TO_DEV; bool is_tx = admac_chan_direction(adchan->no) == DMA_MEM_TO_DEV;
int wordsize = 0; int wordsize = 0;
u32 bus_width = 0; u32 bus_width = readl_relaxed(ad->base + REG_BUS_WIDTH(adchan->no)) &
~(BUS_WIDTH_WORD_SIZE | BUS_WIDTH_FRAME_SIZE);
switch (is_tx ? config->dst_addr_width : config->src_addr_width) { switch (is_tx ? config->dst_addr_width : config->src_addr_width) {
case DMA_SLAVE_BUSWIDTH_1_BYTE: case DMA_SLAVE_BUSWIDTH_1_BYTE:
......
This diff is collapsed.
...@@ -1103,6 +1103,9 @@ EXPORT_SYMBOL_GPL(dma_async_device_channel_register); ...@@ -1103,6 +1103,9 @@ EXPORT_SYMBOL_GPL(dma_async_device_channel_register);
static void __dma_async_device_channel_unregister(struct dma_device *device, static void __dma_async_device_channel_unregister(struct dma_device *device,
struct dma_chan *chan) struct dma_chan *chan)
{ {
if (chan->local == NULL)
return;
WARN_ONCE(!device->device_release && chan->client_count, WARN_ONCE(!device->device_release && chan->client_count,
"%s called while %d clients hold a reference\n", "%s called while %d clients hold a reference\n",
__func__, chan->client_count); __func__, chan->client_count);
......
...@@ -21,6 +21,10 @@ ...@@ -21,6 +21,10 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/wait.h> #include <linux/wait.h>
static bool nobounce;
module_param(nobounce, bool, 0644);
MODULE_PARM_DESC(nobounce, "Prevent using swiotlb buffer (default: use swiotlb buffer)");
static unsigned int test_buf_size = 16384; static unsigned int test_buf_size = 16384;
module_param(test_buf_size, uint, 0644); module_param(test_buf_size, uint, 0644);
MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer"); MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer");
...@@ -90,6 +94,7 @@ MODULE_PARM_DESC(polled, "Use polling for completion instead of interrupts"); ...@@ -90,6 +94,7 @@ MODULE_PARM_DESC(polled, "Use polling for completion instead of interrupts");
/** /**
* struct dmatest_params - test parameters. * struct dmatest_params - test parameters.
* @nobounce: prevent using swiotlb buffer
* @buf_size: size of the memcpy test buffer * @buf_size: size of the memcpy test buffer
* @channel: bus ID of the channel to test * @channel: bus ID of the channel to test
* @device: bus ID of the DMA Engine to test * @device: bus ID of the DMA Engine to test
...@@ -106,6 +111,7 @@ MODULE_PARM_DESC(polled, "Use polling for completion instead of interrupts"); ...@@ -106,6 +111,7 @@ MODULE_PARM_DESC(polled, "Use polling for completion instead of interrupts");
* @polled: use polling for completion instead of interrupts * @polled: use polling for completion instead of interrupts
*/ */
struct dmatest_params { struct dmatest_params {
bool nobounce;
unsigned int buf_size; unsigned int buf_size;
char channel[20]; char channel[20];
char device[32]; char device[32];
...@@ -215,6 +221,7 @@ struct dmatest_done { ...@@ -215,6 +221,7 @@ struct dmatest_done {
struct dmatest_data { struct dmatest_data {
u8 **raw; u8 **raw;
u8 **aligned; u8 **aligned;
gfp_t gfp_flags;
unsigned int cnt; unsigned int cnt;
unsigned int off; unsigned int off;
}; };
...@@ -533,7 +540,7 @@ static int dmatest_alloc_test_data(struct dmatest_data *d, ...@@ -533,7 +540,7 @@ static int dmatest_alloc_test_data(struct dmatest_data *d,
goto err; goto err;
for (i = 0; i < d->cnt; i++) { for (i = 0; i < d->cnt; i++) {
d->raw[i] = kmalloc(buf_size + align, GFP_KERNEL); d->raw[i] = kmalloc(buf_size + align, d->gfp_flags);
if (!d->raw[i]) if (!d->raw[i])
goto err; goto err;
...@@ -655,6 +662,13 @@ static int dmatest_func(void *data) ...@@ -655,6 +662,13 @@ static int dmatest_func(void *data)
goto err_free_coefs; goto err_free_coefs;
} }
src->gfp_flags = GFP_KERNEL;
dst->gfp_flags = GFP_KERNEL;
if (params->nobounce) {
src->gfp_flags = GFP_DMA;
dst->gfp_flags = GFP_DMA;
}
if (dmatest_alloc_test_data(src, buf_size, align) < 0) if (dmatest_alloc_test_data(src, buf_size, align) < 0)
goto err_free_coefs; goto err_free_coefs;
...@@ -1093,6 +1107,7 @@ static void add_threaded_test(struct dmatest_info *info) ...@@ -1093,6 +1107,7 @@ static void add_threaded_test(struct dmatest_info *info)
struct dmatest_params *params = &info->params; struct dmatest_params *params = &info->params;
/* Copy test parameters */ /* Copy test parameters */
params->nobounce = nobounce;
params->buf_size = test_buf_size; params->buf_size = test_buf_size;
strscpy(params->channel, strim(test_channel), sizeof(params->channel)); strscpy(params->channel, strim(test_channel), sizeof(params->channel));
strscpy(params->device, strim(test_device), sizeof(params->device)); strscpy(params->device, strim(test_device), sizeof(params->device));
......
...@@ -176,7 +176,7 @@ dw_edma_debugfs_regs_wr(struct dw_edma *dw, struct dentry *dent) ...@@ -176,7 +176,7 @@ dw_edma_debugfs_regs_wr(struct dw_edma *dw, struct dentry *dent)
}; };
struct dentry *regs_dent, *ch_dent; struct dentry *regs_dent, *ch_dent;
int nr_entries, i; int nr_entries, i;
char name[16]; char name[32];
regs_dent = debugfs_create_dir(WRITE_STR, dent); regs_dent = debugfs_create_dir(WRITE_STR, dent);
...@@ -239,7 +239,7 @@ static noinline_for_stack void dw_edma_debugfs_regs_rd(struct dw_edma *dw, ...@@ -239,7 +239,7 @@ static noinline_for_stack void dw_edma_debugfs_regs_rd(struct dw_edma *dw,
}; };
struct dentry *regs_dent, *ch_dent; struct dentry *regs_dent, *ch_dent;
int nr_entries, i; int nr_entries, i;
char name[16]; char name[32];
regs_dent = debugfs_create_dir(READ_STR, dent); regs_dent = debugfs_create_dir(READ_STR, dent);
......
...@@ -116,7 +116,7 @@ static void dw_hdma_debugfs_regs_ch(struct dw_edma *dw, enum dw_edma_dir dir, ...@@ -116,7 +116,7 @@ static void dw_hdma_debugfs_regs_ch(struct dw_edma *dw, enum dw_edma_dir dir,
static void dw_hdma_debugfs_regs_wr(struct dw_edma *dw, struct dentry *dent) static void dw_hdma_debugfs_regs_wr(struct dw_edma *dw, struct dentry *dent)
{ {
struct dentry *regs_dent, *ch_dent; struct dentry *regs_dent, *ch_dent;
char name[16]; char name[32];
int i; int i;
regs_dent = debugfs_create_dir(WRITE_STR, dent); regs_dent = debugfs_create_dir(WRITE_STR, dent);
...@@ -133,7 +133,7 @@ static void dw_hdma_debugfs_regs_wr(struct dw_edma *dw, struct dentry *dent) ...@@ -133,7 +133,7 @@ static void dw_hdma_debugfs_regs_wr(struct dw_edma *dw, struct dentry *dent)
static void dw_hdma_debugfs_regs_rd(struct dw_edma *dw, struct dentry *dent) static void dw_hdma_debugfs_regs_rd(struct dw_edma *dw, struct dentry *dent)
{ {
struct dentry *regs_dent, *ch_dent; struct dentry *regs_dent, *ch_dent;
char name[16]; char name[32];
int i; int i;
regs_dent = debugfs_create_dir(READ_STR, dent); regs_dent = debugfs_create_dir(READ_STR, dent);
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
* Vybrid and Layerscape SoCs. * Vybrid and Layerscape SoCs.
*/ */
#include <dt-bindings/dma/fsl-edma.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/clk.h> #include <linux/clk.h>
...@@ -21,10 +22,6 @@ ...@@ -21,10 +22,6 @@
#include "fsl-edma-common.h" #include "fsl-edma-common.h"
#define ARGS_RX BIT(0)
#define ARGS_REMOTE BIT(1)
#define ARGS_MULTI_FIFO BIT(2)
static void fsl_edma_synchronize(struct dma_chan *chan) static void fsl_edma_synchronize(struct dma_chan *chan)
{ {
struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan); struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
...@@ -153,9 +150,15 @@ static struct dma_chan *fsl_edma3_xlate(struct of_phandle_args *dma_spec, ...@@ -153,9 +150,15 @@ static struct dma_chan *fsl_edma3_xlate(struct of_phandle_args *dma_spec,
i = fsl_chan - fsl_edma->chans; i = fsl_chan - fsl_edma->chans;
fsl_chan->priority = dma_spec->args[1]; fsl_chan->priority = dma_spec->args[1];
fsl_chan->is_rxchan = dma_spec->args[2] & ARGS_RX; fsl_chan->is_rxchan = dma_spec->args[2] & FSL_EDMA_RX;
fsl_chan->is_remote = dma_spec->args[2] & ARGS_REMOTE; fsl_chan->is_remote = dma_spec->args[2] & FSL_EDMA_REMOTE;
fsl_chan->is_multi_fifo = dma_spec->args[2] & ARGS_MULTI_FIFO; fsl_chan->is_multi_fifo = dma_spec->args[2] & FSL_EDMA_MULTI_FIFO;
if ((dma_spec->args[2] & FSL_EDMA_EVEN_CH) && (i & 0x1))
continue;
if ((dma_spec->args[2] & FSL_EDMA_ODD_CH) && !(i & 0x1))
continue;
if (!b_chmux && i == dma_spec->args[0]) { if (!b_chmux && i == dma_spec->args[0]) {
chan = dma_get_slave_channel(chan); chan = dma_get_slave_channel(chan);
......
...@@ -805,7 +805,7 @@ fsl_qdma_irq_init(struct platform_device *pdev, ...@@ -805,7 +805,7 @@ fsl_qdma_irq_init(struct platform_device *pdev,
int i; int i;
int cpu; int cpu;
int ret; int ret;
char irq_name[20]; char irq_name[32];
fsl_qdma->error_irq = fsl_qdma->error_irq =
platform_get_irq_byname(pdev, "qdma-error"); platform_get_irq_byname(pdev, "qdma-error");
......
...@@ -165,7 +165,7 @@ static void idxd_cdev_dev_release(struct device *dev) ...@@ -165,7 +165,7 @@ static void idxd_cdev_dev_release(struct device *dev)
struct idxd_wq *wq = idxd_cdev->wq; struct idxd_wq *wq = idxd_cdev->wq;
cdev_ctx = &ictx[wq->idxd->data->type]; cdev_ctx = &ictx[wq->idxd->data->type];
ida_simple_remove(&cdev_ctx->minor_ida, idxd_cdev->minor); ida_free(&cdev_ctx->minor_ida, idxd_cdev->minor);
kfree(idxd_cdev); kfree(idxd_cdev);
} }
...@@ -463,7 +463,7 @@ int idxd_wq_add_cdev(struct idxd_wq *wq) ...@@ -463,7 +463,7 @@ int idxd_wq_add_cdev(struct idxd_wq *wq)
cdev = &idxd_cdev->cdev; cdev = &idxd_cdev->cdev;
dev = cdev_dev(idxd_cdev); dev = cdev_dev(idxd_cdev);
cdev_ctx = &ictx[wq->idxd->data->type]; cdev_ctx = &ictx[wq->idxd->data->type];
minor = ida_simple_get(&cdev_ctx->minor_ida, 0, MINORMASK, GFP_KERNEL); minor = ida_alloc_max(&cdev_ctx->minor_ida, MINORMASK, GFP_KERNEL);
if (minor < 0) { if (minor < 0) {
kfree(idxd_cdev); kfree(idxd_cdev);
return minor; return minor;
......
...@@ -807,6 +807,9 @@ static int idxd_device_evl_setup(struct idxd_device *idxd) ...@@ -807,6 +807,9 @@ static int idxd_device_evl_setup(struct idxd_device *idxd)
static void idxd_device_evl_free(struct idxd_device *idxd) static void idxd_device_evl_free(struct idxd_device *idxd)
{ {
void *evl_log;
unsigned int evl_log_size;
dma_addr_t evl_dma;
union gencfg_reg gencfg; union gencfg_reg gencfg;
union genctrl_reg genctrl; union genctrl_reg genctrl;
struct device *dev = &idxd->pdev->dev; struct device *dev = &idxd->pdev->dev;
...@@ -827,11 +830,15 @@ static void idxd_device_evl_free(struct idxd_device *idxd) ...@@ -827,11 +830,15 @@ static void idxd_device_evl_free(struct idxd_device *idxd)
iowrite64(0, idxd->reg_base + IDXD_EVLCFG_OFFSET); iowrite64(0, idxd->reg_base + IDXD_EVLCFG_OFFSET);
iowrite64(0, idxd->reg_base + IDXD_EVLCFG_OFFSET + 8); iowrite64(0, idxd->reg_base + IDXD_EVLCFG_OFFSET + 8);
dma_free_coherent(dev, evl->log_size, evl->log, evl->dma);
bitmap_free(evl->bmap); bitmap_free(evl->bmap);
evl_log = evl->log;
evl_log_size = evl->log_size;
evl_dma = evl->dma;
evl->log = NULL; evl->log = NULL;
evl->size = IDXD_EVL_SIZE_MIN; evl->size = IDXD_EVL_SIZE_MIN;
spin_unlock(&evl->lock); spin_unlock(&evl->lock);
dma_free_coherent(dev, evl_log_size, evl_log, evl_dma);
} }
static void idxd_group_config_write(struct idxd_group *group) static void idxd_group_config_write(struct idxd_group *group)
......
...@@ -421,9 +421,7 @@ struct sdma_desc { ...@@ -421,9 +421,7 @@ struct sdma_desc {
* @shp_addr: value for gReg[6] * @shp_addr: value for gReg[6]
* @per_addr: value for gReg[2] * @per_addr: value for gReg[2]
* @status: status of dma channel * @status: status of dma channel
* @context_loaded: ensure context is only loaded once
* @data: specific sdma interface structure * @data: specific sdma interface structure
* @bd_pool: dma_pool for bd
* @terminate_worker: used to call back into terminate work function * @terminate_worker: used to call back into terminate work function
* @terminated: terminated list * @terminated: terminated list
* @is_ram_script: flag for script in ram * @is_ram_script: flag for script in ram
...@@ -486,8 +484,6 @@ struct sdma_channel { ...@@ -486,8 +484,6 @@ struct sdma_channel {
* @num_script_addrs: Number of script addresses in this image * @num_script_addrs: Number of script addresses in this image
* @ram_code_start: offset of SDMA ram image in this firmware image * @ram_code_start: offset of SDMA ram image in this firmware image
* @ram_code_size: size of SDMA ram image * @ram_code_size: size of SDMA ram image
* @script_addrs: Stores the start address of the SDMA scripts
* (in SDMA memory space)
*/ */
struct sdma_firmware_header { struct sdma_firmware_header {
u32 magic; u32 magic;
......
This diff is collapsed.
...@@ -531,7 +531,7 @@ static int milbeaut_hdmac_probe(struct platform_device *pdev) ...@@ -531,7 +531,7 @@ static int milbeaut_hdmac_probe(struct platform_device *pdev)
return ret; return ret;
} }
static int milbeaut_hdmac_remove(struct platform_device *pdev) static void milbeaut_hdmac_remove(struct platform_device *pdev)
{ {
struct milbeaut_hdmac_device *mdev = platform_get_drvdata(pdev); struct milbeaut_hdmac_device *mdev = platform_get_drvdata(pdev);
struct dma_chan *chan; struct dma_chan *chan;
...@@ -546,16 +546,21 @@ static int milbeaut_hdmac_remove(struct platform_device *pdev) ...@@ -546,16 +546,21 @@ static int milbeaut_hdmac_remove(struct platform_device *pdev)
*/ */
list_for_each_entry(chan, &mdev->ddev.channels, device_node) { list_for_each_entry(chan, &mdev->ddev.channels, device_node) {
ret = dmaengine_terminate_sync(chan); ret = dmaengine_terminate_sync(chan);
if (ret) if (ret) {
return ret; /*
* This results in resource leakage and maybe also
* use-after-free errors as e.g. *mdev is kfreed.
*/
dev_alert(&pdev->dev, "Failed to terminate channel %d (%pe)\n",
chan->chan_id, ERR_PTR(ret));
return;
}
milbeaut_hdmac_free_chan_resources(chan); milbeaut_hdmac_free_chan_resources(chan);
} }
of_dma_controller_free(pdev->dev.of_node); of_dma_controller_free(pdev->dev.of_node);
dma_async_device_unregister(&mdev->ddev); dma_async_device_unregister(&mdev->ddev);
clk_disable_unprepare(mdev->clk); clk_disable_unprepare(mdev->clk);
return 0;
} }
static const struct of_device_id milbeaut_hdmac_match[] = { static const struct of_device_id milbeaut_hdmac_match[] = {
...@@ -566,7 +571,7 @@ MODULE_DEVICE_TABLE(of, milbeaut_hdmac_match); ...@@ -566,7 +571,7 @@ MODULE_DEVICE_TABLE(of, milbeaut_hdmac_match);
static struct platform_driver milbeaut_hdmac_driver = { static struct platform_driver milbeaut_hdmac_driver = {
.probe = milbeaut_hdmac_probe, .probe = milbeaut_hdmac_probe,
.remove = milbeaut_hdmac_remove, .remove_new = milbeaut_hdmac_remove,
.driver = { .driver = {
.name = "milbeaut-m10v-hdmac", .name = "milbeaut-m10v-hdmac",
.of_match_table = milbeaut_hdmac_match, .of_match_table = milbeaut_hdmac_match,
......
...@@ -368,7 +368,7 @@ static int milbeaut_xdmac_probe(struct platform_device *pdev) ...@@ -368,7 +368,7 @@ static int milbeaut_xdmac_probe(struct platform_device *pdev)
return ret; return ret;
} }
static int milbeaut_xdmac_remove(struct platform_device *pdev) static void milbeaut_xdmac_remove(struct platform_device *pdev)
{ {
struct milbeaut_xdmac_device *mdev = platform_get_drvdata(pdev); struct milbeaut_xdmac_device *mdev = platform_get_drvdata(pdev);
struct dma_chan *chan; struct dma_chan *chan;
...@@ -383,8 +383,15 @@ static int milbeaut_xdmac_remove(struct platform_device *pdev) ...@@ -383,8 +383,15 @@ static int milbeaut_xdmac_remove(struct platform_device *pdev)
*/ */
list_for_each_entry(chan, &mdev->ddev.channels, device_node) { list_for_each_entry(chan, &mdev->ddev.channels, device_node) {
ret = dmaengine_terminate_sync(chan); ret = dmaengine_terminate_sync(chan);
if (ret) if (ret) {
return ret; /*
* This results in resource leakage and maybe also
* use-after-free errors as e.g. *mdev is kfreed.
*/
dev_alert(&pdev->dev, "Failed to terminate channel %d (%pe)\n",
chan->chan_id, ERR_PTR(ret));
return;
}
milbeaut_xdmac_free_chan_resources(chan); milbeaut_xdmac_free_chan_resources(chan);
} }
...@@ -392,8 +399,6 @@ static int milbeaut_xdmac_remove(struct platform_device *pdev) ...@@ -392,8 +399,6 @@ static int milbeaut_xdmac_remove(struct platform_device *pdev)
dma_async_device_unregister(&mdev->ddev); dma_async_device_unregister(&mdev->ddev);
disable_xdmac(mdev); disable_xdmac(mdev);
return 0;
} }
static const struct of_device_id milbeaut_xdmac_match[] = { static const struct of_device_id milbeaut_xdmac_match[] = {
...@@ -404,7 +409,7 @@ MODULE_DEVICE_TABLE(of, milbeaut_xdmac_match); ...@@ -404,7 +409,7 @@ MODULE_DEVICE_TABLE(of, milbeaut_xdmac_match);
static struct platform_driver milbeaut_xdmac_driver = { static struct platform_driver milbeaut_xdmac_driver = {
.probe = milbeaut_xdmac_probe, .probe = milbeaut_xdmac_probe,
.remove = milbeaut_xdmac_remove, .remove_new = milbeaut_xdmac_remove,
.driver = { .driver = {
.name = "milbeaut-m10v-xdmac", .name = "milbeaut-m10v-xdmac",
.of_match_table = milbeaut_xdmac_match, .of_match_table = milbeaut_xdmac_match,
......
...@@ -1053,6 +1053,9 @@ static bool _trigger(struct pl330_thread *thrd) ...@@ -1053,6 +1053,9 @@ static bool _trigger(struct pl330_thread *thrd)
thrd->req_running = idx; thrd->req_running = idx;
if (desc->rqtype == DMA_MEM_TO_DEV || desc->rqtype == DMA_DEV_TO_MEM)
UNTIL(thrd, PL330_STATE_WFP);
return true; return true;
} }
......
...@@ -20,10 +20,13 @@ ...@@ -20,10 +20,13 @@
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_dma.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "sf-pdma.h" #include "sf-pdma.h"
#define PDMA_QUIRK_NO_STRICT_ORDERING BIT(0)
#ifndef readq #ifndef readq
static inline unsigned long long readq(void __iomem *addr) static inline unsigned long long readq(void __iomem *addr)
{ {
...@@ -65,7 +68,7 @@ static struct sf_pdma_desc *sf_pdma_alloc_desc(struct sf_pdma_chan *chan) ...@@ -65,7 +68,7 @@ static struct sf_pdma_desc *sf_pdma_alloc_desc(struct sf_pdma_chan *chan)
static void sf_pdma_fill_desc(struct sf_pdma_desc *desc, static void sf_pdma_fill_desc(struct sf_pdma_desc *desc,
u64 dst, u64 src, u64 size) u64 dst, u64 src, u64 size)
{ {
desc->xfer_type = PDMA_FULL_SPEED; desc->xfer_type = desc->chan->pdma->transfer_type;
desc->xfer_size = size; desc->xfer_size = size;
desc->dst_addr = dst; desc->dst_addr = dst;
desc->src_addr = src; desc->src_addr = src;
...@@ -492,6 +495,7 @@ static void sf_pdma_setup_chans(struct sf_pdma *pdma) ...@@ -492,6 +495,7 @@ static void sf_pdma_setup_chans(struct sf_pdma *pdma)
static int sf_pdma_probe(struct platform_device *pdev) static int sf_pdma_probe(struct platform_device *pdev)
{ {
const struct sf_pdma_driver_platdata *ddata;
struct sf_pdma *pdma; struct sf_pdma *pdma;
int ret, n_chans; int ret, n_chans;
const enum dma_slave_buswidth widths = const enum dma_slave_buswidth widths =
...@@ -517,6 +521,14 @@ static int sf_pdma_probe(struct platform_device *pdev) ...@@ -517,6 +521,14 @@ static int sf_pdma_probe(struct platform_device *pdev)
pdma->n_chans = n_chans; pdma->n_chans = n_chans;
pdma->transfer_type = PDMA_FULL_SPEED | PDMA_STRICT_ORDERING;
ddata = device_get_match_data(&pdev->dev);
if (ddata) {
if (ddata->quirks & PDMA_QUIRK_NO_STRICT_ORDERING)
pdma->transfer_type &= ~PDMA_STRICT_ORDERING;
}
pdma->membase = devm_platform_ioremap_resource(pdev, 0); pdma->membase = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pdma->membase)) if (IS_ERR(pdma->membase))
return PTR_ERR(pdma->membase); return PTR_ERR(pdma->membase);
...@@ -563,7 +575,20 @@ static int sf_pdma_probe(struct platform_device *pdev) ...@@ -563,7 +575,20 @@ static int sf_pdma_probe(struct platform_device *pdev)
return ret; return ret;
} }
ret = of_dma_controller_register(pdev->dev.of_node,
of_dma_xlate_by_chan_id, pdma);
if (ret < 0) {
dev_err(&pdev->dev,
"Can't register SiFive Platform OF_DMA. (%d)\n", ret);
goto err_unregister;
}
return 0; return 0;
err_unregister:
dma_async_device_unregister(&pdma->dma_dev);
return ret;
} }
static void sf_pdma_remove(struct platform_device *pdev) static void sf_pdma_remove(struct platform_device *pdev)
...@@ -583,12 +608,25 @@ static void sf_pdma_remove(struct platform_device *pdev) ...@@ -583,12 +608,25 @@ static void sf_pdma_remove(struct platform_device *pdev)
tasklet_kill(&ch->err_tasklet); tasklet_kill(&ch->err_tasklet);
} }
if (pdev->dev.of_node)
of_dma_controller_free(pdev->dev.of_node);
dma_async_device_unregister(&pdma->dma_dev); dma_async_device_unregister(&pdma->dma_dev);
} }
static const struct sf_pdma_driver_platdata mpfs_pdma = {
.quirks = PDMA_QUIRK_NO_STRICT_ORDERING,
};
static const struct of_device_id sf_pdma_dt_ids[] = { static const struct of_device_id sf_pdma_dt_ids[] = {
{ .compatible = "sifive,fu540-c000-pdma" }, {
{ .compatible = "sifive,pdma0" }, .compatible = "sifive,fu540-c000-pdma",
}, {
.compatible = "sifive,pdma0",
}, {
.compatible = "microchip,mpfs-pdma",
.data = &mpfs_pdma,
},
{}, {},
}; };
MODULE_DEVICE_TABLE(of, sf_pdma_dt_ids); MODULE_DEVICE_TABLE(of, sf_pdma_dt_ids);
......
...@@ -48,7 +48,8 @@ ...@@ -48,7 +48,8 @@
#define PDMA_ERR_STATUS_MASK GENMASK(31, 31) #define PDMA_ERR_STATUS_MASK GENMASK(31, 31)
/* Transfer Type */ /* Transfer Type */
#define PDMA_FULL_SPEED 0xFF000008 #define PDMA_FULL_SPEED 0xFF000000
#define PDMA_STRICT_ORDERING BIT(3)
/* Error Recovery */ /* Error Recovery */
#define MAX_RETRY 1 #define MAX_RETRY 1
...@@ -112,8 +113,13 @@ struct sf_pdma { ...@@ -112,8 +113,13 @@ struct sf_pdma {
struct dma_device dma_dev; struct dma_device dma_dev;
void __iomem *membase; void __iomem *membase;
void __iomem *mappedbase; void __iomem *mappedbase;
u32 transfer_type;
u32 n_chans; u32 n_chans;
struct sf_pdma_chan chans[] __counted_by(n_chans); struct sf_pdma_chan chans[] __counted_by(n_chans);
}; };
struct sf_pdma_driver_platdata {
u32 quirks;
};
#endif /* _SF_PDMA_H */ #endif /* _SF_PDMA_H */
...@@ -755,11 +755,11 @@ static struct dma_chan *rz_dmac_of_xlate(struct of_phandle_args *dma_spec, ...@@ -755,11 +755,11 @@ static struct dma_chan *rz_dmac_of_xlate(struct of_phandle_args *dma_spec,
static int rz_dmac_chan_probe(struct rz_dmac *dmac, static int rz_dmac_chan_probe(struct rz_dmac *dmac,
struct rz_dmac_chan *channel, struct rz_dmac_chan *channel,
unsigned int index) u8 index)
{ {
struct platform_device *pdev = to_platform_device(dmac->dev); struct platform_device *pdev = to_platform_device(dmac->dev);
struct rz_lmdesc *lmdesc; struct rz_lmdesc *lmdesc;
char pdev_irqname[5]; char pdev_irqname[6];
char *irqname; char *irqname;
int ret; int ret;
...@@ -767,7 +767,7 @@ static int rz_dmac_chan_probe(struct rz_dmac *dmac, ...@@ -767,7 +767,7 @@ static int rz_dmac_chan_probe(struct rz_dmac *dmac,
channel->mid_rid = -EINVAL; channel->mid_rid = -EINVAL;
/* Request the channel interrupt. */ /* Request the channel interrupt. */
sprintf(pdev_irqname, "ch%u", index); scnprintf(pdev_irqname, sizeof(pdev_irqname), "ch%u", index);
channel->irq = platform_get_irq_byname(pdev, pdev_irqname); channel->irq = platform_get_irq_byname(pdev, pdev_irqname);
if (channel->irq < 0) if (channel->irq < 0)
return channel->irq; return channel->irq;
...@@ -845,9 +845,9 @@ static int rz_dmac_probe(struct platform_device *pdev) ...@@ -845,9 +845,9 @@ static int rz_dmac_probe(struct platform_device *pdev)
struct dma_device *engine; struct dma_device *engine;
struct rz_dmac *dmac; struct rz_dmac *dmac;
int channel_num; int channel_num;
unsigned int i;
int ret; int ret;
int irq; int irq;
u8 i;
dmac = devm_kzalloc(&pdev->dev, sizeof(*dmac), GFP_KERNEL); dmac = devm_kzalloc(&pdev->dev, sizeof(*dmac), GFP_KERNEL);
if (!dmac) if (!dmac)
......
...@@ -25,7 +25,7 @@ struct sh_dmae_chan { ...@@ -25,7 +25,7 @@ struct sh_dmae_chan {
const struct sh_dmae_slave_config *config; /* Slave DMA configuration */ const struct sh_dmae_slave_config *config; /* Slave DMA configuration */
int xmit_shift; /* log_2(bytes_per_xfer) */ int xmit_shift; /* log_2(bytes_per_xfer) */
void __iomem *base; void __iomem *base;
char dev_id[16]; /* unique name per DMAC of channel */ char dev_id[32]; /* unique name per DMAC of channel */
int pm_error; int pm_error;
dma_addr_t slave_addr; dma_addr_t slave_addr;
}; };
......
...@@ -706,10 +706,10 @@ static const struct dev_pm_ops usb_dmac_pm = { ...@@ -706,10 +706,10 @@ static const struct dev_pm_ops usb_dmac_pm = {
static int usb_dmac_chan_probe(struct usb_dmac *dmac, static int usb_dmac_chan_probe(struct usb_dmac *dmac,
struct usb_dmac_chan *uchan, struct usb_dmac_chan *uchan,
unsigned int index) u8 index)
{ {
struct platform_device *pdev = to_platform_device(dmac->dev); struct platform_device *pdev = to_platform_device(dmac->dev);
char pdev_irqname[5]; char pdev_irqname[6];
char *irqname; char *irqname;
int ret; int ret;
...@@ -717,7 +717,7 @@ static int usb_dmac_chan_probe(struct usb_dmac *dmac, ...@@ -717,7 +717,7 @@ static int usb_dmac_chan_probe(struct usb_dmac *dmac,
uchan->iomem = dmac->iomem + USB_DMAC_CHAN_OFFSET(index); uchan->iomem = dmac->iomem + USB_DMAC_CHAN_OFFSET(index);
/* Request the channel interrupt. */ /* Request the channel interrupt. */
sprintf(pdev_irqname, "ch%u", index); scnprintf(pdev_irqname, sizeof(pdev_irqname), "ch%u", index);
uchan->irq = platform_get_irq_byname(pdev, pdev_irqname); uchan->irq = platform_get_irq_byname(pdev, pdev_irqname);
if (uchan->irq < 0) if (uchan->irq < 0)
return -ENODEV; return -ENODEV;
...@@ -768,8 +768,8 @@ static int usb_dmac_probe(struct platform_device *pdev) ...@@ -768,8 +768,8 @@ static int usb_dmac_probe(struct platform_device *pdev)
const enum dma_slave_buswidth widths = USB_DMAC_SLAVE_BUSWIDTH; const enum dma_slave_buswidth widths = USB_DMAC_SLAVE_BUSWIDTH;
struct dma_device *engine; struct dma_device *engine;
struct usb_dmac *dmac; struct usb_dmac *dmac;
unsigned int i;
int ret; int ret;
u8 i;
dmac = devm_kzalloc(&pdev->dev, sizeof(*dmac), GFP_KERNEL); dmac = devm_kzalloc(&pdev->dev, sizeof(*dmac), GFP_KERNEL);
if (!dmac) if (!dmac)
...@@ -869,7 +869,7 @@ static void usb_dmac_chan_remove(struct usb_dmac *dmac, ...@@ -869,7 +869,7 @@ static void usb_dmac_chan_remove(struct usb_dmac *dmac,
static void usb_dmac_remove(struct platform_device *pdev) static void usb_dmac_remove(struct platform_device *pdev)
{ {
struct usb_dmac *dmac = platform_get_drvdata(pdev); struct usb_dmac *dmac = platform_get_drvdata(pdev);
int i; u8 i;
for (i = 0; i < dmac->n_channels; ++i) for (i = 0; i < dmac->n_channels; ++i)
usb_dmac_chan_remove(dmac, &dmac->channels[i]); usb_dmac_chan_remove(dmac, &dmac->channels[i]);
......
...@@ -31,13 +31,11 @@ ...@@ -31,13 +31,11 @@
/** /**
* struct stedma40_platform_data - Configuration struct for the dma device. * struct stedma40_platform_data - Configuration struct for the dma device.
* *
* @dev_tx: mapping between destination event line and io address
* @dev_rx: mapping between source event line and io address
* @disabled_channels: A vector, ending with -1, that marks physical channels * @disabled_channels: A vector, ending with -1, that marks physical channels
* that are for different reasons not available for the driver. * that are for different reasons not available for the driver.
* @soft_lli_chans: A vector, that marks physical channels will use LLI by SW * @soft_lli_chans: A vector, that marks physical channels will use LLI by SW
* which avoids HW bug that exists in some versions of the controller. * which avoids HW bug that exists in some versions of the controller.
* SoftLLI introduces relink overhead that could impact performace for * SoftLLI introduces relink overhead that could impact performance for
* certain use cases. * certain use cases.
* @num_of_soft_lli_chans: The number of channels that needs to be configured * @num_of_soft_lli_chans: The number of channels that needs to be configured
* to use SoftLLI. * to use SoftLLI.
...@@ -184,7 +182,7 @@ static __maybe_unused u32 d40_backup_regs[] = { ...@@ -184,7 +182,7 @@ static __maybe_unused u32 d40_backup_regs[] = {
/* /*
* since 9540 and 8540 has the same HW revision * since 9540 and 8540 has the same HW revision
* use v4a for 9540 or ealier * use v4a for 9540 or earlier
* use v4b for 8540 or later * use v4b for 8540 or later
* HW revision: * HW revision:
* DB8500ed has revision 0 * DB8500ed has revision 0
...@@ -411,7 +409,7 @@ struct d40_desc { ...@@ -411,7 +409,7 @@ struct d40_desc {
* *
* @base: The virtual address of LCLA. 18 bit aligned. * @base: The virtual address of LCLA. 18 bit aligned.
* @dma_addr: DMA address, if mapped * @dma_addr: DMA address, if mapped
* @base_unaligned: The orignal kmalloc pointer, if kmalloc is used. * @base_unaligned: The original kmalloc pointer, if kmalloc is used.
* This pointer is only there for clean-up on error. * This pointer is only there for clean-up on error.
* @pages: The number of pages needed for all physical channels. * @pages: The number of pages needed for all physical channels.
* Only used later for clean-up on error * Only used later for clean-up on error
...@@ -1655,7 +1653,7 @@ static void dma_tasklet(struct tasklet_struct *t) ...@@ -1655,7 +1653,7 @@ static void dma_tasklet(struct tasklet_struct *t)
return; return;
check_pending_tx: check_pending_tx:
/* Rescue manouver if receiving double interrupts */ /* Rescue maneuver if receiving double interrupts */
if (d40c->pending_tx > 0) if (d40c->pending_tx > 0)
d40c->pending_tx--; d40c->pending_tx--;
spin_unlock_irqrestore(&d40c->lock, flags); spin_unlock_irqrestore(&d40c->lock, flags);
...@@ -3412,7 +3410,7 @@ static int __init d40_lcla_allocate(struct d40_base *base) ...@@ -3412,7 +3410,7 @@ static int __init d40_lcla_allocate(struct d40_base *base)
base->lcla_pool.base = (void *)page_list[i]; base->lcla_pool.base = (void *)page_list[i];
} else { } else {
/* /*
* After many attempts and no succees with finding the correct * After many attempts and no success with finding the correct
* alignment, try with allocating a big buffer. * alignment, try with allocating a big buffer.
*/ */
dev_warn(base->dev, dev_warn(base->dev,
......
...@@ -153,6 +153,7 @@ struct tegra_adma { ...@@ -153,6 +153,7 @@ struct tegra_adma {
void __iomem *base_addr; void __iomem *base_addr;
struct clk *ahub_clk; struct clk *ahub_clk;
unsigned int nr_channels; unsigned int nr_channels;
unsigned long *dma_chan_mask;
unsigned long rx_requests_reserved; unsigned long rx_requests_reserved;
unsigned long tx_requests_reserved; unsigned long tx_requests_reserved;
...@@ -741,6 +742,10 @@ static int __maybe_unused tegra_adma_runtime_suspend(struct device *dev) ...@@ -741,6 +742,10 @@ static int __maybe_unused tegra_adma_runtime_suspend(struct device *dev)
for (i = 0; i < tdma->nr_channels; i++) { for (i = 0; i < tdma->nr_channels; i++) {
tdc = &tdma->channels[i]; tdc = &tdma->channels[i];
/* skip for reserved channels */
if (!tdc->tdma)
continue;
ch_reg = &tdc->ch_regs; ch_reg = &tdc->ch_regs;
ch_reg->cmd = tdma_ch_read(tdc, ADMA_CH_CMD); ch_reg->cmd = tdma_ch_read(tdc, ADMA_CH_CMD);
/* skip if channel is not active */ /* skip if channel is not active */
...@@ -779,6 +784,9 @@ static int __maybe_unused tegra_adma_runtime_resume(struct device *dev) ...@@ -779,6 +784,9 @@ static int __maybe_unused tegra_adma_runtime_resume(struct device *dev)
for (i = 0; i < tdma->nr_channels; i++) { for (i = 0; i < tdma->nr_channels; i++) {
tdc = &tdma->channels[i]; tdc = &tdma->channels[i];
/* skip for reserved channels */
if (!tdc->tdma)
continue;
ch_reg = &tdc->ch_regs; ch_reg = &tdc->ch_regs;
/* skip if channel was not active earlier */ /* skip if channel was not active earlier */
if (!ch_reg->cmd) if (!ch_reg->cmd)
...@@ -867,10 +875,31 @@ static int tegra_adma_probe(struct platform_device *pdev) ...@@ -867,10 +875,31 @@ static int tegra_adma_probe(struct platform_device *pdev)
return PTR_ERR(tdma->ahub_clk); return PTR_ERR(tdma->ahub_clk);
} }
tdma->dma_chan_mask = devm_kzalloc(&pdev->dev,
BITS_TO_LONGS(tdma->nr_channels) * sizeof(unsigned long),
GFP_KERNEL);
if (!tdma->dma_chan_mask)
return -ENOMEM;
/* Enable all channels by default */
bitmap_fill(tdma->dma_chan_mask, tdma->nr_channels);
ret = of_property_read_u32_array(pdev->dev.of_node, "dma-channel-mask",
(u32 *)tdma->dma_chan_mask,
BITS_TO_U32(tdma->nr_channels));
if (ret < 0 && (ret != -EINVAL)) {
dev_err(&pdev->dev, "dma-channel-mask is not complete.\n");
return ret;
}
INIT_LIST_HEAD(&tdma->dma_dev.channels); INIT_LIST_HEAD(&tdma->dma_dev.channels);
for (i = 0; i < tdma->nr_channels; i++) { for (i = 0; i < tdma->nr_channels; i++) {
struct tegra_adma_chan *tdc = &tdma->channels[i]; struct tegra_adma_chan *tdc = &tdma->channels[i];
/* skip for reserved channels */
if (!test_bit(i, tdma->dma_chan_mask))
continue;
tdc->chan_addr = tdma->base_addr + cdata->ch_base_offset tdc->chan_addr = tdma->base_addr + cdata->ch_base_offset
+ (cdata->ch_reg_size * i); + (cdata->ch_reg_size * i);
...@@ -957,8 +986,10 @@ static void tegra_adma_remove(struct platform_device *pdev) ...@@ -957,8 +986,10 @@ static void tegra_adma_remove(struct platform_device *pdev)
of_dma_controller_free(pdev->dev.of_node); of_dma_controller_free(pdev->dev.of_node);
dma_async_device_unregister(&tdma->dma_dev); dma_async_device_unregister(&tdma->dma_dev);
for (i = 0; i < tdma->nr_channels; ++i) for (i = 0; i < tdma->nr_channels; ++i) {
irq_dispose_mapping(tdma->channels[i].irq); if (tdma->channels[i].irq)
irq_dispose_mapping(tdma->channels[i].irq);
}
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
} }
......
...@@ -12,6 +12,7 @@ k3-psil-lib-objs := k3-psil.o \ ...@@ -12,6 +12,7 @@ k3-psil-lib-objs := k3-psil.o \
k3-psil-j721s2.o \ k3-psil-j721s2.o \
k3-psil-am62.o \ k3-psil-am62.o \
k3-psil-am62a.o \ k3-psil-am62a.o \
k3-psil-j784s4.o k3-psil-j784s4.o \
k3-psil-am62p.o
obj-$(CONFIG_TI_K3_PSIL) += k3-psil-lib.o obj-$(CONFIG_TI_K3_PSIL) += k3-psil-lib.o
obj-$(CONFIG_TI_DMA_CROSSBAR) += dma-crossbar.o obj-$(CONFIG_TI_DMA_CROSSBAR) += dma-crossbar.o
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com
*/
#include <linux/kernel.h>
#include "k3-psil-priv.h"
#define PSIL_PDMA_XY_TR(x) \
{ \
.thread_id = x, \
.ep_config = { \
.ep_type = PSIL_EP_PDMA_XY, \
.mapped_channel_id = -1, \
.default_flow_id = -1, \
}, \
}
#define PSIL_PDMA_XY_PKT(x) \
{ \
.thread_id = x, \
.ep_config = { \
.ep_type = PSIL_EP_PDMA_XY, \
.mapped_channel_id = -1, \
.default_flow_id = -1, \
.pkt_mode = 1, \
}, \
}
#define PSIL_ETHERNET(x, ch, flow_base, flow_cnt) \
{ \
.thread_id = x, \
.ep_config = { \
.ep_type = PSIL_EP_NATIVE, \
.pkt_mode = 1, \
.needs_epib = 1, \
.psd_size = 16, \
.mapped_channel_id = ch, \
.flow_start = flow_base, \
.flow_num = flow_cnt, \
.default_flow_id = flow_base, \
}, \
}
#define PSIL_SAUL(x, ch, flow_base, flow_cnt, default_flow, tx) \
{ \
.thread_id = x, \
.ep_config = { \
.ep_type = PSIL_EP_NATIVE, \
.pkt_mode = 1, \
.needs_epib = 1, \
.psd_size = 64, \
.mapped_channel_id = ch, \
.flow_start = flow_base, \
.flow_num = flow_cnt, \
.default_flow_id = default_flow, \
.notdpkt = tx, \
}, \
}
#define PSIL_PDMA_MCASP(x) \
{ \
.thread_id = x, \
.ep_config = { \
.ep_type = PSIL_EP_PDMA_XY, \
.pdma_acc32 = 1, \
.pdma_burst = 1, \
}, \
}
#define PSIL_CSI2RX(x) \
{ \
.thread_id = x, \
.ep_config = { \
.ep_type = PSIL_EP_NATIVE, \
}, \
}
/* PSI-L source thread IDs, used for RX (DMA_DEV_TO_MEM) */
static struct psil_ep am62p_src_ep_map[] = {
/* SAUL */
PSIL_SAUL(0x7504, 20, 35, 8, 35, 0),
PSIL_SAUL(0x7505, 21, 35, 8, 36, 0),
PSIL_SAUL(0x7506, 22, 43, 8, 43, 0),
PSIL_SAUL(0x7507, 23, 43, 8, 44, 0),
/* PDMA_MAIN0 - SPI0-2 */
PSIL_PDMA_XY_PKT(0x4300),
PSIL_PDMA_XY_PKT(0x4301),
PSIL_PDMA_XY_PKT(0x4302),
PSIL_PDMA_XY_PKT(0x4303),
PSIL_PDMA_XY_PKT(0x4304),
PSIL_PDMA_XY_PKT(0x4305),
PSIL_PDMA_XY_PKT(0x4306),
PSIL_PDMA_XY_PKT(0x4307),
PSIL_PDMA_XY_PKT(0x4308),
PSIL_PDMA_XY_PKT(0x4309),
PSIL_PDMA_XY_PKT(0x430a),
PSIL_PDMA_XY_PKT(0x430b),
/* PDMA_MAIN1 - UART0-6 */
PSIL_PDMA_XY_PKT(0x4400),
PSIL_PDMA_XY_PKT(0x4401),
PSIL_PDMA_XY_PKT(0x4402),
PSIL_PDMA_XY_PKT(0x4403),
PSIL_PDMA_XY_PKT(0x4404),
PSIL_PDMA_XY_PKT(0x4405),
PSIL_PDMA_XY_PKT(0x4406),
/* PDMA_MAIN2 - MCASP0-2 */
PSIL_PDMA_MCASP(0x4500),
PSIL_PDMA_MCASP(0x4501),
PSIL_PDMA_MCASP(0x4502),
/* CPSW3G */
PSIL_ETHERNET(0x4600, 19, 19, 16),
/* CSI2RX */
PSIL_CSI2RX(0x5000),
PSIL_CSI2RX(0x5001),
PSIL_CSI2RX(0x5002),
PSIL_CSI2RX(0x5003),
PSIL_CSI2RX(0x5004),
PSIL_CSI2RX(0x5005),
PSIL_CSI2RX(0x5006),
PSIL_CSI2RX(0x5007),
PSIL_CSI2RX(0x5008),
PSIL_CSI2RX(0x5009),
PSIL_CSI2RX(0x500a),
PSIL_CSI2RX(0x500b),
PSIL_CSI2RX(0x500c),
PSIL_CSI2RX(0x500d),
PSIL_CSI2RX(0x500e),
PSIL_CSI2RX(0x500f),
PSIL_CSI2RX(0x5010),
PSIL_CSI2RX(0x5011),
PSIL_CSI2RX(0x5012),
PSIL_CSI2RX(0x5013),
PSIL_CSI2RX(0x5014),
PSIL_CSI2RX(0x5015),
PSIL_CSI2RX(0x5016),
PSIL_CSI2RX(0x5017),
PSIL_CSI2RX(0x5018),
PSIL_CSI2RX(0x5019),
PSIL_CSI2RX(0x501a),
PSIL_CSI2RX(0x501b),
PSIL_CSI2RX(0x501c),
PSIL_CSI2RX(0x501d),
PSIL_CSI2RX(0x501e),
PSIL_CSI2RX(0x501f),
PSIL_CSI2RX(0x5000),
PSIL_CSI2RX(0x5001),
PSIL_CSI2RX(0x5002),
PSIL_CSI2RX(0x5003),
PSIL_CSI2RX(0x5004),
PSIL_CSI2RX(0x5005),
PSIL_CSI2RX(0x5006),
PSIL_CSI2RX(0x5007),
PSIL_CSI2RX(0x5008),
PSIL_CSI2RX(0x5009),
PSIL_CSI2RX(0x500a),
PSIL_CSI2RX(0x500b),
PSIL_CSI2RX(0x500c),
PSIL_CSI2RX(0x500d),
PSIL_CSI2RX(0x500e),
PSIL_CSI2RX(0x500f),
PSIL_CSI2RX(0x5010),
PSIL_CSI2RX(0x5011),
PSIL_CSI2RX(0x5012),
PSIL_CSI2RX(0x5013),
PSIL_CSI2RX(0x5014),
PSIL_CSI2RX(0x5015),
PSIL_CSI2RX(0x5016),
PSIL_CSI2RX(0x5017),
PSIL_CSI2RX(0x5018),
PSIL_CSI2RX(0x5019),
PSIL_CSI2RX(0x501a),
PSIL_CSI2RX(0x501b),
PSIL_CSI2RX(0x501c),
PSIL_CSI2RX(0x501d),
PSIL_CSI2RX(0x501e),
PSIL_CSI2RX(0x501f),
/* CSIRX 1-3 (only for J722S) */
PSIL_CSI2RX(0x5100),
PSIL_CSI2RX(0x5101),
PSIL_CSI2RX(0x5102),
PSIL_CSI2RX(0x5103),
PSIL_CSI2RX(0x5104),
PSIL_CSI2RX(0x5105),
PSIL_CSI2RX(0x5106),
PSIL_CSI2RX(0x5107),
PSIL_CSI2RX(0x5108),
PSIL_CSI2RX(0x5109),
PSIL_CSI2RX(0x510a),
PSIL_CSI2RX(0x510b),
PSIL_CSI2RX(0x510c),
PSIL_CSI2RX(0x510d),
PSIL_CSI2RX(0x510e),
PSIL_CSI2RX(0x510f),
PSIL_CSI2RX(0x5110),
PSIL_CSI2RX(0x5111),
PSIL_CSI2RX(0x5112),
PSIL_CSI2RX(0x5113),
PSIL_CSI2RX(0x5114),
PSIL_CSI2RX(0x5115),
PSIL_CSI2RX(0x5116),
PSIL_CSI2RX(0x5117),
PSIL_CSI2RX(0x5118),
PSIL_CSI2RX(0x5119),
PSIL_CSI2RX(0x511a),
PSIL_CSI2RX(0x511b),
PSIL_CSI2RX(0x511c),
PSIL_CSI2RX(0x511d),
PSIL_CSI2RX(0x511e),
PSIL_CSI2RX(0x511f),
PSIL_CSI2RX(0x5200),
PSIL_CSI2RX(0x5201),
PSIL_CSI2RX(0x5202),
PSIL_CSI2RX(0x5203),
PSIL_CSI2RX(0x5204),
PSIL_CSI2RX(0x5205),
PSIL_CSI2RX(0x5206),
PSIL_CSI2RX(0x5207),
PSIL_CSI2RX(0x5208),
PSIL_CSI2RX(0x5209),
PSIL_CSI2RX(0x520a),
PSIL_CSI2RX(0x520b),
PSIL_CSI2RX(0x520c),
PSIL_CSI2RX(0x520d),
PSIL_CSI2RX(0x520e),
PSIL_CSI2RX(0x520f),
PSIL_CSI2RX(0x5210),
PSIL_CSI2RX(0x5211),
PSIL_CSI2RX(0x5212),
PSIL_CSI2RX(0x5213),
PSIL_CSI2RX(0x5214),
PSIL_CSI2RX(0x5215),
PSIL_CSI2RX(0x5216),
PSIL_CSI2RX(0x5217),
PSIL_CSI2RX(0x5218),
PSIL_CSI2RX(0x5219),
PSIL_CSI2RX(0x521a),
PSIL_CSI2RX(0x521b),
PSIL_CSI2RX(0x521c),
PSIL_CSI2RX(0x521d),
PSIL_CSI2RX(0x521e),
PSIL_CSI2RX(0x521f),
PSIL_CSI2RX(0x5300),
PSIL_CSI2RX(0x5301),
PSIL_CSI2RX(0x5302),
PSIL_CSI2RX(0x5303),
PSIL_CSI2RX(0x5304),
PSIL_CSI2RX(0x5305),
PSIL_CSI2RX(0x5306),
PSIL_CSI2RX(0x5307),
PSIL_CSI2RX(0x5308),
PSIL_CSI2RX(0x5309),
PSIL_CSI2RX(0x530a),
PSIL_CSI2RX(0x530b),
PSIL_CSI2RX(0x530c),
PSIL_CSI2RX(0x530d),
PSIL_CSI2RX(0x530e),
PSIL_CSI2RX(0x530f),
PSIL_CSI2RX(0x5310),
PSIL_CSI2RX(0x5311),
PSIL_CSI2RX(0x5312),
PSIL_CSI2RX(0x5313),
PSIL_CSI2RX(0x5314),
PSIL_CSI2RX(0x5315),
PSIL_CSI2RX(0x5316),
PSIL_CSI2RX(0x5317),
PSIL_CSI2RX(0x5318),
PSIL_CSI2RX(0x5319),
PSIL_CSI2RX(0x531a),
PSIL_CSI2RX(0x531b),
PSIL_CSI2RX(0x531c),
PSIL_CSI2RX(0x531d),
PSIL_CSI2RX(0x531e),
PSIL_CSI2RX(0x531f),
};
/* PSI-L destination thread IDs, used for TX (DMA_MEM_TO_DEV) */
static struct psil_ep am62p_dst_ep_map[] = {
/* SAUL */
PSIL_SAUL(0xf500, 27, 83, 8, 83, 1),
PSIL_SAUL(0xf501, 28, 91, 8, 91, 1),
/* PDMA_MAIN0 - SPI0-2 */
PSIL_PDMA_XY_PKT(0xc300),
PSIL_PDMA_XY_PKT(0xc301),
PSIL_PDMA_XY_PKT(0xc302),
PSIL_PDMA_XY_PKT(0xc303),
PSIL_PDMA_XY_PKT(0xc304),
PSIL_PDMA_XY_PKT(0xc305),
PSIL_PDMA_XY_PKT(0xc306),
PSIL_PDMA_XY_PKT(0xc307),
PSIL_PDMA_XY_PKT(0xc308),
PSIL_PDMA_XY_PKT(0xc309),
PSIL_PDMA_XY_PKT(0xc30a),
PSIL_PDMA_XY_PKT(0xc30b),
/* PDMA_MAIN1 - UART0-6 */
PSIL_PDMA_XY_PKT(0xc400),
PSIL_PDMA_XY_PKT(0xc401),
PSIL_PDMA_XY_PKT(0xc402),
PSIL_PDMA_XY_PKT(0xc403),
PSIL_PDMA_XY_PKT(0xc404),
PSIL_PDMA_XY_PKT(0xc405),
PSIL_PDMA_XY_PKT(0xc406),
/* PDMA_MAIN2 - MCASP0-2 */
PSIL_PDMA_MCASP(0xc500),
PSIL_PDMA_MCASP(0xc501),
PSIL_PDMA_MCASP(0xc502),
/* CPSW3G */
PSIL_ETHERNET(0xc600, 19, 19, 8),
PSIL_ETHERNET(0xc601, 20, 27, 8),
PSIL_ETHERNET(0xc602, 21, 35, 8),
PSIL_ETHERNET(0xc603, 22, 43, 8),
PSIL_ETHERNET(0xc604, 23, 51, 8),
PSIL_ETHERNET(0xc605, 24, 59, 8),
PSIL_ETHERNET(0xc606, 25, 67, 8),
PSIL_ETHERNET(0xc607, 26, 75, 8),
};
struct psil_ep_map am62p_ep_map = {
.name = "am62p",
.src = am62p_src_ep_map,
.src_count = ARRAY_SIZE(am62p_src_ep_map),
.dst = am62p_dst_ep_map,
.dst_count = ARRAY_SIZE(am62p_dst_ep_map),
};
...@@ -45,5 +45,6 @@ extern struct psil_ep_map j721s2_ep_map; ...@@ -45,5 +45,6 @@ extern struct psil_ep_map j721s2_ep_map;
extern struct psil_ep_map am62_ep_map; extern struct psil_ep_map am62_ep_map;
extern struct psil_ep_map am62a_ep_map; extern struct psil_ep_map am62a_ep_map;
extern struct psil_ep_map j784s4_ep_map; extern struct psil_ep_map j784s4_ep_map;
extern struct psil_ep_map am62p_ep_map;
#endif /* K3_PSIL_PRIV_H_ */ #endif /* K3_PSIL_PRIV_H_ */
...@@ -26,6 +26,8 @@ static const struct soc_device_attribute k3_soc_devices[] = { ...@@ -26,6 +26,8 @@ static const struct soc_device_attribute k3_soc_devices[] = {
{ .family = "AM62X", .data = &am62_ep_map }, { .family = "AM62X", .data = &am62_ep_map },
{ .family = "AM62AX", .data = &am62a_ep_map }, { .family = "AM62AX", .data = &am62a_ep_map },
{ .family = "J784S4", .data = &j784s4_ep_map }, { .family = "J784S4", .data = &j784s4_ep_map },
{ .family = "AM62PX", .data = &am62p_ep_map },
{ .family = "J722S", .data = &am62p_ep_map },
{ /* sentinel */ } { /* sentinel */ }
}; };
......
...@@ -4441,6 +4441,8 @@ static const struct soc_device_attribute k3_soc_devices[] = { ...@@ -4441,6 +4441,8 @@ static const struct soc_device_attribute k3_soc_devices[] = {
{ .family = "AM62X", .data = &am64_soc_data }, { .family = "AM62X", .data = &am64_soc_data },
{ .family = "AM62AX", .data = &am64_soc_data }, { .family = "AM62AX", .data = &am64_soc_data },
{ .family = "J784S4", .data = &j721e_soc_data }, { .family = "J784S4", .data = &j721e_soc_data },
{ .family = "AM62PX", .data = &am64_soc_data },
{ .family = "J722S", .data = &am64_soc_data },
{ /* sentinel */ } { /* sentinel */ }
}; };
......
...@@ -453,7 +453,7 @@ static int uniphier_mdmac_probe(struct platform_device *pdev) ...@@ -453,7 +453,7 @@ static int uniphier_mdmac_probe(struct platform_device *pdev)
return ret; return ret;
} }
static int uniphier_mdmac_remove(struct platform_device *pdev) static void uniphier_mdmac_remove(struct platform_device *pdev)
{ {
struct uniphier_mdmac_device *mdev = platform_get_drvdata(pdev); struct uniphier_mdmac_device *mdev = platform_get_drvdata(pdev);
struct dma_chan *chan; struct dma_chan *chan;
...@@ -468,16 +468,21 @@ static int uniphier_mdmac_remove(struct platform_device *pdev) ...@@ -468,16 +468,21 @@ static int uniphier_mdmac_remove(struct platform_device *pdev)
*/ */
list_for_each_entry(chan, &mdev->ddev.channels, device_node) { list_for_each_entry(chan, &mdev->ddev.channels, device_node) {
ret = dmaengine_terminate_sync(chan); ret = dmaengine_terminate_sync(chan);
if (ret) if (ret) {
return ret; /*
* This results in resource leakage and maybe also
* use-after-free errors as e.g. *mdev is kfreed.
*/
dev_alert(&pdev->dev, "Failed to terminate channel %d (%pe)\n",
chan->chan_id, ERR_PTR(ret));
return;
}
uniphier_mdmac_free_chan_resources(chan); uniphier_mdmac_free_chan_resources(chan);
} }
of_dma_controller_free(pdev->dev.of_node); of_dma_controller_free(pdev->dev.of_node);
dma_async_device_unregister(&mdev->ddev); dma_async_device_unregister(&mdev->ddev);
clk_disable_unprepare(mdev->clk); clk_disable_unprepare(mdev->clk);
return 0;
} }
static const struct of_device_id uniphier_mdmac_match[] = { static const struct of_device_id uniphier_mdmac_match[] = {
...@@ -488,7 +493,7 @@ MODULE_DEVICE_TABLE(of, uniphier_mdmac_match); ...@@ -488,7 +493,7 @@ MODULE_DEVICE_TABLE(of, uniphier_mdmac_match);
static struct platform_driver uniphier_mdmac_driver = { static struct platform_driver uniphier_mdmac_driver = {
.probe = uniphier_mdmac_probe, .probe = uniphier_mdmac_probe,
.remove = uniphier_mdmac_remove, .remove_new = uniphier_mdmac_remove,
.driver = { .driver = {
.name = "uniphier-mio-dmac", .name = "uniphier-mio-dmac",
.of_match_table = uniphier_mdmac_match, .of_match_table = uniphier_mdmac_match,
......
...@@ -563,7 +563,7 @@ static int uniphier_xdmac_probe(struct platform_device *pdev) ...@@ -563,7 +563,7 @@ static int uniphier_xdmac_probe(struct platform_device *pdev)
return ret; return ret;
} }
static int uniphier_xdmac_remove(struct platform_device *pdev) static void uniphier_xdmac_remove(struct platform_device *pdev)
{ {
struct uniphier_xdmac_device *xdev = platform_get_drvdata(pdev); struct uniphier_xdmac_device *xdev = platform_get_drvdata(pdev);
struct dma_device *ddev = &xdev->ddev; struct dma_device *ddev = &xdev->ddev;
...@@ -579,15 +579,20 @@ static int uniphier_xdmac_remove(struct platform_device *pdev) ...@@ -579,15 +579,20 @@ static int uniphier_xdmac_remove(struct platform_device *pdev)
*/ */
list_for_each_entry(chan, &ddev->channels, device_node) { list_for_each_entry(chan, &ddev->channels, device_node) {
ret = dmaengine_terminate_sync(chan); ret = dmaengine_terminate_sync(chan);
if (ret) if (ret) {
return ret; /*
* This results in resource leakage and maybe also
* use-after-free errors as e.g. *xdev is kfreed.
*/
dev_alert(&pdev->dev, "Failed to terminate channel %d (%pe)\n",
chan->chan_id, ERR_PTR(ret));
return;
}
uniphier_xdmac_free_chan_resources(chan); uniphier_xdmac_free_chan_resources(chan);
} }
of_dma_controller_free(pdev->dev.of_node); of_dma_controller_free(pdev->dev.of_node);
dma_async_device_unregister(ddev); dma_async_device_unregister(ddev);
return 0;
} }
static const struct of_device_id uniphier_xdmac_match[] = { static const struct of_device_id uniphier_xdmac_match[] = {
...@@ -598,7 +603,7 @@ MODULE_DEVICE_TABLE(of, uniphier_xdmac_match); ...@@ -598,7 +603,7 @@ MODULE_DEVICE_TABLE(of, uniphier_xdmac_match);
static struct platform_driver uniphier_xdmac_driver = { static struct platform_driver uniphier_xdmac_driver = {
.probe = uniphier_xdmac_probe, .probe = uniphier_xdmac_probe,
.remove = uniphier_xdmac_remove, .remove_new = uniphier_xdmac_remove,
.driver = { .driver = {
.name = "uniphier-xdmac", .name = "uniphier-xdmac",
.of_match_table = uniphier_xdmac_match, .of_match_table = uniphier_xdmac_match,
......
...@@ -64,9 +64,10 @@ struct xdma_hw_desc { ...@@ -64,9 +64,10 @@ struct xdma_hw_desc {
__le64 next_desc; __le64 next_desc;
}; };
#define XDMA_DESC_SIZE sizeof(struct xdma_hw_desc) #define XDMA_DESC_SIZE sizeof(struct xdma_hw_desc)
#define XDMA_DESC_BLOCK_SIZE (XDMA_DESC_SIZE * XDMA_DESC_ADJACENT) #define XDMA_DESC_BLOCK_SIZE (XDMA_DESC_SIZE * XDMA_DESC_ADJACENT)
#define XDMA_DESC_BLOCK_ALIGN 4096 #define XDMA_DESC_BLOCK_ALIGN 32
#define XDMA_DESC_BLOCK_BOUNDARY 4096
/* /*
* Channel registers * Channel registers
...@@ -76,6 +77,7 @@ struct xdma_hw_desc { ...@@ -76,6 +77,7 @@ struct xdma_hw_desc {
#define XDMA_CHAN_CONTROL_W1S 0x8 #define XDMA_CHAN_CONTROL_W1S 0x8
#define XDMA_CHAN_CONTROL_W1C 0xc #define XDMA_CHAN_CONTROL_W1C 0xc
#define XDMA_CHAN_STATUS 0x40 #define XDMA_CHAN_STATUS 0x40
#define XDMA_CHAN_STATUS_RC 0x44
#define XDMA_CHAN_COMPLETED_DESC 0x48 #define XDMA_CHAN_COMPLETED_DESC 0x48
#define XDMA_CHAN_ALIGNMENTS 0x4c #define XDMA_CHAN_ALIGNMENTS 0x4c
#define XDMA_CHAN_INTR_ENABLE 0x90 #define XDMA_CHAN_INTR_ENABLE 0x90
...@@ -101,6 +103,7 @@ struct xdma_hw_desc { ...@@ -101,6 +103,7 @@ struct xdma_hw_desc {
#define CHAN_CTRL_IE_MAGIC_STOPPED BIT(4) #define CHAN_CTRL_IE_MAGIC_STOPPED BIT(4)
#define CHAN_CTRL_IE_IDLE_STOPPED BIT(6) #define CHAN_CTRL_IE_IDLE_STOPPED BIT(6)
#define CHAN_CTRL_IE_READ_ERROR GENMASK(13, 9) #define CHAN_CTRL_IE_READ_ERROR GENMASK(13, 9)
#define CHAN_CTRL_IE_WRITE_ERROR GENMASK(18, 14)
#define CHAN_CTRL_IE_DESC_ERROR GENMASK(23, 19) #define CHAN_CTRL_IE_DESC_ERROR GENMASK(23, 19)
#define CHAN_CTRL_NON_INCR_ADDR BIT(25) #define CHAN_CTRL_NON_INCR_ADDR BIT(25)
#define CHAN_CTRL_POLL_MODE_WB BIT(26) #define CHAN_CTRL_POLL_MODE_WB BIT(26)
...@@ -111,8 +114,17 @@ struct xdma_hw_desc { ...@@ -111,8 +114,17 @@ struct xdma_hw_desc {
CHAN_CTRL_IE_DESC_ALIGN_MISMATCH | \ CHAN_CTRL_IE_DESC_ALIGN_MISMATCH | \
CHAN_CTRL_IE_MAGIC_STOPPED | \ CHAN_CTRL_IE_MAGIC_STOPPED | \
CHAN_CTRL_IE_READ_ERROR | \ CHAN_CTRL_IE_READ_ERROR | \
CHAN_CTRL_IE_WRITE_ERROR | \
CHAN_CTRL_IE_DESC_ERROR) CHAN_CTRL_IE_DESC_ERROR)
#define XDMA_CHAN_STATUS_MASK CHAN_CTRL_START
#define XDMA_CHAN_ERROR_MASK (CHAN_CTRL_IE_DESC_ALIGN_MISMATCH | \
CHAN_CTRL_IE_MAGIC_STOPPED | \
CHAN_CTRL_IE_READ_ERROR | \
CHAN_CTRL_IE_WRITE_ERROR | \
CHAN_CTRL_IE_DESC_ERROR)
/* bits of the channel interrupt enable mask */ /* bits of the channel interrupt enable mask */
#define CHAN_IM_DESC_ERROR BIT(19) #define CHAN_IM_DESC_ERROR BIT(19)
#define CHAN_IM_READ_ERROR BIT(9) #define CHAN_IM_READ_ERROR BIT(9)
...@@ -134,18 +146,6 @@ struct xdma_hw_desc { ...@@ -134,18 +146,6 @@ struct xdma_hw_desc {
#define XDMA_SGDMA_DESC_ADJ 0x4088 #define XDMA_SGDMA_DESC_ADJ 0x4088
#define XDMA_SGDMA_DESC_CREDIT 0x408c #define XDMA_SGDMA_DESC_CREDIT 0x408c
/* bits of the SG DMA control register */
#define XDMA_CTRL_RUN_STOP BIT(0)
#define XDMA_CTRL_IE_DESC_STOPPED BIT(1)
#define XDMA_CTRL_IE_DESC_COMPLETED BIT(2)
#define XDMA_CTRL_IE_DESC_ALIGN_MISMATCH BIT(3)
#define XDMA_CTRL_IE_MAGIC_STOPPED BIT(4)
#define XDMA_CTRL_IE_IDLE_STOPPED BIT(6)
#define XDMA_CTRL_IE_READ_ERROR GENMASK(13, 9)
#define XDMA_CTRL_IE_DESC_ERROR GENMASK(23, 19)
#define XDMA_CTRL_NON_INCR_ADDR BIT(25)
#define XDMA_CTRL_POLL_MODE_WB BIT(26)
/* /*
* interrupt registers * interrupt registers
*/ */
......
This diff is collapsed.
...@@ -309,7 +309,7 @@ static ssize_t xilinx_dpdma_debugfs_desc_done_irq_read(char *buf) ...@@ -309,7 +309,7 @@ static ssize_t xilinx_dpdma_debugfs_desc_done_irq_read(char *buf)
out_str_len = strlen(XILINX_DPDMA_DEBUGFS_UINT16_MAX_STR); out_str_len = strlen(XILINX_DPDMA_DEBUGFS_UINT16_MAX_STR);
out_str_len = min_t(size_t, XILINX_DPDMA_DEBUGFS_READ_MAX_SIZE, out_str_len = min_t(size_t, XILINX_DPDMA_DEBUGFS_READ_MAX_SIZE,
out_str_len); out_str_len + 1);
snprintf(buf, out_str_len, "%d", snprintf(buf, out_str_len, "%d",
dpdma_debugfs.xilinx_dpdma_irq_done_count); dpdma_debugfs.xilinx_dpdma_irq_done_count);
......
/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
#ifndef _FSL_EDMA_DT_BINDING_H_
#define _FSL_EDMA_DT_BINDING_H_
/* Receive Channel */
#define FSL_EDMA_RX 0x1
/* iMX8 audio remote DMA */
#define FSL_EDMA_REMOTE 0x2
/* FIFO is continue memory region */
#define FSL_EDMA_MULTI_FIFO 0x4
/* Channel need stick to even channel */
#define FSL_EDMA_EVEN_CH 0x8
/* Channel need stick to odd channel */
#define FSL_EDMA_ODD_CH 0x10
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment