dmaengine updates for v6.2
New support: - Qualcomm SDM670, SM6115 and SM6375 GPI controller support - Ingenic JZ4755 dmaengine support - Removal of iop-adma driver Updates: - Tegra support for dma-channel-mask - at_hdmac cleanup and virt-chan support for this driver -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+vs47OPLdNbVcHzyfBQHDyUjg0cFAmOfJXIACgkQfBQHDyUj g0eC1RAAr8WdSJo1Vv9EmzgmxIwx5l8nuGWJ+mRBVRvsiK0bVk5a2pDN8XGnyLim sQVd/RpH42MSYBk35GHsFaLPNvsn9h7cX3oDPwNzbQmijZsnX7ht7yHiYwamxNhC p/hzmRtBZvGwdUrInHwKG/tiLleCBDDALyDMnRkLsJ5qPxZpeVEe5WrfTQUachLZ yIHoOg3l+WrXkfqQwPZ5kO3pNTA0igdh3LZwZqKYXveuXVXYYG4zOLtgcJWnArG1 oLpUaJp75QPgHcknAZLDf47pwdDevV/mpv+2deoz3EbnhQc1b0bMZHRHRVc8B06w Xgx8U51L5iZsfiaueNDQTq+amCu3OehMiG0eouiXd2CmWC/jAB7NYehyJj7003t7 2BFIWSOEIKaLaoGVb7NJssc7yrkWH3QBvdAwQorFT1FnclAQnnaC5zVRng10BvA0 Ul/W9pmHXHrk5CvGGCUzlVRHF04KoRCEifQjMzAM9rgJJSJPM1ZybAtQzDhb1HGM 5lqHmi+BpKududS9MEHiMtfpch0hYdLkBfYemd0v8qFDKNsmNwtpbbg+aS1vwsZP lnRqCo50YVMsvCsEsjtfR0LyF0vx0ppuO8t7MKu+SIaa4YeJ9KK5JKMpnD33dJWe jSo+OPgsE2W+14ysdqVXnZpr6Aik34PZlSd13UcrRm9S9u2yyY8= =pURR -----END PGP SIGNATURE----- Merge tag 'dmaengine-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine Pull dmaengine updates from Vinod Koul: "New support: - Qualcomm SDM670, SM6115 and SM6375 GPI controller support - Ingenic JZ4755 dmaengine support - Removal of iop-adma driver Updates: - Tegra support for dma-channel-mask - at_hdmac cleanup and virt-chan support for this driver" * tag 'dmaengine-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine: (46 commits) dmaengine: Revert "dmaengine: remove s3c24xx driver" dmaengine: tegra: Add support for dma-channel-mask dt-bindings: dmaengine: Add dma-channel-mask to Tegra GPCDMA dmaengine: idxd: Remove linux/msi.h include dt-bindings: dmaengine: qcom: gpi: add compatible for SM6375 dmaengine: idxd: Fix crc_val field for completion record dmaengine: at_hdmac: Convert driver to use virt-dma dmaengine: at_hdmac: Remove unused member of at_dma_chan dmaengine: at_hdmac: Rename "chan_common" to "dma_chan" dmaengine: at_hdmac: Rename "dma_common" to "dma_device" dmaengine: at_hdmac: Use bitfield access macros dmaengine: at_hdmac: Keep register definitions and structures private to at_hdmac.c dmaengine: at_hdmac: Set include entries in alphabetic order dmaengine: at_hdmac: Use pm_ptr() dmaengine: at_hdmac: Use devm_clk_get() dmaengine: at_hdmac: Use devm_platform_ioremap_resource dmaengine: at_hdmac: Use devm_kzalloc() and struct_size() dmaengine: at_hdmac: Introduce atc_get_llis_residue() dmaengine: at_hdmac: s/atc_get_bytes_left/atc_get_residue dmaengine: at_hdmac: Pass residue by address to avoid unnecessary implicit casts ...
This commit is contained in:
commit
9322af3e6a
|
@ -22,6 +22,7 @@ Date: Oct 25, 2019
|
|||
KernelVersion: 5.6.0
|
||||
Contact: dmaengine@vger.kernel.org
|
||||
Description: The largest number of work descriptors in a batch.
|
||||
It's not visible when the device does not support batch.
|
||||
|
||||
What: /sys/bus/dsa/devices/dsa<m>/max_work_queues_size
|
||||
Date: Oct 25, 2019
|
||||
|
@ -49,6 +50,8 @@ Description: The total number of read buffers supported by this device.
|
|||
The read buffers represent resources within the DSA
|
||||
implementation, and these resources are allocated by engines to
|
||||
support operations. See DSA spec v1.2 9.2.4 Total Read Buffers.
|
||||
It's not visible when the device does not support Read Buffer
|
||||
allocation control.
|
||||
|
||||
What: /sys/bus/dsa/devices/dsa<m>/max_transfer_size
|
||||
Date: Oct 25, 2019
|
||||
|
@ -122,6 +125,8 @@ Contact: dmaengine@vger.kernel.org
|
|||
Description: The maximum number of read buffers that may be in use at
|
||||
one time by operations that access low bandwidth memory in the
|
||||
device. See DSA spec v1.2 9.2.8 GENCFG on Global Read Buffer Limit.
|
||||
It's not visible when the device does not support Read Buffer
|
||||
allocation control.
|
||||
|
||||
What: /sys/bus/dsa/devices/dsa<m>/cmd_status
|
||||
Date: Aug 28, 2020
|
||||
|
@ -205,6 +210,7 @@ KernelVersion: 5.10.0
|
|||
Contact: dmaengine@vger.kernel.org
|
||||
Description: The max batch size for this workqueue. Cannot exceed device
|
||||
max batch size. Configurable parameter.
|
||||
It's not visible when the device does not support batch.
|
||||
|
||||
What: /sys/bus/dsa/devices/wq<m>.<n>/ats_disable
|
||||
Date: Nov 13, 2020
|
||||
|
@ -250,6 +256,8 @@ KernelVersion: 5.17.0
|
|||
Contact: dmaengine@vger.kernel.org
|
||||
Description: Enable the use of global read buffer limit for the group. See DSA
|
||||
spec v1.2 9.2.18 GRPCFG Use Global Read Buffer Limit.
|
||||
It's not visible when the device does not support Read Buffer
|
||||
allocation control.
|
||||
|
||||
What: /sys/bus/dsa/devices/group<m>.<n>/read_buffers_allowed
|
||||
Date: Dec 10, 2021
|
||||
|
@ -258,6 +266,8 @@ Contact: dmaengine@vger.kernel.org
|
|||
Description: Indicates max number of read buffers that may be in use at one time
|
||||
by all engines in the group. See DSA spec v1.2 9.2.18 GRPCFG Read
|
||||
Buffers Allowed.
|
||||
It's not visible when the device does not support Read Buffer
|
||||
allocation control.
|
||||
|
||||
What: /sys/bus/dsa/devices/group<m>.<n>/read_buffers_reserved
|
||||
Date: Dec 10, 2021
|
||||
|
@ -266,6 +276,8 @@ Contact: dmaengine@vger.kernel.org
|
|||
Description: Indicates the number of Read Buffers reserved for the use of
|
||||
engines in the group. See DSA spec v1.2 9.2.18 GRPCFG Read Buffers
|
||||
Reserved.
|
||||
It's not visible when the device does not support Read Buffer
|
||||
allocation control.
|
||||
|
||||
What: /sys/bus/dsa/devices/group<m>.<n>/desc_progress_limit
|
||||
Date: Sept 14, 2022
|
||||
|
|
|
@ -18,6 +18,7 @@ properties:
|
|||
- enum:
|
||||
- ingenic,jz4740-dma
|
||||
- ingenic,jz4725b-dma
|
||||
- ingenic,jz4755-dma
|
||||
- ingenic,jz4760-dma
|
||||
- ingenic,jz4760-bdma
|
||||
- ingenic,jz4760-mdma
|
||||
|
|
|
@ -39,7 +39,7 @@ properties:
|
|||
Should contain all of the per-channel DMA interrupts in
|
||||
ascending order with respect to the DMA channel index.
|
||||
minItems: 1
|
||||
maxItems: 31
|
||||
maxItems: 32
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
@ -52,6 +52,9 @@ properties:
|
|||
|
||||
dma-coherent: true
|
||||
|
||||
dma-channel-mask:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -60,6 +63,7 @@ required:
|
|||
- reset-names
|
||||
- "#dma-cells"
|
||||
- iommus
|
||||
- dma-channel-mask
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
|
@ -108,5 +112,6 @@ examples:
|
|||
#dma-cells = <1>;
|
||||
iommus = <&smmu TEGRA186_SID_GPCDMA_0>;
|
||||
dma-coherent;
|
||||
dma-channel-mask = <0xfffffffe>;
|
||||
};
|
||||
...
|
||||
|
|
|
@ -18,14 +18,24 @@ allOf:
|
|||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,sc7280-gpi-dma
|
||||
- qcom,sdm845-gpi-dma
|
||||
- qcom,sm6350-gpi-dma
|
||||
- qcom,sm8150-gpi-dma
|
||||
- qcom,sm8250-gpi-dma
|
||||
- qcom,sm8350-gpi-dma
|
||||
- qcom,sm8450-gpi-dma
|
||||
oneOf:
|
||||
- enum:
|
||||
- qcom,sdm845-gpi-dma
|
||||
- qcom,sm6350-gpi-dma
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,sc7280-gpi-dma
|
||||
- qcom,sm6115-gpi-dma
|
||||
- qcom,sm6375-gpi-dma
|
||||
- qcom,sm8350-gpi-dma
|
||||
- qcom,sm8450-gpi-dma
|
||||
- const: qcom,sm6350-gpi-dma
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,sdm670-gpi-dma
|
||||
- qcom,sm8150-gpi-dma
|
||||
- qcom,sm8250-gpi-dma
|
||||
- const: qcom,sdm845-gpi-dma
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
|
@ -450,6 +450,7 @@ SERDEV
|
|||
|
||||
SLAVE DMA ENGINE
|
||||
devm_acpi_dma_controller_register()
|
||||
devm_acpi_dma_controller_free()
|
||||
|
||||
SPI
|
||||
devm_spi_alloc_master()
|
||||
|
|
|
@ -10460,11 +10460,6 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
|
|||
F: drivers/iommu/intel/
|
||||
F: include/linux/intel-svm.h
|
||||
|
||||
INTEL IOP-ADMA DMA DRIVER
|
||||
R: Dan Williams <dan.j.williams@intel.com>
|
||||
S: Odd fixes
|
||||
F: drivers/dma/iop-adma.c
|
||||
|
||||
INTEL IPU3 CSI-2 CIO2 DRIVER
|
||||
M: Yong Zhi <yong.zhi@intel.com>
|
||||
M: Sakari Ailus <sakari.ailus@linux.intel.com>
|
||||
|
@ -13629,7 +13624,6 @@ L: dmaengine@vger.kernel.org
|
|||
S: Supported
|
||||
F: Documentation/devicetree/bindings/dma/atmel-dma.txt
|
||||
F: drivers/dma/at_hdmac.c
|
||||
F: drivers/dma/at_hdmac_regs.h
|
||||
F: drivers/dma/at_xdmac.c
|
||||
F: include/dt-bindings/dma/at91.h
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ config AT_HDMAC
|
|||
tristate "Atmel AHB DMA support"
|
||||
depends on ARCH_AT91
|
||||
select DMA_ENGINE
|
||||
select DMA_VIRTUAL_CHANNELS
|
||||
help
|
||||
Support the Atmel AHB DMA controller.
|
||||
|
||||
|
@ -357,14 +358,6 @@ config INTEL_IOATDMA
|
|||
|
||||
If unsure, say N.
|
||||
|
||||
config INTEL_IOP_ADMA
|
||||
tristate "Intel IOP32x ADMA support"
|
||||
depends on ARCH_IOP32X || COMPILE_TEST
|
||||
select DMA_ENGINE
|
||||
select ASYNC_TX_ENABLE_CHANNEL_SWITCH
|
||||
help
|
||||
Enable support for the Intel(R) IOP Series RAID engines.
|
||||
|
||||
config K3_DMA
|
||||
tristate "Hisilicon K3 DMA support"
|
||||
depends on ARCH_HI3xxx || ARCH_HISI || COMPILE_TEST
|
||||
|
|
|
@ -44,7 +44,6 @@ obj-$(CONFIG_IMX_SDMA) += imx-sdma.o
|
|||
obj-$(CONFIG_INTEL_IDMA64) += idma64.o
|
||||
obj-$(CONFIG_INTEL_IOATDMA) += ioat/
|
||||
obj-y += idxd/
|
||||
obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
|
||||
obj-$(CONFIG_K3_DMA) += k3dma.o
|
||||
obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o
|
||||
obj-$(CONFIG_MILBEAUT_HDMAC) += milbeaut-hdmac.o
|
||||
|
|
|
@ -21,6 +21,12 @@
|
|||
#define NCHANNELS_MAX 64
|
||||
#define IRQ_NOUTPUTS 4
|
||||
|
||||
/*
|
||||
* For allocation purposes we split the cache
|
||||
* memory into blocks of fixed size (given in bytes).
|
||||
*/
|
||||
#define SRAM_BLOCK 2048
|
||||
|
||||
#define RING_WRITE_SLOT GENMASK(1, 0)
|
||||
#define RING_READ_SLOT GENMASK(5, 4)
|
||||
#define RING_FULL BIT(9)
|
||||
|
@ -36,6 +42,9 @@
|
|||
#define REG_TX_STOP 0x0004
|
||||
#define REG_RX_START 0x0008
|
||||
#define REG_RX_STOP 0x000c
|
||||
#define REG_IMPRINT 0x0090
|
||||
#define REG_TX_SRAM_SIZE 0x0094
|
||||
#define REG_RX_SRAM_SIZE 0x0098
|
||||
|
||||
#define REG_CHAN_CTL(ch) (0x8000 + (ch) * 0x200)
|
||||
#define REG_CHAN_CTL_RST_RINGS BIT(0)
|
||||
|
@ -53,7 +62,9 @@
|
|||
#define BUS_WIDTH_FRAME_2_WORDS 0x10
|
||||
#define BUS_WIDTH_FRAME_4_WORDS 0x20
|
||||
|
||||
#define CHAN_BUFSIZE 0x8000
|
||||
#define REG_CHAN_SRAM_CARVEOUT(ch) (0x8050 + (ch) * 0x200)
|
||||
#define CHAN_SRAM_CARVEOUT_SIZE GENMASK(31, 16)
|
||||
#define CHAN_SRAM_CARVEOUT_BASE GENMASK(15, 0)
|
||||
|
||||
#define REG_CHAN_FIFOCTL(ch) (0x8054 + (ch) * 0x200)
|
||||
#define CHAN_FIFOCTL_LIMIT GENMASK(31, 16)
|
||||
|
@ -76,6 +87,8 @@ struct admac_chan {
|
|||
struct dma_chan chan;
|
||||
struct tasklet_struct tasklet;
|
||||
|
||||
u32 carveout;
|
||||
|
||||
spinlock_t lock;
|
||||
struct admac_tx *current_tx;
|
||||
int nperiod_acks;
|
||||
|
@ -92,12 +105,24 @@ struct admac_chan {
|
|||
struct list_head to_free;
|
||||
};
|
||||
|
||||
struct admac_sram {
|
||||
u32 size;
|
||||
/*
|
||||
* SRAM_CARVEOUT has 16-bit fields, so the SRAM cannot be larger than
|
||||
* 64K and a 32-bit bitfield over 2K blocks covers it.
|
||||
*/
|
||||
u32 allocated;
|
||||
};
|
||||
|
||||
struct admac_data {
|
||||
struct dma_device dma;
|
||||
struct device *dev;
|
||||
__iomem void *base;
|
||||
struct reset_control *rstc;
|
||||
|
||||
struct mutex cache_alloc_lock;
|
||||
struct admac_sram txcache, rxcache;
|
||||
|
||||
int irq;
|
||||
int irq_index;
|
||||
int nchannels;
|
||||
|
@ -118,6 +143,60 @@ struct admac_tx {
|
|||
struct list_head node;
|
||||
};
|
||||
|
||||
static int admac_alloc_sram_carveout(struct admac_data *ad,
|
||||
enum dma_transfer_direction dir,
|
||||
u32 *out)
|
||||
{
|
||||
struct admac_sram *sram;
|
||||
int i, ret = 0, nblocks;
|
||||
|
||||
if (dir == DMA_MEM_TO_DEV)
|
||||
sram = &ad->txcache;
|
||||
else
|
||||
sram = &ad->rxcache;
|
||||
|
||||
mutex_lock(&ad->cache_alloc_lock);
|
||||
|
||||
nblocks = sram->size / SRAM_BLOCK;
|
||||
for (i = 0; i < nblocks; i++)
|
||||
if (!(sram->allocated & BIT(i)))
|
||||
break;
|
||||
|
||||
if (i < nblocks) {
|
||||
*out = FIELD_PREP(CHAN_SRAM_CARVEOUT_BASE, i * SRAM_BLOCK) |
|
||||
FIELD_PREP(CHAN_SRAM_CARVEOUT_SIZE, SRAM_BLOCK);
|
||||
sram->allocated |= BIT(i);
|
||||
} else {
|
||||
ret = -EBUSY;
|
||||
}
|
||||
|
||||
mutex_unlock(&ad->cache_alloc_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void admac_free_sram_carveout(struct admac_data *ad,
|
||||
enum dma_transfer_direction dir,
|
||||
u32 carveout)
|
||||
{
|
||||
struct admac_sram *sram;
|
||||
u32 base = FIELD_GET(CHAN_SRAM_CARVEOUT_BASE, carveout);
|
||||
int i;
|
||||
|
||||
if (dir == DMA_MEM_TO_DEV)
|
||||
sram = &ad->txcache;
|
||||
else
|
||||
sram = &ad->rxcache;
|
||||
|
||||
if (WARN_ON(base >= sram->size))
|
||||
return;
|
||||
|
||||
mutex_lock(&ad->cache_alloc_lock);
|
||||
i = base / SRAM_BLOCK;
|
||||
sram->allocated &= ~BIT(i);
|
||||
mutex_unlock(&ad->cache_alloc_lock);
|
||||
}
|
||||
|
||||
static void admac_modify(struct admac_data *ad, int reg, u32 mask, u32 val)
|
||||
{
|
||||
void __iomem *addr = ad->base + reg;
|
||||
|
@ -466,15 +545,28 @@ static void admac_synchronize(struct dma_chan *chan)
|
|||
static int admac_alloc_chan_resources(struct dma_chan *chan)
|
||||
{
|
||||
struct admac_chan *adchan = to_admac_chan(chan);
|
||||
struct admac_data *ad = adchan->host;
|
||||
int ret;
|
||||
|
||||
dma_cookie_init(&adchan->chan);
|
||||
ret = admac_alloc_sram_carveout(ad, admac_chan_direction(adchan->no),
|
||||
&adchan->carveout);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
writel_relaxed(adchan->carveout,
|
||||
ad->base + REG_CHAN_SRAM_CARVEOUT(adchan->no));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void admac_free_chan_resources(struct dma_chan *chan)
|
||||
{
|
||||
struct admac_chan *adchan = to_admac_chan(chan);
|
||||
|
||||
admac_terminate_all(chan);
|
||||
admac_synchronize(chan);
|
||||
admac_free_sram_carveout(adchan->host, admac_chan_direction(adchan->no),
|
||||
adchan->carveout);
|
||||
}
|
||||
|
||||
static struct dma_chan *admac_dma_of_xlate(struct of_phandle_args *dma_spec,
|
||||
|
@ -712,6 +804,7 @@ static int admac_probe(struct platform_device *pdev)
|
|||
platform_set_drvdata(pdev, ad);
|
||||
ad->dev = &pdev->dev;
|
||||
ad->nchannels = nchannels;
|
||||
mutex_init(&ad->cache_alloc_lock);
|
||||
|
||||
/*
|
||||
* The controller has 4 IRQ outputs. Try them all until
|
||||
|
@ -801,6 +894,13 @@ static int admac_probe(struct platform_device *pdev)
|
|||
goto free_irq;
|
||||
}
|
||||
|
||||
ad->txcache.size = readl_relaxed(ad->base + REG_TX_SRAM_SIZE);
|
||||
ad->rxcache.size = readl_relaxed(ad->base + REG_RX_SRAM_SIZE);
|
||||
|
||||
dev_info(&pdev->dev, "Audio DMA Controller\n");
|
||||
dev_info(&pdev->dev, "imprint %x TX cache %u RX cache %u\n",
|
||||
readl_relaxed(ad->base + REG_IMPRINT), ad->txcache.size, ad->rxcache.size);
|
||||
|
||||
return 0;
|
||||
|
||||
free_irq:
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,478 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Header file for the Atmel AHB DMA Controller driver
|
||||
*
|
||||
* Copyright (C) 2008 Atmel Corporation
|
||||
*/
|
||||
#ifndef AT_HDMAC_REGS_H
|
||||
#define AT_HDMAC_REGS_H
|
||||
|
||||
#define AT_DMA_MAX_NR_CHANNELS 8
|
||||
|
||||
|
||||
#define AT_DMA_GCFG 0x00 /* Global Configuration Register */
|
||||
#define AT_DMA_IF_BIGEND(i) (0x1 << (i)) /* AHB-Lite Interface i in Big-endian mode */
|
||||
#define AT_DMA_ARB_CFG (0x1 << 4) /* Arbiter mode. */
|
||||
#define AT_DMA_ARB_CFG_FIXED (0x0 << 4)
|
||||
#define AT_DMA_ARB_CFG_ROUND_ROBIN (0x1 << 4)
|
||||
|
||||
#define AT_DMA_EN 0x04 /* Controller Enable Register */
|
||||
#define AT_DMA_ENABLE (0x1 << 0)
|
||||
|
||||
#define AT_DMA_SREQ 0x08 /* Software Single Request Register */
|
||||
#define AT_DMA_SSREQ(x) (0x1 << ((x) << 1)) /* Request a source single transfer on channel x */
|
||||
#define AT_DMA_DSREQ(x) (0x1 << (1 + ((x) << 1))) /* Request a destination single transfer on channel x */
|
||||
|
||||
#define AT_DMA_CREQ 0x0C /* Software Chunk Transfer Request Register */
|
||||
#define AT_DMA_SCREQ(x) (0x1 << ((x) << 1)) /* Request a source chunk transfer on channel x */
|
||||
#define AT_DMA_DCREQ(x) (0x1 << (1 + ((x) << 1))) /* Request a destination chunk transfer on channel x */
|
||||
|
||||
#define AT_DMA_LAST 0x10 /* Software Last Transfer Flag Register */
|
||||
#define AT_DMA_SLAST(x) (0x1 << ((x) << 1)) /* This src rq is last tx of buffer on channel x */
|
||||
#define AT_DMA_DLAST(x) (0x1 << (1 + ((x) << 1))) /* This dst rq is last tx of buffer on channel x */
|
||||
|
||||
#define AT_DMA_SYNC 0x14 /* Request Synchronization Register */
|
||||
#define AT_DMA_SYR(h) (0x1 << (h)) /* Synchronize handshake line h */
|
||||
|
||||
/* Error, Chained Buffer transfer completed and Buffer transfer completed Interrupt registers */
|
||||
#define AT_DMA_EBCIER 0x18 /* Enable register */
|
||||
#define AT_DMA_EBCIDR 0x1C /* Disable register */
|
||||
#define AT_DMA_EBCIMR 0x20 /* Mask Register */
|
||||
#define AT_DMA_EBCISR 0x24 /* Status Register */
|
||||
#define AT_DMA_CBTC_OFFSET 8
|
||||
#define AT_DMA_ERR_OFFSET 16
|
||||
#define AT_DMA_BTC(x) (0x1 << (x))
|
||||
#define AT_DMA_CBTC(x) (0x1 << (AT_DMA_CBTC_OFFSET + (x)))
|
||||
#define AT_DMA_ERR(x) (0x1 << (AT_DMA_ERR_OFFSET + (x)))
|
||||
|
||||
#define AT_DMA_CHER 0x28 /* Channel Handler Enable Register */
|
||||
#define AT_DMA_ENA(x) (0x1 << (x))
|
||||
#define AT_DMA_SUSP(x) (0x1 << ( 8 + (x)))
|
||||
#define AT_DMA_KEEP(x) (0x1 << (24 + (x)))
|
||||
|
||||
#define AT_DMA_CHDR 0x2C /* Channel Handler Disable Register */
|
||||
#define AT_DMA_DIS(x) (0x1 << (x))
|
||||
#define AT_DMA_RES(x) (0x1 << ( 8 + (x)))
|
||||
|
||||
#define AT_DMA_CHSR 0x30 /* Channel Handler Status Register */
|
||||
#define AT_DMA_EMPT(x) (0x1 << (16 + (x)))
|
||||
#define AT_DMA_STAL(x) (0x1 << (24 + (x)))
|
||||
|
||||
|
||||
#define AT_DMA_CH_REGS_BASE 0x3C /* Channel registers base address */
|
||||
#define ch_regs(x) (AT_DMA_CH_REGS_BASE + (x) * 0x28) /* Channel x base addr */
|
||||
|
||||
/* Hardware register offset for each channel */
|
||||
#define ATC_SADDR_OFFSET 0x00 /* Source Address Register */
|
||||
#define ATC_DADDR_OFFSET 0x04 /* Destination Address Register */
|
||||
#define ATC_DSCR_OFFSET 0x08 /* Descriptor Address Register */
|
||||
#define ATC_CTRLA_OFFSET 0x0C /* Control A Register */
|
||||
#define ATC_CTRLB_OFFSET 0x10 /* Control B Register */
|
||||
#define ATC_CFG_OFFSET 0x14 /* Configuration Register */
|
||||
#define ATC_SPIP_OFFSET 0x18 /* Src PIP Configuration Register */
|
||||
#define ATC_DPIP_OFFSET 0x1C /* Dst PIP Configuration Register */
|
||||
|
||||
|
||||
/* Bitfield definitions */
|
||||
|
||||
/* Bitfields in DSCR */
|
||||
#define ATC_DSCR_IF(i) (0x3 & (i)) /* Dsc feched via AHB-Lite Interface i */
|
||||
|
||||
/* Bitfields in CTRLA */
|
||||
#define ATC_BTSIZE_MAX 0xFFFFUL /* Maximum Buffer Transfer Size */
|
||||
#define ATC_BTSIZE(x) (ATC_BTSIZE_MAX & (x)) /* Buffer Transfer Size */
|
||||
#define ATC_SCSIZE_MASK (0x7 << 16) /* Source Chunk Transfer Size */
|
||||
#define ATC_SCSIZE(x) (ATC_SCSIZE_MASK & ((x) << 16))
|
||||
#define ATC_SCSIZE_1 (0x0 << 16)
|
||||
#define ATC_SCSIZE_4 (0x1 << 16)
|
||||
#define ATC_SCSIZE_8 (0x2 << 16)
|
||||
#define ATC_SCSIZE_16 (0x3 << 16)
|
||||
#define ATC_SCSIZE_32 (0x4 << 16)
|
||||
#define ATC_SCSIZE_64 (0x5 << 16)
|
||||
#define ATC_SCSIZE_128 (0x6 << 16)
|
||||
#define ATC_SCSIZE_256 (0x7 << 16)
|
||||
#define ATC_DCSIZE_MASK (0x7 << 20) /* Destination Chunk Transfer Size */
|
||||
#define ATC_DCSIZE(x) (ATC_DCSIZE_MASK & ((x) << 20))
|
||||
#define ATC_DCSIZE_1 (0x0 << 20)
|
||||
#define ATC_DCSIZE_4 (0x1 << 20)
|
||||
#define ATC_DCSIZE_8 (0x2 << 20)
|
||||
#define ATC_DCSIZE_16 (0x3 << 20)
|
||||
#define ATC_DCSIZE_32 (0x4 << 20)
|
||||
#define ATC_DCSIZE_64 (0x5 << 20)
|
||||
#define ATC_DCSIZE_128 (0x6 << 20)
|
||||
#define ATC_DCSIZE_256 (0x7 << 20)
|
||||
#define ATC_SRC_WIDTH_MASK (0x3 << 24) /* Source Single Transfer Size */
|
||||
#define ATC_SRC_WIDTH(x) ((x) << 24)
|
||||
#define ATC_SRC_WIDTH_BYTE (0x0 << 24)
|
||||
#define ATC_SRC_WIDTH_HALFWORD (0x1 << 24)
|
||||
#define ATC_SRC_WIDTH_WORD (0x2 << 24)
|
||||
#define ATC_REG_TO_SRC_WIDTH(r) (((r) >> 24) & 0x3)
|
||||
#define ATC_DST_WIDTH_MASK (0x3 << 28) /* Destination Single Transfer Size */
|
||||
#define ATC_DST_WIDTH(x) ((x) << 28)
|
||||
#define ATC_DST_WIDTH_BYTE (0x0 << 28)
|
||||
#define ATC_DST_WIDTH_HALFWORD (0x1 << 28)
|
||||
#define ATC_DST_WIDTH_WORD (0x2 << 28)
|
||||
#define ATC_DONE (0x1 << 31) /* Tx Done (only written back in descriptor) */
|
||||
|
||||
/* Bitfields in CTRLB */
|
||||
#define ATC_SIF(i) (0x3 & (i)) /* Src tx done via AHB-Lite Interface i */
|
||||
#define ATC_DIF(i) ((0x3 & (i)) << 4) /* Dst tx done via AHB-Lite Interface i */
|
||||
/* Specify AHB interfaces */
|
||||
#define AT_DMA_MEM_IF 0 /* interface 0 as memory interface */
|
||||
#define AT_DMA_PER_IF 1 /* interface 1 as peripheral interface */
|
||||
|
||||
#define ATC_SRC_PIP (0x1 << 8) /* Source Picture-in-Picture enabled */
|
||||
#define ATC_DST_PIP (0x1 << 12) /* Destination Picture-in-Picture enabled */
|
||||
#define ATC_SRC_DSCR_DIS (0x1 << 16) /* Src Descriptor fetch disable */
|
||||
#define ATC_DST_DSCR_DIS (0x1 << 20) /* Dst Descriptor fetch disable */
|
||||
#define ATC_FC_MASK (0x7 << 21) /* Choose Flow Controller */
|
||||
#define ATC_FC_MEM2MEM (0x0 << 21) /* Mem-to-Mem (DMA) */
|
||||
#define ATC_FC_MEM2PER (0x1 << 21) /* Mem-to-Periph (DMA) */
|
||||
#define ATC_FC_PER2MEM (0x2 << 21) /* Periph-to-Mem (DMA) */
|
||||
#define ATC_FC_PER2PER (0x3 << 21) /* Periph-to-Periph (DMA) */
|
||||
#define ATC_FC_PER2MEM_PER (0x4 << 21) /* Periph-to-Mem (Peripheral) */
|
||||
#define ATC_FC_MEM2PER_PER (0x5 << 21) /* Mem-to-Periph (Peripheral) */
|
||||
#define ATC_FC_PER2PER_SRCPER (0x6 << 21) /* Periph-to-Periph (Src Peripheral) */
|
||||
#define ATC_FC_PER2PER_DSTPER (0x7 << 21) /* Periph-to-Periph (Dst Peripheral) */
|
||||
#define ATC_SRC_ADDR_MODE_MASK (0x3 << 24)
|
||||
#define ATC_SRC_ADDR_MODE_INCR (0x0 << 24) /* Incrementing Mode */
|
||||
#define ATC_SRC_ADDR_MODE_DECR (0x1 << 24) /* Decrementing Mode */
|
||||
#define ATC_SRC_ADDR_MODE_FIXED (0x2 << 24) /* Fixed Mode */
|
||||
#define ATC_DST_ADDR_MODE_MASK (0x3 << 28)
|
||||
#define ATC_DST_ADDR_MODE_INCR (0x0 << 28) /* Incrementing Mode */
|
||||
#define ATC_DST_ADDR_MODE_DECR (0x1 << 28) /* Decrementing Mode */
|
||||
#define ATC_DST_ADDR_MODE_FIXED (0x2 << 28) /* Fixed Mode */
|
||||
#define ATC_IEN (0x1 << 30) /* BTC interrupt enable (active low) */
|
||||
#define ATC_AUTO (0x1 << 31) /* Auto multiple buffer tx enable */
|
||||
|
||||
/* Bitfields in CFG */
|
||||
#define ATC_PER_MSB(h) ((0x30U & (h)) >> 4) /* Extract most significant bits of a handshaking identifier */
|
||||
|
||||
#define ATC_SRC_PER(h) (0xFU & (h)) /* Channel src rq associated with periph handshaking ifc h */
|
||||
#define ATC_DST_PER(h) ((0xFU & (h)) << 4) /* Channel dst rq associated with periph handshaking ifc h */
|
||||
#define ATC_SRC_REP (0x1 << 8) /* Source Replay Mod */
|
||||
#define ATC_SRC_H2SEL (0x1 << 9) /* Source Handshaking Mod */
|
||||
#define ATC_SRC_H2SEL_SW (0x0 << 9)
|
||||
#define ATC_SRC_H2SEL_HW (0x1 << 9)
|
||||
#define ATC_SRC_PER_MSB(h) (ATC_PER_MSB(h) << 10) /* Channel src rq (most significant bits) */
|
||||
#define ATC_DST_REP (0x1 << 12) /* Destination Replay Mod */
|
||||
#define ATC_DST_H2SEL (0x1 << 13) /* Destination Handshaking Mod */
|
||||
#define ATC_DST_H2SEL_SW (0x0 << 13)
|
||||
#define ATC_DST_H2SEL_HW (0x1 << 13)
|
||||
#define ATC_DST_PER_MSB(h) (ATC_PER_MSB(h) << 14) /* Channel dst rq (most significant bits) */
|
||||
#define ATC_SOD (0x1 << 16) /* Stop On Done */
|
||||
#define ATC_LOCK_IF (0x1 << 20) /* Interface Lock */
|
||||
#define ATC_LOCK_B (0x1 << 21) /* AHB Bus Lock */
|
||||
#define ATC_LOCK_IF_L (0x1 << 22) /* Master Interface Arbiter Lock */
|
||||
#define ATC_LOCK_IF_L_CHUNK (0x0 << 22)
|
||||
#define ATC_LOCK_IF_L_BUFFER (0x1 << 22)
|
||||
#define ATC_AHB_PROT_MASK (0x7 << 24) /* AHB Protection */
|
||||
#define ATC_FIFOCFG_MASK (0x3 << 28) /* FIFO Request Configuration */
|
||||
#define ATC_FIFOCFG_LARGESTBURST (0x0 << 28)
|
||||
#define ATC_FIFOCFG_HALFFIFO (0x1 << 28)
|
||||
#define ATC_FIFOCFG_ENOUGHSPACE (0x2 << 28)
|
||||
|
||||
/* Bitfields in SPIP */
|
||||
#define ATC_SPIP_HOLE(x) (0xFFFFU & (x))
|
||||
#define ATC_SPIP_BOUNDARY(x) ((0x3FF & (x)) << 16)
|
||||
|
||||
/* Bitfields in DPIP */
|
||||
#define ATC_DPIP_HOLE(x) (0xFFFFU & (x))
|
||||
#define ATC_DPIP_BOUNDARY(x) ((0x3FF & (x)) << 16)
|
||||
|
||||
|
||||
/*-- descriptors -----------------------------------------------------*/
|
||||
|
||||
/* LLI == Linked List Item; aka DMA buffer descriptor */
|
||||
struct at_lli {
|
||||
/* values that are not changed by hardware */
|
||||
u32 saddr;
|
||||
u32 daddr;
|
||||
/* value that may get written back: */
|
||||
u32 ctrla;
|
||||
/* more values that are not changed by hardware */
|
||||
u32 ctrlb;
|
||||
u32 dscr; /* chain to next lli */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct at_desc - software descriptor
|
||||
* @at_lli: hardware lli structure
|
||||
* @txd: support for the async_tx api
|
||||
* @desc_node: node on the channed descriptors list
|
||||
* @len: descriptor byte count
|
||||
* @total_len: total transaction byte count
|
||||
*/
|
||||
struct at_desc {
|
||||
/* FIRST values the hardware uses */
|
||||
struct at_lli lli;
|
||||
|
||||
/* THEN values for driver housekeeping */
|
||||
struct list_head tx_list;
|
||||
struct dma_async_tx_descriptor txd;
|
||||
struct list_head desc_node;
|
||||
size_t len;
|
||||
size_t total_len;
|
||||
|
||||
/* Interleaved data */
|
||||
size_t boundary;
|
||||
size_t dst_hole;
|
||||
size_t src_hole;
|
||||
|
||||
/* Memset temporary buffer */
|
||||
bool memset_buffer;
|
||||
dma_addr_t memset_paddr;
|
||||
int *memset_vaddr;
|
||||
};
|
||||
|
||||
static inline struct at_desc *
|
||||
txd_to_at_desc(struct dma_async_tx_descriptor *txd)
|
||||
{
|
||||
return container_of(txd, struct at_desc, txd);
|
||||
}
|
||||
|
||||
|
||||
/*-- Channels --------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* atc_status - information bits stored in channel status flag
|
||||
*
|
||||
* Manipulated with atomic operations.
|
||||
*/
|
||||
enum atc_status {
|
||||
ATC_IS_ERROR = 0,
|
||||
ATC_IS_PAUSED = 1,
|
||||
ATC_IS_CYCLIC = 24,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct at_dma_chan - internal representation of an Atmel HDMAC channel
|
||||
* @chan_common: common dmaengine channel object members
|
||||
* @device: parent device
|
||||
* @ch_regs: memory mapped register base
|
||||
* @mask: channel index in a mask
|
||||
* @per_if: peripheral interface
|
||||
* @mem_if: memory interface
|
||||
* @status: transmit status information from irq/prep* functions
|
||||
* to tasklet (use atomic operations)
|
||||
* @tasklet: bottom half to finish transaction work
|
||||
* @save_cfg: configuration register that is saved on suspend/resume cycle
|
||||
* @save_dscr: for cyclic operations, preserve next descriptor address in
|
||||
* the cyclic list on suspend/resume cycle
|
||||
* @dma_sconfig: configuration for slave transfers, passed via
|
||||
* .device_config
|
||||
* @lock: serializes enqueue/dequeue operations to descriptors lists
|
||||
* @active_list: list of descriptors dmaengine is being running on
|
||||
* @queue: list of descriptors ready to be submitted to engine
|
||||
* @free_list: list of descriptors usable by the channel
|
||||
*/
|
||||
struct at_dma_chan {
|
||||
struct dma_chan chan_common;
|
||||
struct at_dma *device;
|
||||
void __iomem *ch_regs;
|
||||
u8 mask;
|
||||
u8 per_if;
|
||||
u8 mem_if;
|
||||
unsigned long status;
|
||||
struct tasklet_struct tasklet;
|
||||
u32 save_cfg;
|
||||
u32 save_dscr;
|
||||
struct dma_slave_config dma_sconfig;
|
||||
|
||||
spinlock_t lock;
|
||||
|
||||
/* these other elements are all protected by lock */
|
||||
struct list_head active_list;
|
||||
struct list_head queue;
|
||||
struct list_head free_list;
|
||||
};
|
||||
|
||||
#define channel_readl(atchan, name) \
|
||||
__raw_readl((atchan)->ch_regs + ATC_##name##_OFFSET)
|
||||
|
||||
#define channel_writel(atchan, name, val) \
|
||||
__raw_writel((val), (atchan)->ch_regs + ATC_##name##_OFFSET)
|
||||
|
||||
static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan)
|
||||
{
|
||||
return container_of(dchan, struct at_dma_chan, chan_common);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix sconfig's burst size according to at_hdmac. We need to convert them as:
|
||||
* 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3, 32 -> 4, 64 -> 5, 128 -> 6, 256 -> 7.
|
||||
*
|
||||
* This can be done by finding most significant bit set.
|
||||
*/
|
||||
static inline void convert_burst(u32 *maxburst)
|
||||
{
|
||||
if (*maxburst > 1)
|
||||
*maxburst = fls(*maxburst) - 2;
|
||||
else
|
||||
*maxburst = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix sconfig's bus width according to at_hdmac.
|
||||
* 1 byte -> 0, 2 bytes -> 1, 4 bytes -> 2.
|
||||
*/
|
||||
static inline u8 convert_buswidth(enum dma_slave_buswidth addr_width)
|
||||
{
|
||||
switch (addr_width) {
|
||||
case DMA_SLAVE_BUSWIDTH_2_BYTES:
|
||||
return 1;
|
||||
case DMA_SLAVE_BUSWIDTH_4_BYTES:
|
||||
return 2;
|
||||
default:
|
||||
/* For 1 byte width or fallback */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*-- Controller ------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* struct at_dma - internal representation of an Atmel HDMA Controller
|
||||
* @chan_common: common dmaengine dma_device object members
|
||||
* @atdma_devtype: identifier of DMA controller compatibility
|
||||
* @ch_regs: memory mapped register base
|
||||
* @clk: dma controller clock
|
||||
* @save_imr: interrupt mask register that is saved on suspend/resume cycle
|
||||
* @all_chan_mask: all channels availlable in a mask
|
||||
* @dma_desc_pool: base of DMA descriptor region (DMA address)
|
||||
* @chan: channels table to store at_dma_chan structures
|
||||
*/
|
||||
struct at_dma {
|
||||
struct dma_device dma_common;
|
||||
void __iomem *regs;
|
||||
struct clk *clk;
|
||||
u32 save_imr;
|
||||
|
||||
u8 all_chan_mask;
|
||||
|
||||
struct dma_pool *dma_desc_pool;
|
||||
struct dma_pool *memset_pool;
|
||||
/* AT THE END channels table */
|
||||
struct at_dma_chan chan[];
|
||||
};
|
||||
|
||||
#define dma_readl(atdma, name) \
|
||||
__raw_readl((atdma)->regs + AT_DMA_##name)
|
||||
#define dma_writel(atdma, name, val) \
|
||||
__raw_writel((val), (atdma)->regs + AT_DMA_##name)
|
||||
|
||||
static inline struct at_dma *to_at_dma(struct dma_device *ddev)
|
||||
{
|
||||
return container_of(ddev, struct at_dma, dma_common);
|
||||
}
|
||||
|
||||
|
||||
/*-- Helper functions ------------------------------------------------*/
|
||||
|
||||
static struct device *chan2dev(struct dma_chan *chan)
|
||||
{
|
||||
return &chan->dev->device;
|
||||
}
|
||||
|
||||
#if defined(VERBOSE_DEBUG)
|
||||
static void vdbg_dump_regs(struct at_dma_chan *atchan)
|
||||
{
|
||||
struct at_dma *atdma = to_at_dma(atchan->chan_common.device);
|
||||
|
||||
dev_err(chan2dev(&atchan->chan_common),
|
||||
" channel %d : imr = 0x%x, chsr = 0x%x\n",
|
||||
atchan->chan_common.chan_id,
|
||||
dma_readl(atdma, EBCIMR),
|
||||
dma_readl(atdma, CHSR));
|
||||
|
||||
dev_err(chan2dev(&atchan->chan_common),
|
||||
" channel: s0x%x d0x%x ctrl0x%x:0x%x cfg0x%x l0x%x\n",
|
||||
channel_readl(atchan, SADDR),
|
||||
channel_readl(atchan, DADDR),
|
||||
channel_readl(atchan, CTRLA),
|
||||
channel_readl(atchan, CTRLB),
|
||||
channel_readl(atchan, CFG),
|
||||
channel_readl(atchan, DSCR));
|
||||
}
|
||||
#else
|
||||
static void vdbg_dump_regs(struct at_dma_chan *atchan) {}
|
||||
#endif
|
||||
|
||||
static void atc_dump_lli(struct at_dma_chan *atchan, struct at_lli *lli)
|
||||
{
|
||||
dev_crit(chan2dev(&atchan->chan_common),
|
||||
"desc: s%pad d%pad ctrl0x%x:0x%x l%pad\n",
|
||||
&lli->saddr, &lli->daddr,
|
||||
lli->ctrla, lli->ctrlb, &lli->dscr);
|
||||
}
|
||||
|
||||
|
||||
static void atc_setup_irq(struct at_dma *atdma, int chan_id, int on)
|
||||
{
|
||||
u32 ebci;
|
||||
|
||||
/* enable interrupts on buffer transfer completion & error */
|
||||
ebci = AT_DMA_BTC(chan_id)
|
||||
| AT_DMA_ERR(chan_id);
|
||||
if (on)
|
||||
dma_writel(atdma, EBCIER, ebci);
|
||||
else
|
||||
dma_writel(atdma, EBCIDR, ebci);
|
||||
}
|
||||
|
||||
static void atc_enable_chan_irq(struct at_dma *atdma, int chan_id)
|
||||
{
|
||||
atc_setup_irq(atdma, chan_id, 1);
|
||||
}
|
||||
|
||||
static void atc_disable_chan_irq(struct at_dma *atdma, int chan_id)
|
||||
{
|
||||
atc_setup_irq(atdma, chan_id, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* atc_chan_is_enabled - test if given channel is enabled
|
||||
* @atchan: channel we want to test status
|
||||
*/
|
||||
static inline int atc_chan_is_enabled(struct at_dma_chan *atchan)
|
||||
{
|
||||
struct at_dma *atdma = to_at_dma(atchan->chan_common.device);
|
||||
|
||||
return !!(dma_readl(atdma, CHSR) & atchan->mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* atc_chan_is_paused - test channel pause/resume status
|
||||
* @atchan: channel we want to test status
|
||||
*/
|
||||
static inline int atc_chan_is_paused(struct at_dma_chan *atchan)
|
||||
{
|
||||
return test_bit(ATC_IS_PAUSED, &atchan->status);
|
||||
}
|
||||
|
||||
/**
|
||||
* atc_chan_is_cyclic - test if given channel has cyclic property set
|
||||
* @atchan: channel we want to test status
|
||||
*/
|
||||
static inline int atc_chan_is_cyclic(struct at_dma_chan *atchan)
|
||||
{
|
||||
return test_bit(ATC_IS_CYCLIC, &atchan->status);
|
||||
}
|
||||
|
||||
/**
|
||||
* set_desc_eol - set end-of-link to descriptor so it will end transfer
|
||||
* @desc: descriptor, signle or at the end of a chain, to end chain on
|
||||
*/
|
||||
static void set_desc_eol(struct at_desc *desc)
|
||||
{
|
||||
u32 ctrlb = desc->lli.ctrlb;
|
||||
|
||||
ctrlb &= ~ATC_IEN;
|
||||
ctrlb |= ATC_SRC_DSCR_DIS | ATC_DST_DSCR_DIS;
|
||||
|
||||
desc->lli.ctrlb = ctrlb;
|
||||
desc->lli.dscr = 0;
|
||||
}
|
||||
|
||||
#endif /* AT_HDMAC_REGS_H */
|
|
@ -1038,6 +1038,13 @@ static const struct jz4780_dma_soc_data jz4725b_dma_soc_data = {
|
|||
JZ_SOC_DATA_BREAK_LINKS,
|
||||
};
|
||||
|
||||
static const struct jz4780_dma_soc_data jz4755_dma_soc_data = {
|
||||
.nb_channels = 4,
|
||||
.transfer_ord_max = 5,
|
||||
.flags = JZ_SOC_DATA_PER_CHAN_PM | JZ_SOC_DATA_NO_DCKES_DCKEC |
|
||||
JZ_SOC_DATA_BREAK_LINKS,
|
||||
};
|
||||
|
||||
static const struct jz4780_dma_soc_data jz4760_dma_soc_data = {
|
||||
.nb_channels = 5,
|
||||
.transfer_ord_max = 6,
|
||||
|
@ -1101,6 +1108,7 @@ static const struct jz4780_dma_soc_data x1830_dma_soc_data = {
|
|||
static const struct of_device_id jz4780_dma_dt_match[] = {
|
||||
{ .compatible = "ingenic,jz4740-dma", .data = &jz4740_dma_soc_data },
|
||||
{ .compatible = "ingenic,jz4725b-dma", .data = &jz4725b_dma_soc_data },
|
||||
{ .compatible = "ingenic,jz4755-dma", .data = &jz4755_dma_soc_data },
|
||||
{ .compatible = "ingenic,jz4760-dma", .data = &jz4760_dma_soc_data },
|
||||
{ .compatible = "ingenic,jz4760-mdma", .data = &jz4760_mdma_soc_data },
|
||||
{ .compatible = "ingenic,jz4760-bdma", .data = &jz4760_bdma_soc_data },
|
||||
|
|
|
@ -600,7 +600,7 @@ static int idma64_probe(struct idma64_chip *chip)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int idma64_remove(struct idma64_chip *chip)
|
||||
static void idma64_remove(struct idma64_chip *chip)
|
||||
{
|
||||
struct idma64 *idma64 = chip->idma64;
|
||||
unsigned short i;
|
||||
|
@ -618,8 +618,6 @@ static int idma64_remove(struct idma64_chip *chip)
|
|||
|
||||
tasklet_kill(&idma64c->vchan.task);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
@ -664,7 +662,9 @@ static int idma64_platform_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct idma64_chip *chip = platform_get_drvdata(pdev);
|
||||
|
||||
return idma64_remove(chip);
|
||||
idma64_remove(chip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused idma64_pm_suspend(struct device *dev)
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include <linux/io-64-nonatomic-lo-hi.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/msi.h>
|
||||
#include <uapi/linux/idxd.h>
|
||||
#include "../dmaengine.h"
|
||||
#include "idxd.h"
|
||||
|
|
|
@ -528,6 +528,22 @@ static bool idxd_group_attr_progress_limit_invisible(struct attribute *attr,
|
|||
!idxd->hw.group_cap.progress_limit;
|
||||
}
|
||||
|
||||
static bool idxd_group_attr_read_buffers_invisible(struct attribute *attr,
|
||||
struct idxd_device *idxd)
|
||||
{
|
||||
/*
|
||||
* Intel IAA does not support Read Buffer allocation control,
|
||||
* make these attributes invisible.
|
||||
*/
|
||||
return (attr == &dev_attr_group_use_token_limit.attr ||
|
||||
attr == &dev_attr_group_use_read_buffer_limit.attr ||
|
||||
attr == &dev_attr_group_tokens_allowed.attr ||
|
||||
attr == &dev_attr_group_read_buffers_allowed.attr ||
|
||||
attr == &dev_attr_group_tokens_reserved.attr ||
|
||||
attr == &dev_attr_group_read_buffers_reserved.attr) &&
|
||||
idxd->data->type == IDXD_TYPE_IAX;
|
||||
}
|
||||
|
||||
static umode_t idxd_group_attr_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int n)
|
||||
{
|
||||
|
@ -538,6 +554,9 @@ static umode_t idxd_group_attr_visible(struct kobject *kobj,
|
|||
if (idxd_group_attr_progress_limit_invisible(attr, idxd))
|
||||
return 0;
|
||||
|
||||
if (idxd_group_attr_read_buffers_invisible(attr, idxd))
|
||||
return 0;
|
||||
|
||||
return attr->mode;
|
||||
}
|
||||
|
||||
|
@ -1233,6 +1252,14 @@ static bool idxd_wq_attr_op_config_invisible(struct attribute *attr,
|
|||
!idxd->hw.wq_cap.op_config;
|
||||
}
|
||||
|
||||
static bool idxd_wq_attr_max_batch_size_invisible(struct attribute *attr,
|
||||
struct idxd_device *idxd)
|
||||
{
|
||||
/* Intel IAA does not support batch processing, make it invisible */
|
||||
return attr == &dev_attr_wq_max_batch_size.attr &&
|
||||
idxd->data->type == IDXD_TYPE_IAX;
|
||||
}
|
||||
|
||||
static umode_t idxd_wq_attr_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int n)
|
||||
{
|
||||
|
@ -1243,6 +1270,9 @@ static umode_t idxd_wq_attr_visible(struct kobject *kobj,
|
|||
if (idxd_wq_attr_op_config_invisible(attr, idxd))
|
||||
return 0;
|
||||
|
||||
if (idxd_wq_attr_max_batch_size_invisible(attr, idxd))
|
||||
return 0;
|
||||
|
||||
return attr->mode;
|
||||
}
|
||||
|
||||
|
@ -1533,6 +1563,43 @@ static ssize_t cmd_status_store(struct device *dev, struct device_attribute *att
|
|||
}
|
||||
static DEVICE_ATTR_RW(cmd_status);
|
||||
|
||||
static bool idxd_device_attr_max_batch_size_invisible(struct attribute *attr,
|
||||
struct idxd_device *idxd)
|
||||
{
|
||||
/* Intel IAA does not support batch processing, make it invisible */
|
||||
return attr == &dev_attr_max_batch_size.attr &&
|
||||
idxd->data->type == IDXD_TYPE_IAX;
|
||||
}
|
||||
|
||||
static bool idxd_device_attr_read_buffers_invisible(struct attribute *attr,
|
||||
struct idxd_device *idxd)
|
||||
{
|
||||
/*
|
||||
* Intel IAA does not support Read Buffer allocation control,
|
||||
* make these attributes invisible.
|
||||
*/
|
||||
return (attr == &dev_attr_max_tokens.attr ||
|
||||
attr == &dev_attr_max_read_buffers.attr ||
|
||||
attr == &dev_attr_token_limit.attr ||
|
||||
attr == &dev_attr_read_buffer_limit.attr) &&
|
||||
idxd->data->type == IDXD_TYPE_IAX;
|
||||
}
|
||||
|
||||
static umode_t idxd_device_attr_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int n)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct idxd_device *idxd = confdev_to_idxd(dev);
|
||||
|
||||
if (idxd_device_attr_max_batch_size_invisible(attr, idxd))
|
||||
return 0;
|
||||
|
||||
if (idxd_device_attr_read_buffers_invisible(attr, idxd))
|
||||
return 0;
|
||||
|
||||
return attr->mode;
|
||||
}
|
||||
|
||||
static struct attribute *idxd_device_attributes[] = {
|
||||
&dev_attr_version.attr,
|
||||
&dev_attr_max_groups.attr,
|
||||
|
@ -1560,6 +1627,7 @@ static struct attribute *idxd_device_attributes[] = {
|
|||
|
||||
static const struct attribute_group idxd_device_attribute_group = {
|
||||
.attrs = idxd_device_attributes,
|
||||
.is_visible = idxd_device_attr_visible,
|
||||
};
|
||||
|
||||
static const struct attribute_group *idxd_attribute_groups[] = {
|
||||
|
|
|
@ -33,7 +33,7 @@ MODULE_PARM_DESC(completion_timeout,
|
|||
static int idle_timeout = 2000;
|
||||
module_param(idle_timeout, int, 0644);
|
||||
MODULE_PARM_DESC(idle_timeout,
|
||||
"set ioat idel timeout [msec] (default 2000 [msec])");
|
||||
"set ioat idle timeout [msec] (default 2000 [msec])");
|
||||
|
||||
#define IDLE_TIMEOUT msecs_to_jiffies(idle_timeout)
|
||||
#define COMPLETION_TIMEOUT msecs_to_jiffies(completion_timeout)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,914 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright © 2006, Intel Corporation.
|
||||
*/
|
||||
#ifndef _ADMA_H
|
||||
#define _ADMA_H
|
||||
#include <linux/types.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_data/dma-iop32x.h>
|
||||
|
||||
/* Memory copy units */
|
||||
#define DMA_CCR(chan) (chan->mmr_base + 0x0)
|
||||
#define DMA_CSR(chan) (chan->mmr_base + 0x4)
|
||||
#define DMA_DAR(chan) (chan->mmr_base + 0xc)
|
||||
#define DMA_NDAR(chan) (chan->mmr_base + 0x10)
|
||||
#define DMA_PADR(chan) (chan->mmr_base + 0x14)
|
||||
#define DMA_PUADR(chan) (chan->mmr_base + 0x18)
|
||||
#define DMA_LADR(chan) (chan->mmr_base + 0x1c)
|
||||
#define DMA_BCR(chan) (chan->mmr_base + 0x20)
|
||||
#define DMA_DCR(chan) (chan->mmr_base + 0x24)
|
||||
|
||||
/* Application accelerator unit */
|
||||
#define AAU_ACR(chan) (chan->mmr_base + 0x0)
|
||||
#define AAU_ASR(chan) (chan->mmr_base + 0x4)
|
||||
#define AAU_ADAR(chan) (chan->mmr_base + 0x8)
|
||||
#define AAU_ANDAR(chan) (chan->mmr_base + 0xc)
|
||||
#define AAU_SAR(src, chan) (chan->mmr_base + (0x10 + ((src) << 2)))
|
||||
#define AAU_DAR(chan) (chan->mmr_base + 0x20)
|
||||
#define AAU_ABCR(chan) (chan->mmr_base + 0x24)
|
||||
#define AAU_ADCR(chan) (chan->mmr_base + 0x28)
|
||||
#define AAU_SAR_EDCR(src_edc) (chan->mmr_base + (0x02c + ((src_edc-4) << 2)))
|
||||
#define AAU_EDCR0_IDX 8
|
||||
#define AAU_EDCR1_IDX 17
|
||||
#define AAU_EDCR2_IDX 26
|
||||
|
||||
struct iop3xx_aau_desc_ctrl {
|
||||
unsigned int int_en:1;
|
||||
unsigned int blk1_cmd_ctrl:3;
|
||||
unsigned int blk2_cmd_ctrl:3;
|
||||
unsigned int blk3_cmd_ctrl:3;
|
||||
unsigned int blk4_cmd_ctrl:3;
|
||||
unsigned int blk5_cmd_ctrl:3;
|
||||
unsigned int blk6_cmd_ctrl:3;
|
||||
unsigned int blk7_cmd_ctrl:3;
|
||||
unsigned int blk8_cmd_ctrl:3;
|
||||
unsigned int blk_ctrl:2;
|
||||
unsigned int dual_xor_en:1;
|
||||
unsigned int tx_complete:1;
|
||||
unsigned int zero_result_err:1;
|
||||
unsigned int zero_result_en:1;
|
||||
unsigned int dest_write_en:1;
|
||||
};
|
||||
|
||||
struct iop3xx_aau_e_desc_ctrl {
|
||||
unsigned int reserved:1;
|
||||
unsigned int blk1_cmd_ctrl:3;
|
||||
unsigned int blk2_cmd_ctrl:3;
|
||||
unsigned int blk3_cmd_ctrl:3;
|
||||
unsigned int blk4_cmd_ctrl:3;
|
||||
unsigned int blk5_cmd_ctrl:3;
|
||||
unsigned int blk6_cmd_ctrl:3;
|
||||
unsigned int blk7_cmd_ctrl:3;
|
||||
unsigned int blk8_cmd_ctrl:3;
|
||||
unsigned int reserved2:7;
|
||||
};
|
||||
|
||||
struct iop3xx_dma_desc_ctrl {
|
||||
unsigned int pci_transaction:4;
|
||||
unsigned int int_en:1;
|
||||
unsigned int dac_cycle_en:1;
|
||||
unsigned int mem_to_mem_en:1;
|
||||
unsigned int crc_data_tx_en:1;
|
||||
unsigned int crc_gen_en:1;
|
||||
unsigned int crc_seed_dis:1;
|
||||
unsigned int reserved:21;
|
||||
unsigned int crc_tx_complete:1;
|
||||
};
|
||||
|
||||
struct iop3xx_desc_dma {
|
||||
u32 next_desc;
|
||||
union {
|
||||
u32 pci_src_addr;
|
||||
u32 pci_dest_addr;
|
||||
u32 src_addr;
|
||||
};
|
||||
union {
|
||||
u32 upper_pci_src_addr;
|
||||
u32 upper_pci_dest_addr;
|
||||
};
|
||||
union {
|
||||
u32 local_pci_src_addr;
|
||||
u32 local_pci_dest_addr;
|
||||
u32 dest_addr;
|
||||
};
|
||||
u32 byte_count;
|
||||
union {
|
||||
u32 desc_ctrl;
|
||||
struct iop3xx_dma_desc_ctrl desc_ctrl_field;
|
||||
};
|
||||
u32 crc_addr;
|
||||
};
|
||||
|
||||
struct iop3xx_desc_aau {
|
||||
u32 next_desc;
|
||||
u32 src[4];
|
||||
u32 dest_addr;
|
||||
u32 byte_count;
|
||||
union {
|
||||
u32 desc_ctrl;
|
||||
struct iop3xx_aau_desc_ctrl desc_ctrl_field;
|
||||
};
|
||||
union {
|
||||
u32 src_addr;
|
||||
u32 e_desc_ctrl;
|
||||
struct iop3xx_aau_e_desc_ctrl e_desc_ctrl_field;
|
||||
} src_edc[31];
|
||||
};
|
||||
|
||||
struct iop3xx_aau_gfmr {
|
||||
unsigned int gfmr1:8;
|
||||
unsigned int gfmr2:8;
|
||||
unsigned int gfmr3:8;
|
||||
unsigned int gfmr4:8;
|
||||
};
|
||||
|
||||
struct iop3xx_desc_pq_xor {
|
||||
u32 next_desc;
|
||||
u32 src[3];
|
||||
union {
|
||||
u32 data_mult1;
|
||||
struct iop3xx_aau_gfmr data_mult1_field;
|
||||
};
|
||||
u32 dest_addr;
|
||||
u32 byte_count;
|
||||
union {
|
||||
u32 desc_ctrl;
|
||||
struct iop3xx_aau_desc_ctrl desc_ctrl_field;
|
||||
};
|
||||
union {
|
||||
u32 src_addr;
|
||||
u32 e_desc_ctrl;
|
||||
struct iop3xx_aau_e_desc_ctrl e_desc_ctrl_field;
|
||||
u32 data_multiplier;
|
||||
struct iop3xx_aau_gfmr data_mult_field;
|
||||
u32 reserved;
|
||||
} src_edc_gfmr[19];
|
||||
};
|
||||
|
||||
struct iop3xx_desc_dual_xor {
|
||||
u32 next_desc;
|
||||
u32 src0_addr;
|
||||
u32 src1_addr;
|
||||
u32 h_src_addr;
|
||||
u32 d_src_addr;
|
||||
u32 h_dest_addr;
|
||||
u32 byte_count;
|
||||
union {
|
||||
u32 desc_ctrl;
|
||||
struct iop3xx_aau_desc_ctrl desc_ctrl_field;
|
||||
};
|
||||
u32 d_dest_addr;
|
||||
};
|
||||
|
||||
union iop3xx_desc {
|
||||
struct iop3xx_desc_aau *aau;
|
||||
struct iop3xx_desc_dma *dma;
|
||||
struct iop3xx_desc_pq_xor *pq_xor;
|
||||
struct iop3xx_desc_dual_xor *dual_xor;
|
||||
void *ptr;
|
||||
};
|
||||
|
||||
/* No support for p+q operations */
|
||||
static inline int
|
||||
iop_chan_pq_slot_count(size_t len, int src_cnt, int *slots_per_op)
|
||||
{
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
iop_desc_init_pq(struct iop_adma_desc_slot *desc, int src_cnt,
|
||||
unsigned long flags)
|
||||
{
|
||||
BUG();
|
||||
}
|
||||
|
||||
static inline void
|
||||
iop_desc_set_pq_addr(struct iop_adma_desc_slot *desc, dma_addr_t *addr)
|
||||
{
|
||||
BUG();
|
||||
}
|
||||
|
||||
static inline void
|
||||
iop_desc_set_pq_src_addr(struct iop_adma_desc_slot *desc, int src_idx,
|
||||
dma_addr_t addr, unsigned char coef)
|
||||
{
|
||||
BUG();
|
||||
}
|
||||
|
||||
static inline int
|
||||
iop_chan_pq_zero_sum_slot_count(size_t len, int src_cnt, int *slots_per_op)
|
||||
{
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
iop_desc_init_pq_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt,
|
||||
unsigned long flags)
|
||||
{
|
||||
BUG();
|
||||
}
|
||||
|
||||
static inline void
|
||||
iop_desc_set_pq_zero_sum_byte_count(struct iop_adma_desc_slot *desc, u32 len)
|
||||
{
|
||||
BUG();
|
||||
}
|
||||
|
||||
#define iop_desc_set_pq_zero_sum_src_addr iop_desc_set_pq_src_addr
|
||||
|
||||
static inline void
|
||||
iop_desc_set_pq_zero_sum_addr(struct iop_adma_desc_slot *desc, int pq_idx,
|
||||
dma_addr_t *src)
|
||||
{
|
||||
BUG();
|
||||
}
|
||||
|
||||
static inline int iop_adma_get_max_xor(void)
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
|
||||
static inline int iop_adma_get_max_pq(void)
|
||||
{
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u32 iop_chan_get_current_descriptor(struct iop_adma_chan *chan)
|
||||
{
|
||||
int id = chan->device->id;
|
||||
|
||||
switch (id) {
|
||||
case DMA0_ID:
|
||||
case DMA1_ID:
|
||||
return __raw_readl(DMA_DAR(chan));
|
||||
case AAU_ID:
|
||||
return __raw_readl(AAU_ADAR(chan));
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void iop_chan_set_next_descriptor(struct iop_adma_chan *chan,
|
||||
u32 next_desc_addr)
|
||||
{
|
||||
int id = chan->device->id;
|
||||
|
||||
switch (id) {
|
||||
case DMA0_ID:
|
||||
case DMA1_ID:
|
||||
__raw_writel(next_desc_addr, DMA_NDAR(chan));
|
||||
break;
|
||||
case AAU_ID:
|
||||
__raw_writel(next_desc_addr, AAU_ANDAR(chan));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#define IOP_ADMA_STATUS_BUSY (1 << 10)
|
||||
#define IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT (1024)
|
||||
#define IOP_ADMA_XOR_MAX_BYTE_COUNT (16 * 1024 * 1024)
|
||||
#define IOP_ADMA_MAX_BYTE_COUNT (16 * 1024 * 1024)
|
||||
|
||||
static inline int iop_chan_is_busy(struct iop_adma_chan *chan)
|
||||
{
|
||||
u32 status = __raw_readl(DMA_CSR(chan));
|
||||
return (status & IOP_ADMA_STATUS_BUSY) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline int iop_desc_is_aligned(struct iop_adma_desc_slot *desc,
|
||||
int num_slots)
|
||||
{
|
||||
/* num_slots will only ever be 1, 2, 4, or 8 */
|
||||
return (desc->idx & (num_slots - 1)) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* to do: support large (i.e. > hw max) buffer sizes */
|
||||
static inline int iop_chan_memcpy_slot_count(size_t len, int *slots_per_op)
|
||||
{
|
||||
*slots_per_op = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* to do: support large (i.e. > hw max) buffer sizes */
|
||||
static inline int iop_chan_memset_slot_count(size_t len, int *slots_per_op)
|
||||
{
|
||||
*slots_per_op = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int iop3xx_aau_xor_slot_count(size_t len, int src_cnt,
|
||||
int *slots_per_op)
|
||||
{
|
||||
static const char slot_count_table[] = {
|
||||
1, 1, 1, 1, /* 01 - 04 */
|
||||
2, 2, 2, 2, /* 05 - 08 */
|
||||
4, 4, 4, 4, /* 09 - 12 */
|
||||
4, 4, 4, 4, /* 13 - 16 */
|
||||
8, 8, 8, 8, /* 17 - 20 */
|
||||
8, 8, 8, 8, /* 21 - 24 */
|
||||
8, 8, 8, 8, /* 25 - 28 */
|
||||
8, 8, 8, 8, /* 29 - 32 */
|
||||
};
|
||||
*slots_per_op = slot_count_table[src_cnt - 1];
|
||||
return *slots_per_op;
|
||||
}
|
||||
|
||||
static inline int
|
||||
iop_chan_interrupt_slot_count(int *slots_per_op, struct iop_adma_chan *chan)
|
||||
{
|
||||
switch (chan->device->id) {
|
||||
case DMA0_ID:
|
||||
case DMA1_ID:
|
||||
return iop_chan_memcpy_slot_count(0, slots_per_op);
|
||||
case AAU_ID:
|
||||
return iop3xx_aau_xor_slot_count(0, 2, slots_per_op);
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int iop_chan_xor_slot_count(size_t len, int src_cnt,
|
||||
int *slots_per_op)
|
||||
{
|
||||
int slot_cnt = iop3xx_aau_xor_slot_count(len, src_cnt, slots_per_op);
|
||||
|
||||
if (len <= IOP_ADMA_XOR_MAX_BYTE_COUNT)
|
||||
return slot_cnt;
|
||||
|
||||
len -= IOP_ADMA_XOR_MAX_BYTE_COUNT;
|
||||
while (len > IOP_ADMA_XOR_MAX_BYTE_COUNT) {
|
||||
len -= IOP_ADMA_XOR_MAX_BYTE_COUNT;
|
||||
slot_cnt += *slots_per_op;
|
||||
}
|
||||
|
||||
slot_cnt += *slots_per_op;
|
||||
|
||||
return slot_cnt;
|
||||
}
|
||||
|
||||
/* zero sum on iop3xx is limited to 1k at a time so it requires multiple
|
||||
* descriptors
|
||||
*/
|
||||
static inline int iop_chan_zero_sum_slot_count(size_t len, int src_cnt,
|
||||
int *slots_per_op)
|
||||
{
|
||||
int slot_cnt = iop3xx_aau_xor_slot_count(len, src_cnt, slots_per_op);
|
||||
|
||||
if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT)
|
||||
return slot_cnt;
|
||||
|
||||
len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
|
||||
while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
|
||||
len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
|
||||
slot_cnt += *slots_per_op;
|
||||
}
|
||||
|
||||
slot_cnt += *slots_per_op;
|
||||
|
||||
return slot_cnt;
|
||||
}
|
||||
|
||||
static inline u32 iop_desc_get_byte_count(struct iop_adma_desc_slot *desc,
|
||||
struct iop_adma_chan *chan)
|
||||
{
|
||||
union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
|
||||
|
||||
switch (chan->device->id) {
|
||||
case DMA0_ID:
|
||||
case DMA1_ID:
|
||||
return hw_desc.dma->byte_count;
|
||||
case AAU_ID:
|
||||
return hw_desc.aau->byte_count;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* translate the src_idx to a descriptor word index */
|
||||
static inline int __desc_idx(int src_idx)
|
||||
{
|
||||
static const int desc_idx_table[] = { 0, 0, 0, 0,
|
||||
0, 1, 2, 3,
|
||||
5, 6, 7, 8,
|
||||
9, 10, 11, 12,
|
||||
14, 15, 16, 17,
|
||||
18, 19, 20, 21,
|
||||
23, 24, 25, 26,
|
||||
27, 28, 29, 30,
|
||||
};
|
||||
|
||||
return desc_idx_table[src_idx];
|
||||
}
|
||||
|
||||
static inline u32 iop_desc_get_src_addr(struct iop_adma_desc_slot *desc,
|
||||
struct iop_adma_chan *chan,
|
||||
int src_idx)
|
||||
{
|
||||
union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
|
||||
|
||||
switch (chan->device->id) {
|
||||
case DMA0_ID:
|
||||
case DMA1_ID:
|
||||
return hw_desc.dma->src_addr;
|
||||
case AAU_ID:
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
if (src_idx < 4)
|
||||
return hw_desc.aau->src[src_idx];
|
||||
else
|
||||
return hw_desc.aau->src_edc[__desc_idx(src_idx)].src_addr;
|
||||
}
|
||||
|
||||
static inline void iop3xx_aau_desc_set_src_addr(struct iop3xx_desc_aau *hw_desc,
|
||||
int src_idx, dma_addr_t addr)
|
||||
{
|
||||
if (src_idx < 4)
|
||||
hw_desc->src[src_idx] = addr;
|
||||
else
|
||||
hw_desc->src_edc[__desc_idx(src_idx)].src_addr = addr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
iop_desc_init_memcpy(struct iop_adma_desc_slot *desc, unsigned long flags)
|
||||
{
|
||||
struct iop3xx_desc_dma *hw_desc = desc->hw_desc;
|
||||
union {
|
||||
u32 value;
|
||||
struct iop3xx_dma_desc_ctrl field;
|
||||
} u_desc_ctrl;
|
||||
|
||||
u_desc_ctrl.value = 0;
|
||||
u_desc_ctrl.field.mem_to_mem_en = 1;
|
||||
u_desc_ctrl.field.pci_transaction = 0xe; /* memory read block */
|
||||
u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
|
||||
hw_desc->desc_ctrl = u_desc_ctrl.value;
|
||||
hw_desc->upper_pci_src_addr = 0;
|
||||
hw_desc->crc_addr = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
iop_desc_init_memset(struct iop_adma_desc_slot *desc, unsigned long flags)
|
||||
{
|
||||
struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
|
||||
union {
|
||||
u32 value;
|
||||
struct iop3xx_aau_desc_ctrl field;
|
||||
} u_desc_ctrl;
|
||||
|
||||
u_desc_ctrl.value = 0;
|
||||
u_desc_ctrl.field.blk1_cmd_ctrl = 0x2; /* memory block fill */
|
||||
u_desc_ctrl.field.dest_write_en = 1;
|
||||
u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
|
||||
hw_desc->desc_ctrl = u_desc_ctrl.value;
|
||||
}
|
||||
|
||||
static inline u32
|
||||
iop3xx_desc_init_xor(struct iop3xx_desc_aau *hw_desc, int src_cnt,
|
||||
unsigned long flags)
|
||||
{
|
||||
int i, shift;
|
||||
u32 edcr;
|
||||
union {
|
||||
u32 value;
|
||||
struct iop3xx_aau_desc_ctrl field;
|
||||
} u_desc_ctrl;
|
||||
|
||||
u_desc_ctrl.value = 0;
|
||||
switch (src_cnt) {
|
||||
case 25 ... 32:
|
||||
u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
|
||||
edcr = 0;
|
||||
shift = 1;
|
||||
for (i = 24; i < src_cnt; i++) {
|
||||
edcr |= (1 << shift);
|
||||
shift += 3;
|
||||
}
|
||||
hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = edcr;
|
||||
src_cnt = 24;
|
||||
fallthrough;
|
||||
case 17 ... 24:
|
||||
if (!u_desc_ctrl.field.blk_ctrl) {
|
||||
hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
|
||||
u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
|
||||
}
|
||||
edcr = 0;
|
||||
shift = 1;
|
||||
for (i = 16; i < src_cnt; i++) {
|
||||
edcr |= (1 << shift);
|
||||
shift += 3;
|
||||
}
|
||||
hw_desc->src_edc[AAU_EDCR1_IDX].e_desc_ctrl = edcr;
|
||||
src_cnt = 16;
|
||||
fallthrough;
|
||||
case 9 ... 16:
|
||||
if (!u_desc_ctrl.field.blk_ctrl)
|
||||
u_desc_ctrl.field.blk_ctrl = 0x2; /* use EDCR0 */
|
||||
edcr = 0;
|
||||
shift = 1;
|
||||
for (i = 8; i < src_cnt; i++) {
|
||||
edcr |= (1 << shift);
|
||||
shift += 3;
|
||||
}
|
||||
hw_desc->src_edc[AAU_EDCR0_IDX].e_desc_ctrl = edcr;
|
||||
src_cnt = 8;
|
||||
fallthrough;
|
||||
case 2 ... 8:
|
||||
shift = 1;
|
||||
for (i = 0; i < src_cnt; i++) {
|
||||
u_desc_ctrl.value |= (1 << shift);
|
||||
shift += 3;
|
||||
}
|
||||
|
||||
if (!u_desc_ctrl.field.blk_ctrl && src_cnt > 4)
|
||||
u_desc_ctrl.field.blk_ctrl = 0x1; /* use mini-desc */
|
||||
}
|
||||
|
||||
u_desc_ctrl.field.dest_write_en = 1;
|
||||
u_desc_ctrl.field.blk1_cmd_ctrl = 0x7; /* direct fill */
|
||||
u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
|
||||
hw_desc->desc_ctrl = u_desc_ctrl.value;
|
||||
|
||||
return u_desc_ctrl.value;
|
||||
}
|
||||
|
||||
static inline void
|
||||
iop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt,
|
||||
unsigned long flags)
|
||||
{
|
||||
iop3xx_desc_init_xor(desc->hw_desc, src_cnt, flags);
|
||||
}
|
||||
|
||||
/* return the number of operations */
|
||||
static inline int
|
||||
iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt,
|
||||
unsigned long flags)
|
||||
{
|
||||
int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
|
||||
struct iop3xx_desc_aau *hw_desc, *prev_hw_desc, *iter;
|
||||
union {
|
||||
u32 value;
|
||||
struct iop3xx_aau_desc_ctrl field;
|
||||
} u_desc_ctrl;
|
||||
int i, j;
|
||||
|
||||
hw_desc = desc->hw_desc;
|
||||
|
||||
for (i = 0, j = 0; (slot_cnt -= slots_per_op) >= 0;
|
||||
i += slots_per_op, j++) {
|
||||
iter = iop_hw_desc_slot_idx(hw_desc, i);
|
||||
u_desc_ctrl.value = iop3xx_desc_init_xor(iter, src_cnt, flags);
|
||||
u_desc_ctrl.field.dest_write_en = 0;
|
||||
u_desc_ctrl.field.zero_result_en = 1;
|
||||
u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
|
||||
iter->desc_ctrl = u_desc_ctrl.value;
|
||||
|
||||
/* for the subsequent descriptors preserve the store queue
|
||||
* and chain them together
|
||||
*/
|
||||
if (i) {
|
||||
prev_hw_desc =
|
||||
iop_hw_desc_slot_idx(hw_desc, i - slots_per_op);
|
||||
prev_hw_desc->next_desc =
|
||||
(u32) (desc->async_tx.phys + (i << 5));
|
||||
}
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
static inline void
|
||||
iop_desc_init_null_xor(struct iop_adma_desc_slot *desc, int src_cnt,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
|
||||
union {
|
||||
u32 value;
|
||||
struct iop3xx_aau_desc_ctrl field;
|
||||
} u_desc_ctrl;
|
||||
|
||||
u_desc_ctrl.value = 0;
|
||||
switch (src_cnt) {
|
||||
case 25 ... 32:
|
||||
u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
|
||||
hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
|
||||
fallthrough;
|
||||
case 17 ... 24:
|
||||
if (!u_desc_ctrl.field.blk_ctrl) {
|
||||
hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
|
||||
u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
|
||||
}
|
||||
hw_desc->src_edc[AAU_EDCR1_IDX].e_desc_ctrl = 0;
|
||||
fallthrough;
|
||||
case 9 ... 16:
|
||||
if (!u_desc_ctrl.field.blk_ctrl)
|
||||
u_desc_ctrl.field.blk_ctrl = 0x2; /* use EDCR0 */
|
||||
hw_desc->src_edc[AAU_EDCR0_IDX].e_desc_ctrl = 0;
|
||||
fallthrough;
|
||||
case 1 ... 8:
|
||||
if (!u_desc_ctrl.field.blk_ctrl && src_cnt > 4)
|
||||
u_desc_ctrl.field.blk_ctrl = 0x1; /* use mini-desc */
|
||||
}
|
||||
|
||||
u_desc_ctrl.field.dest_write_en = 0;
|
||||
u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
|
||||
hw_desc->desc_ctrl = u_desc_ctrl.value;
|
||||
}
|
||||
|
||||
static inline void iop_desc_set_byte_count(struct iop_adma_desc_slot *desc,
|
||||
struct iop_adma_chan *chan,
|
||||
u32 byte_count)
|
||||
{
|
||||
union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
|
||||
|
||||
switch (chan->device->id) {
|
||||
case DMA0_ID:
|
||||
case DMA1_ID:
|
||||
hw_desc.dma->byte_count = byte_count;
|
||||
break;
|
||||
case AAU_ID:
|
||||
hw_desc.aau->byte_count = byte_count;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
iop_desc_init_interrupt(struct iop_adma_desc_slot *desc,
|
||||
struct iop_adma_chan *chan)
|
||||
{
|
||||
union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
|
||||
|
||||
switch (chan->device->id) {
|
||||
case DMA0_ID:
|
||||
case DMA1_ID:
|
||||
iop_desc_init_memcpy(desc, 1);
|
||||
hw_desc.dma->byte_count = 0;
|
||||
hw_desc.dma->dest_addr = 0;
|
||||
hw_desc.dma->src_addr = 0;
|
||||
break;
|
||||
case AAU_ID:
|
||||
iop_desc_init_null_xor(desc, 2, 1);
|
||||
hw_desc.aau->byte_count = 0;
|
||||
hw_desc.aau->dest_addr = 0;
|
||||
hw_desc.aau->src[0] = 0;
|
||||
hw_desc.aau->src[1] = 0;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
iop_desc_set_zero_sum_byte_count(struct iop_adma_desc_slot *desc, u32 len)
|
||||
{
|
||||
int slots_per_op = desc->slots_per_op;
|
||||
struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
|
||||
int i = 0;
|
||||
|
||||
if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
|
||||
hw_desc->byte_count = len;
|
||||
} else {
|
||||
do {
|
||||
iter = iop_hw_desc_slot_idx(hw_desc, i);
|
||||
iter->byte_count = IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
|
||||
len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
|
||||
i += slots_per_op;
|
||||
} while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT);
|
||||
|
||||
iter = iop_hw_desc_slot_idx(hw_desc, i);
|
||||
iter->byte_count = len;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void iop_desc_set_dest_addr(struct iop_adma_desc_slot *desc,
|
||||
struct iop_adma_chan *chan,
|
||||
dma_addr_t addr)
|
||||
{
|
||||
union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
|
||||
|
||||
switch (chan->device->id) {
|
||||
case DMA0_ID:
|
||||
case DMA1_ID:
|
||||
hw_desc.dma->dest_addr = addr;
|
||||
break;
|
||||
case AAU_ID:
|
||||
hw_desc.aau->dest_addr = addr;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void iop_desc_set_memcpy_src_addr(struct iop_adma_desc_slot *desc,
|
||||
dma_addr_t addr)
|
||||
{
|
||||
struct iop3xx_desc_dma *hw_desc = desc->hw_desc;
|
||||
hw_desc->src_addr = addr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
iop_desc_set_zero_sum_src_addr(struct iop_adma_desc_slot *desc, int src_idx,
|
||||
dma_addr_t addr)
|
||||
{
|
||||
|
||||
struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
|
||||
int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
|
||||
int i;
|
||||
|
||||
for (i = 0; (slot_cnt -= slots_per_op) >= 0;
|
||||
i += slots_per_op, addr += IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
|
||||
iter = iop_hw_desc_slot_idx(hw_desc, i);
|
||||
iop3xx_aau_desc_set_src_addr(iter, src_idx, addr);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void iop_desc_set_xor_src_addr(struct iop_adma_desc_slot *desc,
|
||||
int src_idx, dma_addr_t addr)
|
||||
{
|
||||
|
||||
struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
|
||||
int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
|
||||
int i;
|
||||
|
||||
for (i = 0; (slot_cnt -= slots_per_op) >= 0;
|
||||
i += slots_per_op, addr += IOP_ADMA_XOR_MAX_BYTE_COUNT) {
|
||||
iter = iop_hw_desc_slot_idx(hw_desc, i);
|
||||
iop3xx_aau_desc_set_src_addr(iter, src_idx, addr);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc,
|
||||
u32 next_desc_addr)
|
||||
{
|
||||
/* hw_desc->next_desc is the same location for all channels */
|
||||
union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
|
||||
|
||||
iop_paranoia(hw_desc.dma->next_desc);
|
||||
hw_desc.dma->next_desc = next_desc_addr;
|
||||
}
|
||||
|
||||
static inline u32 iop_desc_get_next_desc(struct iop_adma_desc_slot *desc)
|
||||
{
|
||||
/* hw_desc->next_desc is the same location for all channels */
|
||||
union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
|
||||
return hw_desc.dma->next_desc;
|
||||
}
|
||||
|
||||
static inline void iop_desc_clear_next_desc(struct iop_adma_desc_slot *desc)
|
||||
{
|
||||
/* hw_desc->next_desc is the same location for all channels */
|
||||
union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
|
||||
hw_desc.dma->next_desc = 0;
|
||||
}
|
||||
|
||||
static inline void iop_desc_set_block_fill_val(struct iop_adma_desc_slot *desc,
|
||||
u32 val)
|
||||
{
|
||||
struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
|
||||
hw_desc->src[0] = val;
|
||||
}
|
||||
|
||||
static inline enum sum_check_flags
|
||||
iop_desc_get_zero_result(struct iop_adma_desc_slot *desc)
|
||||
{
|
||||
struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
|
||||
struct iop3xx_aau_desc_ctrl desc_ctrl = hw_desc->desc_ctrl_field;
|
||||
|
||||
iop_paranoia(!(desc_ctrl.tx_complete && desc_ctrl.zero_result_en));
|
||||
return desc_ctrl.zero_result_err << SUM_CHECK_P;
|
||||
}
|
||||
|
||||
static inline void iop_chan_append(struct iop_adma_chan *chan)
|
||||
{
|
||||
u32 dma_chan_ctrl;
|
||||
|
||||
dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
|
||||
dma_chan_ctrl |= 0x2;
|
||||
__raw_writel(dma_chan_ctrl, DMA_CCR(chan));
|
||||
}
|
||||
|
||||
static inline u32 iop_chan_get_status(struct iop_adma_chan *chan)
|
||||
{
|
||||
return __raw_readl(DMA_CSR(chan));
|
||||
}
|
||||
|
||||
static inline void iop_chan_disable(struct iop_adma_chan *chan)
|
||||
{
|
||||
u32 dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
|
||||
dma_chan_ctrl &= ~1;
|
||||
__raw_writel(dma_chan_ctrl, DMA_CCR(chan));
|
||||
}
|
||||
|
||||
static inline void iop_chan_enable(struct iop_adma_chan *chan)
|
||||
{
|
||||
u32 dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
|
||||
|
||||
dma_chan_ctrl |= 1;
|
||||
__raw_writel(dma_chan_ctrl, DMA_CCR(chan));
|
||||
}
|
||||
|
||||
static inline void iop_adma_device_clear_eot_status(struct iop_adma_chan *chan)
|
||||
{
|
||||
u32 status = __raw_readl(DMA_CSR(chan));
|
||||
status &= (1 << 9);
|
||||
__raw_writel(status, DMA_CSR(chan));
|
||||
}
|
||||
|
||||
static inline void iop_adma_device_clear_eoc_status(struct iop_adma_chan *chan)
|
||||
{
|
||||
u32 status = __raw_readl(DMA_CSR(chan));
|
||||
status &= (1 << 8);
|
||||
__raw_writel(status, DMA_CSR(chan));
|
||||
}
|
||||
|
||||
static inline void iop_adma_device_clear_err_status(struct iop_adma_chan *chan)
|
||||
{
|
||||
u32 status = __raw_readl(DMA_CSR(chan));
|
||||
|
||||
switch (chan->device->id) {
|
||||
case DMA0_ID:
|
||||
case DMA1_ID:
|
||||
status &= (1 << 5) | (1 << 3) | (1 << 2) | (1 << 1);
|
||||
break;
|
||||
case AAU_ID:
|
||||
status &= (1 << 5);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
__raw_writel(status, DMA_CSR(chan));
|
||||
}
|
||||
|
||||
static inline int
|
||||
iop_is_err_int_parity(unsigned long status, struct iop_adma_chan *chan)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
iop_is_err_mcu_abort(unsigned long status, struct iop_adma_chan *chan)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
iop_is_err_int_tabort(unsigned long status, struct iop_adma_chan *chan)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
iop_is_err_int_mabort(unsigned long status, struct iop_adma_chan *chan)
|
||||
{
|
||||
return test_bit(5, &status);
|
||||
}
|
||||
|
||||
static inline int
|
||||
iop_is_err_pci_tabort(unsigned long status, struct iop_adma_chan *chan)
|
||||
{
|
||||
switch (chan->device->id) {
|
||||
case DMA0_ID:
|
||||
case DMA1_ID:
|
||||
return test_bit(2, &status);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
iop_is_err_pci_mabort(unsigned long status, struct iop_adma_chan *chan)
|
||||
{
|
||||
switch (chan->device->id) {
|
||||
case DMA0_ID:
|
||||
case DMA1_ID:
|
||||
return test_bit(3, &status);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
iop_is_err_split_tx(unsigned long status, struct iop_adma_chan *chan)
|
||||
{
|
||||
switch (chan->device->id) {
|
||||
case DMA0_ID:
|
||||
case DMA1_ID:
|
||||
return test_bit(1, &status);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif /* _ADMA_H */
|
|
@ -2286,9 +2286,14 @@ static int gpi_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
static const struct of_device_id gpi_of_match[] = {
|
||||
{ .compatible = "qcom,sc7280-gpi-dma", .data = (void *)0x10000 },
|
||||
{ .compatible = "qcom,sdm845-gpi-dma", .data = (void *)0x0 },
|
||||
{ .compatible = "qcom,sm6350-gpi-dma", .data = (void *)0x10000 },
|
||||
/*
|
||||
* Do not grow the list for compatible devices. Instead use
|
||||
* qcom,sdm845-gpi-dma (for ee_offset = 0x0) or qcom,sm6350-gpi-dma
|
||||
* (for ee_offset = 0x10000).
|
||||
*/
|
||||
{ .compatible = "qcom,sc7280-gpi-dma", .data = (void *)0x10000 },
|
||||
{ .compatible = "qcom,sm8150-gpi-dma", .data = (void *)0x0 },
|
||||
{ .compatible = "qcom,sm8250-gpi-dma", .data = (void *)0x0 },
|
||||
{ .compatible = "qcom,sm8350-gpi-dma", .data = (void *)0x10000 },
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Renesas SuperH DMA Engine support
|
||||
*
|
||||
* Copyright (C) 2013 Renesas Electronics, Inc.
|
||||
*/
|
||||
|
||||
#ifndef SHDMA_ARM_H
|
||||
#define SHDMA_ARM_H
|
||||
|
||||
#include "shdma.h"
|
||||
|
||||
/* Transmit sizes and respective CHCR register values */
|
||||
enum {
|
||||
XMIT_SZ_8BIT = 0,
|
||||
XMIT_SZ_16BIT = 1,
|
||||
XMIT_SZ_32BIT = 2,
|
||||
XMIT_SZ_64BIT = 7,
|
||||
XMIT_SZ_128BIT = 3,
|
||||
XMIT_SZ_256BIT = 4,
|
||||
XMIT_SZ_512BIT = 5,
|
||||
};
|
||||
|
||||
/* log2(size / 8) - used to calculate number of transfers */
|
||||
#define SH_DMAE_TS_SHIFT { \
|
||||
[XMIT_SZ_8BIT] = 0, \
|
||||
[XMIT_SZ_16BIT] = 1, \
|
||||
[XMIT_SZ_32BIT] = 2, \
|
||||
[XMIT_SZ_64BIT] = 3, \
|
||||
[XMIT_SZ_128BIT] = 4, \
|
||||
[XMIT_SZ_256BIT] = 5, \
|
||||
[XMIT_SZ_512BIT] = 6, \
|
||||
}
|
||||
|
||||
#define TS_LOW_BIT 0x3 /* --xx */
|
||||
#define TS_HI_BIT 0xc /* xx-- */
|
||||
|
||||
#define TS_LOW_SHIFT (3)
|
||||
#define TS_HI_SHIFT (20 - 2) /* 2 bits for shifted low TS */
|
||||
|
||||
#define TS_INDEX2VAL(i) \
|
||||
((((i) & TS_LOW_BIT) << TS_LOW_SHIFT) |\
|
||||
(((i) & TS_HI_BIT) << TS_HI_SHIFT))
|
||||
|
||||
#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL((xmit_sz)))
|
||||
#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL((xmit_sz)))
|
||||
|
||||
#endif
|
|
@ -161,7 +161,10 @@
|
|||
#define TEGRA_GPCDMA_BURST_COMPLETION_TIMEOUT 5000 /* 5 msec */
|
||||
|
||||
/* Channel base address offset from GPCDMA base address */
|
||||
#define TEGRA_GPCDMA_CHANNEL_BASE_ADD_OFFSET 0x20000
|
||||
#define TEGRA_GPCDMA_CHANNEL_BASE_ADDR_OFFSET 0x10000
|
||||
|
||||
/* Default channel mask reserving channel0 */
|
||||
#define TEGRA_GPCDMA_DEFAULT_CHANNEL_MASK 0xfffffffe
|
||||
|
||||
struct tegra_dma;
|
||||
struct tegra_dma_channel;
|
||||
|
@ -246,6 +249,7 @@ struct tegra_dma {
|
|||
const struct tegra_dma_chip_data *chip_data;
|
||||
unsigned long sid_m2d_reserved;
|
||||
unsigned long sid_d2m_reserved;
|
||||
u32 chan_mask;
|
||||
void __iomem *base_addr;
|
||||
struct device *dev;
|
||||
struct dma_device dma_dev;
|
||||
|
@ -1288,7 +1292,7 @@ static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec,
|
|||
}
|
||||
|
||||
static const struct tegra_dma_chip_data tegra186_dma_chip_data = {
|
||||
.nr_channels = 31,
|
||||
.nr_channels = 32,
|
||||
.channel_reg_size = SZ_64K,
|
||||
.max_dma_count = SZ_1G,
|
||||
.hw_support_pause = false,
|
||||
|
@ -1296,7 +1300,7 @@ static const struct tegra_dma_chip_data tegra186_dma_chip_data = {
|
|||
};
|
||||
|
||||
static const struct tegra_dma_chip_data tegra194_dma_chip_data = {
|
||||
.nr_channels = 31,
|
||||
.nr_channels = 32,
|
||||
.channel_reg_size = SZ_64K,
|
||||
.max_dma_count = SZ_1G,
|
||||
.hw_support_pause = true,
|
||||
|
@ -1304,7 +1308,7 @@ static const struct tegra_dma_chip_data tegra194_dma_chip_data = {
|
|||
};
|
||||
|
||||
static const struct tegra_dma_chip_data tegra234_dma_chip_data = {
|
||||
.nr_channels = 31,
|
||||
.nr_channels = 32,
|
||||
.channel_reg_size = SZ_64K,
|
||||
.max_dma_count = SZ_1G,
|
||||
.hw_support_pause = true,
|
||||
|
@ -1380,15 +1384,28 @@ static int tegra_dma_probe(struct platform_device *pdev)
|
|||
}
|
||||
stream_id = iommu_spec->ids[0] & 0xffff;
|
||||
|
||||
ret = device_property_read_u32(&pdev->dev, "dma-channel-mask",
|
||||
&tdma->chan_mask);
|
||||
if (ret) {
|
||||
dev_warn(&pdev->dev,
|
||||
"Missing dma-channel-mask property, using default channel mask %#x\n",
|
||||
TEGRA_GPCDMA_DEFAULT_CHANNEL_MASK);
|
||||
tdma->chan_mask = TEGRA_GPCDMA_DEFAULT_CHANNEL_MASK;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&tdma->dma_dev.channels);
|
||||
for (i = 0; i < cdata->nr_channels; i++) {
|
||||
struct tegra_dma_channel *tdc = &tdma->channels[i];
|
||||
|
||||
/* Check for channel mask */
|
||||
if (!(tdma->chan_mask & BIT(i)))
|
||||
continue;
|
||||
|
||||
tdc->irq = platform_get_irq(pdev, i);
|
||||
if (tdc->irq < 0)
|
||||
return tdc->irq;
|
||||
|
||||
tdc->chan_base_offset = TEGRA_GPCDMA_CHANNEL_BASE_ADD_OFFSET +
|
||||
tdc->chan_base_offset = TEGRA_GPCDMA_CHANNEL_BASE_ADDR_OFFSET +
|
||||
i * cdata->channel_reg_size;
|
||||
snprintf(tdc->name, sizeof(tdc->name), "gpcdma.%d", i);
|
||||
tdc->tdma = tdma;
|
||||
|
@ -1449,8 +1466,8 @@ static int tegra_dma_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "GPC DMA driver register %d channels\n",
|
||||
cdata->nr_channels);
|
||||
dev_info(&pdev->dev, "GPC DMA driver register %lu channels\n",
|
||||
hweight_long(tdma->chan_mask));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1473,6 +1490,9 @@ static int __maybe_unused tegra_dma_pm_suspend(struct device *dev)
|
|||
for (i = 0; i < tdma->chip_data->nr_channels; i++) {
|
||||
struct tegra_dma_channel *tdc = &tdma->channels[i];
|
||||
|
||||
if (!(tdma->chan_mask & BIT(i)))
|
||||
continue;
|
||||
|
||||
if (tdc->dma_desc) {
|
||||
dev_err(tdma->dev, "channel %u busy\n", i);
|
||||
return -EBUSY;
|
||||
|
@ -1492,6 +1512,9 @@ static int __maybe_unused tegra_dma_pm_resume(struct device *dev)
|
|||
for (i = 0; i < tdma->chip_data->nr_channels; i++) {
|
||||
struct tegra_dma_channel *tdc = &tdma->channels[i];
|
||||
|
||||
if (!(tdma->chan_mask & BIT(i)))
|
||||
continue;
|
||||
|
||||
tegra_dma_program_sid(tdc, tdc->stream_id);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ config DMA_OMAP
|
|||
DMA engine is found on OMAP and DRA7xx parts.
|
||||
|
||||
config TI_K3_UDMA
|
||||
bool "Texas Instruments UDMA support"
|
||||
tristate "Texas Instruments UDMA support"
|
||||
depends on ARCH_K3
|
||||
depends on TI_SCI_PROTOCOL
|
||||
depends on TI_SCI_INTA_IRQCHIP
|
||||
|
@ -48,7 +48,7 @@ config TI_K3_UDMA
|
|||
DMA engine is used in AM65x and j721e.
|
||||
|
||||
config TI_K3_UDMA_GLUE_LAYER
|
||||
bool "Texas Instruments UDMA Glue layer for non DMAengine users"
|
||||
tristate "Texas Instruments UDMA Glue layer for non DMAengine users"
|
||||
depends on ARCH_K3
|
||||
depends on TI_K3_UDMA
|
||||
help
|
||||
|
@ -56,7 +56,8 @@ config TI_K3_UDMA_GLUE_LAYER
|
|||
If unsure, say N.
|
||||
|
||||
config TI_K3_PSIL
|
||||
bool
|
||||
tristate
|
||||
default TI_K3_UDMA
|
||||
|
||||
config TI_DMA_CROSSBAR
|
||||
bool
|
||||
|
|
|
@ -4,11 +4,12 @@ obj-$(CONFIG_TI_EDMA) += edma.o
|
|||
obj-$(CONFIG_DMA_OMAP) += omap-dma.o
|
||||
obj-$(CONFIG_TI_K3_UDMA) += k3-udma.o
|
||||
obj-$(CONFIG_TI_K3_UDMA_GLUE_LAYER) += k3-udma-glue.o
|
||||
obj-$(CONFIG_TI_K3_PSIL) += k3-psil.o \
|
||||
k3-psil-am654.o \
|
||||
k3-psil-j721e.o \
|
||||
k3-psil-j7200.o \
|
||||
k3-psil-am64.o \
|
||||
k3-psil-j721s2.o \
|
||||
k3-psil-am62.o
|
||||
k3-psil-lib-objs := k3-psil.o \
|
||||
k3-psil-am654.o \
|
||||
k3-psil-j721e.o \
|
||||
k3-psil-j7200.o \
|
||||
k3-psil-am64.o \
|
||||
k3-psil-j721s2.o \
|
||||
k3-psil-am62.o
|
||||
obj-$(CONFIG_TI_K3_PSIL) += k3-psil-lib.o
|
||||
obj-$(CONFIG_TI_DMA_CROSSBAR) += dma-crossbar.o
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mutex.h>
|
||||
|
@ -101,3 +102,4 @@ int psil_set_new_ep_config(struct device *dev, const char *name,
|
|||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(psil_set_new_ep_config);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
@ -1436,4 +1437,6 @@ static int __init k3_udma_glue_class_init(void)
|
|||
{
|
||||
return class_register(&k3_udma_glue_devclass);
|
||||
}
|
||||
arch_initcall(k3_udma_glue_class_init);
|
||||
|
||||
module_init(k3_udma_glue_class_init);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
@ -4335,18 +4336,10 @@ static const struct of_device_id udma_of_match[] = {
|
|||
.compatible = "ti,j721e-navss-mcu-udmap",
|
||||
.data = &j721e_mcu_data,
|
||||
},
|
||||
{ /* Sentinel */ },
|
||||
};
|
||||
|
||||
static const struct of_device_id bcdma_of_match[] = {
|
||||
{
|
||||
.compatible = "ti,am64-dmss-bcdma",
|
||||
.data = &am64_bcdma_data,
|
||||
},
|
||||
{ /* Sentinel */ },
|
||||
};
|
||||
|
||||
static const struct of_device_id pktdma_of_match[] = {
|
||||
{
|
||||
.compatible = "ti,am64-dmss-pktdma",
|
||||
.data = &am64_pktdma_data,
|
||||
|
@ -5271,14 +5264,9 @@ static int udma_probe(struct platform_device *pdev)
|
|||
return -ENOMEM;
|
||||
|
||||
match = of_match_node(udma_of_match, dev->of_node);
|
||||
if (!match)
|
||||
match = of_match_node(bcdma_of_match, dev->of_node);
|
||||
if (!match) {
|
||||
match = of_match_node(pktdma_of_match, dev->of_node);
|
||||
if (!match) {
|
||||
dev_err(dev, "No compatible match found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
dev_err(dev, "No compatible match found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
ud->match_data = match->data;
|
||||
|
||||
|
@ -5511,27 +5499,9 @@ static struct platform_driver udma_driver = {
|
|||
},
|
||||
.probe = udma_probe,
|
||||
};
|
||||
builtin_platform_driver(udma_driver);
|
||||
|
||||
static struct platform_driver bcdma_driver = {
|
||||
.driver = {
|
||||
.name = "ti-bcdma",
|
||||
.of_match_table = bcdma_of_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe = udma_probe,
|
||||
};
|
||||
builtin_platform_driver(bcdma_driver);
|
||||
|
||||
static struct platform_driver pktdma_driver = {
|
||||
.driver = {
|
||||
.name = "ti-pktdma",
|
||||
.of_match_table = pktdma_of_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe = udma_probe,
|
||||
};
|
||||
builtin_platform_driver(pktdma_driver);
|
||||
module_platform_driver(udma_driver);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
/* Private interfaces to UDMA */
|
||||
#include "k3-udma-private.c"
|
||||
|
|
|
@ -1659,6 +1659,8 @@ static void xilinx_dma_issue_pending(struct dma_chan *dchan)
|
|||
* xilinx_dma_device_config - Configure the DMA channel
|
||||
* @dchan: DMA channel
|
||||
* @config: channel configuration
|
||||
*
|
||||
* Return: 0 always.
|
||||
*/
|
||||
static int xilinx_dma_device_config(struct dma_chan *dchan,
|
||||
struct dma_slave_config *config)
|
||||
|
@ -2924,7 +2926,7 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
|
|||
* @xdev: Driver specific device structure
|
||||
* @node: Device node
|
||||
*
|
||||
* Return: 0 always.
|
||||
* Return: '0' on success and failure value on error.
|
||||
*/
|
||||
static int xilinx_dma_child_probe(struct xilinx_dma_device *xdev,
|
||||
struct device_node *node)
|
||||
|
|
|
@ -730,6 +730,7 @@ struct irq_domain *of_msi_get_domain(struct device *dev,
|
|||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_msi_get_domain);
|
||||
|
||||
/**
|
||||
* of_msi_configure - Set the msi_domain field of a device
|
||||
|
|
|
@ -295,7 +295,7 @@ struct dsa_completion_record {
|
|||
};
|
||||
|
||||
uint32_t delta_rec_size;
|
||||
uint32_t crc_val;
|
||||
uint64_t crc_val;
|
||||
|
||||
/* DIF check & strip */
|
||||
struct {
|
||||
|
|
Loading…
Reference in New Issue