mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-08-18 02:22:47 -07:00
Merge branch 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma
Pull slave-dmaengine updates from Vinod Koul:
"This pull brings:
- Andy's DW driver updates
- Guennadi's sh driver updates
- Pl08x driver fixes from Tomasz & Alban
- Improvements to mmp_pdma by Daniel
- TI EDMA fixes by Joel
- New drivers:
- Hisilicon k3dma driver
- Renesas rcar dma driver
- New API for publishing slave driver capablities
- Various fixes across the subsystem by Andy, Jingoo, Sachin etc..."
* 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma: (94 commits)
dma: edma: Remove limits on number of slots
dma: edma: Leave linked to Null slot instead of DUMMY slot
dma: edma: Find missed events and issue them
ARM: edma: Add function to manually trigger an EDMA channel
dma: edma: Write out and handle MAX_NR_SG at a given time
dma: edma: Setup parameters to DMA MAX_NR_SG at a time
dmaengine: pl330: use dma_set_max_seg_size to set the sg limit
dmaengine: dma_slave_caps: remove sg entries
dma: replace devm_request_and_ioremap by devm_ioremap_resource
dma: ste_dma40: Fix potential null pointer dereference
dma: ste_dma40: Remove duplicate const
dma: imx-dma: Remove redundant NULL check
dma: dmagengine: fix function names in comments
dma: add driver for R-Car HPB-DMAC
dma: k3dma: use devm_ioremap_resource() instead of devm_request_and_ioremap()
dma: imx-sdma: Staticize sdma_driver_data structures
pch_dma: Add MODULE_DEVICE_TABLE
dmaengine: PL08x: Add cyclic transfer support
dmaengine: PL08x: Fix reading the byte count in cctl
dmaengine: PL08x: Add support for different maximum transfer size
...
This commit is contained in:
commit
ec5b103ecf
54 files changed
+3240
-737
No files matched your search
@@ -1,7 +1,12 @@
|
||||
* Freescale Smart Direct Memory Access (SDMA) Controller for i.MX
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "fsl,<chip>-sdma"
|
||||
- compatible : Should be "fsl,imx31-sdma", "fsl,imx31-to1-sdma",
|
||||
"fsl,imx31-to2-sdma", "fsl,imx35-sdma", "fsl,imx35-to1-sdma",
|
||||
"fsl,imx35-to2-sdma", "fsl,imx51-sdma", "fsl,imx53-sdma" or
|
||||
"fsl,imx6q-sdma". The -to variants should be preferred since they
|
||||
allow to determnine the correct ROM script addresses needed for
|
||||
the driver to work without additional firmware.
|
||||
- reg : Should contain SDMA registers location and length
|
||||
- interrupts : Should contain SDMA interrupt
|
||||
- #dma-cells : Must be <3>.
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
* Hisilicon K3 DMA controller
|
||||
|
||||
See dma.txt first
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "hisilicon,k3-dma-1.0"
|
||||
- reg: Should contain DMA registers location and length.
|
||||
- interrupts: Should contain one interrupt shared by all channel
|
||||
- #dma-cells: see dma.txt, should be 1, para number
|
||||
- dma-channels: physical channels supported
|
||||
- dma-requests: virtual channels supported, each virtual channel
|
||||
have specific request line
|
||||
- clocks: clock required
|
||||
|
||||
Example:
|
||||
|
||||
Controller:
|
||||
dma0: dma@fcd02000 {
|
||||
compatible = "hisilicon,k3-dma-1.0";
|
||||
reg = <0xfcd02000 0x1000>;
|
||||
#dma-cells = <1>;
|
||||
dma-channels = <16>;
|
||||
dma-requests = <27>;
|
||||
interrupts = <0 12 4>;
|
||||
clocks = <&pclk>;
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
Client:
|
||||
Use specific request line passing from dmax
|
||||
For example, i2c0 read channel request line is 18, while write channel use 19
|
||||
|
||||
i2c0: i2c@fcb08000 {
|
||||
compatible = "snps,designware-i2c";
|
||||
dmas = <&dma0 18 /* read channel */
|
||||
&dma0 19>; /* write channel */
|
||||
dma-names = "rx", "tx";
|
||||
};
|
||||
|
||||
i2c1: i2c@fcb09000 {
|
||||
compatible = "snps,designware-i2c";
|
||||
dmas = <&dma0 20 /* read channel */
|
||||
&dma0 21>; /* write channel */
|
||||
dma-names = "rx", "tx";
|
||||
};
|
||||
|
||||
@@ -22,42 +22,51 @@ Optional properties (currently unused):
|
||||
* DMA controller
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "renesas,shdma"
|
||||
- compatible: should be of the form "renesas,shdma-<soc>", where <soc> should
|
||||
be replaced with the desired SoC model, e.g.
|
||||
"renesas,shdma-r8a73a4" for the system DMAC on r8a73a4 SoC
|
||||
|
||||
Example:
|
||||
dmac: dma-mux0 {
|
||||
dmac: dma-multiplexer@0 {
|
||||
compatible = "renesas,shdma-mux";
|
||||
#dma-cells = <1>;
|
||||
dma-channels = <6>;
|
||||
dma-channels = <20>;
|
||||
dma-requests = <256>;
|
||||
reg = <0 0>; /* Needed for AUXDATA */
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
dma0: shdma@fe008020 {
|
||||
compatible = "renesas,shdma";
|
||||
reg = <0xfe008020 0x270>,
|
||||
<0xfe009000 0xc>;
|
||||
dma0: dma-controller@e6700020 {
|
||||
compatible = "renesas,shdma-r8a73a4";
|
||||
reg = <0 0xe6700020 0 0x89e0>;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <0 34 4
|
||||
0 28 4
|
||||
0 29 4
|
||||
0 30 4
|
||||
0 31 4
|
||||
0 32 4
|
||||
0 33 4>;
|
||||
interrupts = <0 220 4
|
||||
0 200 4
|
||||
0 201 4
|
||||
0 202 4
|
||||
0 203 4
|
||||
0 204 4
|
||||
0 205 4
|
||||
0 206 4
|
||||
0 207 4
|
||||
0 208 4
|
||||
0 209 4
|
||||
0 210 4
|
||||
0 211 4
|
||||
0 212 4
|
||||
0 213 4
|
||||
0 214 4
|
||||
0 215 4
|
||||
0 216 4
|
||||
0 217 4
|
||||
0 218 4
|
||||
0 219 4>;
|
||||
interrupt-names = "error",
|
||||
"ch0", "ch1", "ch2", "ch3",
|
||||
"ch4", "ch5";
|
||||
};
|
||||
|
||||
dma1: shdma@fe018020 {
|
||||
...
|
||||
};
|
||||
|
||||
dma2: shdma@fe028020 {
|
||||
...
|
||||
"ch4", "ch5", "ch6", "ch7",
|
||||
"ch8", "ch9", "ch10", "ch11",
|
||||
"ch12", "ch13", "ch14", "ch15",
|
||||
"ch16", "ch17", "ch18", "ch19";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -299,3 +299,6 @@ PWM
|
||||
PHY
|
||||
devm_usb_get_phy()
|
||||
devm_usb_put_phy()
|
||||
|
||||
SLAVE DMA ENGINE
|
||||
devm_acpi_dma_controller_register()
|
||||
@@ -7204,6 +7204,7 @@ F: drivers/tty/serial
|
||||
|
||||
SYNOPSYS DESIGNWARE DMAC DRIVER
|
||||
M: Viresh Kumar <viresh.linux@gmail.com>
|
||||
M: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
||||
S: Maintained
|
||||
F: include/linux/dw_dmac.h
|
||||
F: drivers/dma/dw/
|
||||
|
||||
@@ -1235,6 +1235,23 @@ void edma_resume(unsigned channel)
|
||||
}
|
||||
EXPORT_SYMBOL(edma_resume);
|
||||
|
||||
int edma_trigger_channel(unsigned channel)
|
||||
{
|
||||
unsigned ctlr;
|
||||
unsigned int mask;
|
||||
|
||||
ctlr = EDMA_CTLR(channel);
|
||||
channel = EDMA_CHAN_SLOT(channel);
|
||||
mask = BIT(channel & 0x1f);
|
||||
|
||||
edma_shadow0_write_array(ctlr, SH_ESR, (channel >> 5), mask);
|
||||
|
||||
pr_debug("EDMA: ESR%d %08x\n", (channel >> 5),
|
||||
edma_shadow0_read_array(ctlr, SH_ESR, (channel >> 5)));
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(edma_trigger_channel);
|
||||
|
||||
/**
|
||||
* edma_start - start dma on a channel
|
||||
* @channel: channel being activated
|
||||
|
||||
@@ -61,25 +61,8 @@ void __init mx25_init_irq(void)
|
||||
mxc_init_irq(MX25_IO_ADDRESS(MX25_AVIC_BASE_ADDR));
|
||||
}
|
||||
|
||||
static struct sdma_script_start_addrs imx25_sdma_script __initdata = {
|
||||
.ap_2_ap_addr = 729,
|
||||
.uart_2_mcu_addr = 904,
|
||||
.per_2_app_addr = 1255,
|
||||
.mcu_2_app_addr = 834,
|
||||
.uartsh_2_mcu_addr = 1120,
|
||||
.per_2_shp_addr = 1329,
|
||||
.mcu_2_shp_addr = 1048,
|
||||
.ata_2_mcu_addr = 1560,
|
||||
.mcu_2_ata_addr = 1479,
|
||||
.app_2_per_addr = 1189,
|
||||
.app_2_mcu_addr = 770,
|
||||
.shp_2_per_addr = 1407,
|
||||
.shp_2_mcu_addr = 979,
|
||||
};
|
||||
|
||||
static struct sdma_platform_data imx25_sdma_pdata __initdata = {
|
||||
.fw_name = "sdma-imx25.bin",
|
||||
.script_addrs = &imx25_sdma_script,
|
||||
};
|
||||
|
||||
static const struct resource imx25_audmux_res[] __initconst = {
|
||||
|
||||
@@ -103,22 +103,8 @@ void __init mx53_init_irq(void)
|
||||
tzic_init_irq(MX53_IO_ADDRESS(MX53_TZIC_BASE_ADDR));
|
||||
}
|
||||
|
||||
static struct sdma_script_start_addrs imx51_sdma_script __initdata = {
|
||||
.ap_2_ap_addr = 642,
|
||||
.uart_2_mcu_addr = 817,
|
||||
.mcu_2_app_addr = 747,
|
||||
.mcu_2_shp_addr = 961,
|
||||
.ata_2_mcu_addr = 1473,
|
||||
.mcu_2_ata_addr = 1392,
|
||||
.app_2_per_addr = 1033,
|
||||
.app_2_mcu_addr = 683,
|
||||
.shp_2_per_addr = 1251,
|
||||
.shp_2_mcu_addr = 892,
|
||||
};
|
||||
|
||||
static struct sdma_platform_data imx51_sdma_pdata __initdata = {
|
||||
.fw_name = "sdma-imx51.bin",
|
||||
.script_addrs = &imx51_sdma_script,
|
||||
};
|
||||
|
||||
static const struct resource imx51_audmux_res[] __initconst = {
|
||||
|
||||
@@ -308,6 +308,15 @@ config DMA_JZ4740
|
||||
select DMA_ENGINE
|
||||
select DMA_VIRTUAL_CHANNELS
|
||||
|
||||
config K3_DMA
|
||||
tristate "Hisilicon K3 DMA support"
|
||||
depends on ARCH_HI3xxx
|
||||
select DMA_ENGINE
|
||||
select DMA_VIRTUAL_CHANNELS
|
||||
help
|
||||
Support the DMA engine for Hisilicon K3 platform
|
||||
devices.
|
||||
|
||||
config DMA_ENGINE
|
||||
bool
|
||||
|
||||
|
||||
@@ -40,3 +40,4 @@ obj-$(CONFIG_DMA_OMAP) += omap-dma.o
|
||||
obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o
|
||||
obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o
|
||||
obj-$(CONFIG_TI_CPPI41) += cppi41.o
|
||||
obj-$(CONFIG_K3_DMA) += k3dma.o
|
||||
@@ -43,7 +43,6 @@ static int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp,
|
||||
struct list_head resource_list;
|
||||
struct resource_list_entry *rentry;
|
||||
resource_size_t mem = 0, irq = 0;
|
||||
u32 vendor_id;
|
||||
int ret;
|
||||
|
||||
if (grp->shared_info_length != sizeof(struct acpi_csrt_shared_info))
|
||||
@@ -73,9 +72,8 @@ static int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp,
|
||||
if (si->mmio_base_low != mem || si->gsi_interrupt != irq)
|
||||
return 0;
|
||||
|
||||
vendor_id = le32_to_cpu(grp->vendor_id);
|
||||
dev_dbg(&adev->dev, "matches with %.4s%04X (rev %u)\n",
|
||||
(char *)&vendor_id, grp->device_id, grp->revision);
|
||||
(char *)&grp->vendor_id, grp->device_id, grp->revision);
|
||||
|
||||
/* Check if the request line range is available */
|
||||
if (si->base_request_line == 0 && si->num_handshake_signals == 0)
|
||||
|
||||
+363
-138
File diff suppressed because it is too large.
Load diff
+27
-1
@@ -509,7 +509,33 @@ static struct dma_chan *private_candidate(const dma_cap_mask_t *mask,
|
||||
}
|
||||
|
||||
/**
|
||||
* dma_request_channel - try to allocate an exclusive channel
|
||||
* dma_request_slave_channel - try to get specific channel exclusively
|
||||
* @chan: target channel
|
||||
*/
|
||||
struct dma_chan *dma_get_slave_channel(struct dma_chan *chan)
|
||||
{
|
||||
int err = -EBUSY;
|
||||
|
||||
/* lock against __dma_request_channel */
|
||||
mutex_lock(&dma_list_mutex);
|
||||
|
||||
if (chan->client_count == 0) {
|
||||
err = dma_chan_get(chan);
|
||||
if (err)
|
||||
pr_debug("%s: failed to get %s: (%d)\n",
|
||||
__func__, dma_chan_name(chan), err);
|
||||
} else
|
||||
chan = NULL;
|
||||
|
||||
mutex_unlock(&dma_list_mutex);
|
||||
|
||||
|
||||
return chan;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dma_get_slave_channel);
|
||||
|
||||
/**
|
||||
* __dma_request_channel - try to allocate an exclusive channel
|
||||
* @mask: capabilities that the channel must satisfy
|
||||
* @fn: optional callback to disposition available channels
|
||||
* @fn_param: opaque parameter to pass to dma_filter_fn
|
||||
|
||||
+24
-15
@@ -37,16 +37,22 @@
|
||||
* which does not support descriptor writeback.
|
||||
*/
|
||||
|
||||
static inline bool is_request_line_unset(struct dw_dma_chan *dwc)
|
||||
{
|
||||
return dwc->request_line == (typeof(dwc->request_line))~0;
|
||||
}
|
||||
|
||||
static inline void dwc_set_masters(struct dw_dma_chan *dwc)
|
||||
{
|
||||
struct dw_dma *dw = to_dw_dma(dwc->chan.device);
|
||||
struct dw_dma_slave *dws = dwc->chan.private;
|
||||
unsigned char mmax = dw->nr_masters - 1;
|
||||
|
||||
if (dwc->request_line == ~0) {
|
||||
dwc->src_master = min_t(unsigned char, mmax, dwc_get_sms(dws));
|
||||
dwc->dst_master = min_t(unsigned char, mmax, dwc_get_dms(dws));
|
||||
}
|
||||
if (!is_request_line_unset(dwc))
|
||||
return;
|
||||
|
||||
dwc->src_master = min_t(unsigned char, mmax, dwc_get_sms(dws));
|
||||
dwc->dst_master = min_t(unsigned char, mmax, dwc_get_dms(dws));
|
||||
}
|
||||
|
||||
#define DWC_DEFAULT_CTLLO(_chan) ({ \
|
||||
@@ -644,10 +650,13 @@ static void dw_dma_tasklet(unsigned long data)
|
||||
static irqreturn_t dw_dma_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct dw_dma *dw = dev_id;
|
||||
u32 status;
|
||||
u32 status = dma_readl(dw, STATUS_INT);
|
||||
|
||||
dev_vdbg(dw->dma.dev, "%s: status=0x%x\n", __func__,
|
||||
dma_readl(dw, STATUS_INT));
|
||||
dev_vdbg(dw->dma.dev, "%s: status=0x%x\n", __func__, status);
|
||||
|
||||
/* Check if we have any interrupt from the DMAC */
|
||||
if (!status)
|
||||
return IRQ_NONE;
|
||||
|
||||
/*
|
||||
* Just disable the interrupts. We'll turn them back on in the
|
||||
@@ -984,7 +993,7 @@ set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
|
||||
dwc->direction = sconfig->direction;
|
||||
|
||||
/* Take the request line from slave_id member */
|
||||
if (dwc->request_line == ~0)
|
||||
if (is_request_line_unset(dwc))
|
||||
dwc->request_line = sconfig->slave_id;
|
||||
|
||||
convert_burst(&dwc->dma_sconfig.src_maxburst);
|
||||
@@ -1089,16 +1098,16 @@ dwc_tx_status(struct dma_chan *chan,
|
||||
enum dma_status ret;
|
||||
|
||||
ret = dma_cookie_status(chan, cookie, txstate);
|
||||
if (ret != DMA_SUCCESS) {
|
||||
dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
|
||||
if (ret == DMA_SUCCESS)
|
||||
return ret;
|
||||
|
||||
ret = dma_cookie_status(chan, cookie, txstate);
|
||||
}
|
||||
dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
|
||||
|
||||
ret = dma_cookie_status(chan, cookie, txstate);
|
||||
if (ret != DMA_SUCCESS)
|
||||
dma_set_residue(txstate, dwc_get_residue(dwc));
|
||||
|
||||
if (dwc->paused)
|
||||
if (dwc->paused && ret == DMA_IN_PROGRESS)
|
||||
return DMA_PAUSED;
|
||||
|
||||
return ret;
|
||||
@@ -1560,8 +1569,8 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata)
|
||||
/* Disable BLOCK interrupts as well */
|
||||
channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
|
||||
|
||||
err = devm_request_irq(chip->dev, chip->irq, dw_dma_interrupt, 0,
|
||||
"dw_dmac", dw);
|
||||
err = devm_request_irq(chip->dev, chip->irq, dw_dma_interrupt,
|
||||
IRQF_SHARED, "dw_dmac", dw);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
||||
@@ -253,6 +253,7 @@ static const struct acpi_device_id dw_dma_acpi_id_table[] = {
|
||||
{ "INTL9C60", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, dw_dma_acpi_id_table);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
||||
+122
-40
@@ -56,6 +56,7 @@ struct edma_desc {
|
||||
struct list_head node;
|
||||
int absync;
|
||||
int pset_nr;
|
||||
int processed;
|
||||
struct edmacc_param pset[0];
|
||||
};
|
||||
|
||||
@@ -69,6 +70,7 @@ struct edma_chan {
|
||||
int ch_num;
|
||||
bool alloced;
|
||||
int slot[EDMA_MAX_SLOTS];
|
||||
int missed;
|
||||
struct dma_slave_config cfg;
|
||||
};
|
||||
|
||||
@@ -104,22 +106,34 @@ static void edma_desc_free(struct virt_dma_desc *vdesc)
|
||||
/* Dispatch a queued descriptor to the controller (caller holds lock) */
|
||||
static void edma_execute(struct edma_chan *echan)
|
||||
{
|
||||
struct virt_dma_desc *vdesc = vchan_next_desc(&echan->vchan);
|
||||
struct virt_dma_desc *vdesc;
|
||||
struct edma_desc *edesc;
|
||||
int i;
|
||||
struct device *dev = echan->vchan.chan.device->dev;
|
||||
int i, j, left, nslots;
|
||||
|
||||
if (!vdesc) {
|
||||
echan->edesc = NULL;
|
||||
return;
|
||||
/* If either we processed all psets or we're still not started */
|
||||
if (!echan->edesc ||
|
||||
echan->edesc->pset_nr == echan->edesc->processed) {
|
||||
/* Get next vdesc */
|
||||
vdesc = vchan_next_desc(&echan->vchan);
|
||||
if (!vdesc) {
|
||||
echan->edesc = NULL;
|
||||
return;
|
||||
}
|
||||
list_del(&vdesc->node);
|
||||
echan->edesc = to_edma_desc(&vdesc->tx);
|
||||
}
|
||||
|
||||
list_del(&vdesc->node);
|
||||
edesc = echan->edesc;
|
||||
|
||||
echan->edesc = edesc = to_edma_desc(&vdesc->tx);
|
||||
/* Find out how many left */
|
||||
left = edesc->pset_nr - edesc->processed;
|
||||
nslots = min(MAX_NR_SG, left);
|
||||
|
||||
/* Write descriptor PaRAM set(s) */
|
||||
for (i = 0; i < edesc->pset_nr; i++) {
|
||||
edma_write_slot(echan->slot[i], &edesc->pset[i]);
|
||||
for (i = 0; i < nslots; i++) {
|
||||
j = i + edesc->processed;
|
||||
edma_write_slot(echan->slot[i], &edesc->pset[j]);
|
||||
dev_dbg(echan->vchan.chan.device->dev,
|
||||
"\n pset[%d]:\n"
|
||||
" chnum\t%d\n"
|
||||
@@ -132,24 +146,50 @@ static void edma_execute(struct edma_chan *echan)
|
||||
" bidx\t%08x\n"
|
||||
" cidx\t%08x\n"
|
||||
" lkrld\t%08x\n",
|
||||
i, echan->ch_num, echan->slot[i],
|
||||
edesc->pset[i].opt,
|
||||
edesc->pset[i].src,
|
||||
edesc->pset[i].dst,
|
||||
edesc->pset[i].a_b_cnt,
|
||||
edesc->pset[i].ccnt,
|
||||
edesc->pset[i].src_dst_bidx,
|
||||
edesc->pset[i].src_dst_cidx,
|
||||
edesc->pset[i].link_bcntrld);
|
||||
j, echan->ch_num, echan->slot[i],
|
||||
edesc->pset[j].opt,
|
||||
edesc->pset[j].src,
|
||||
edesc->pset[j].dst,
|
||||
edesc->pset[j].a_b_cnt,
|
||||
edesc->pset[j].ccnt,
|
||||
edesc->pset[j].src_dst_bidx,
|
||||
edesc->pset[j].src_dst_cidx,
|
||||
edesc->pset[j].link_bcntrld);
|
||||
/* Link to the previous slot if not the last set */
|
||||
if (i != (edesc->pset_nr - 1))
|
||||
if (i != (nslots - 1))
|
||||
edma_link(echan->slot[i], echan->slot[i+1]);
|
||||
/* Final pset links to the dummy pset */
|
||||
else
|
||||
edma_link(echan->slot[i], echan->ecc->dummy_slot);
|
||||
}
|
||||
|
||||
edma_start(echan->ch_num);
|
||||
edesc->processed += nslots;
|
||||
|
||||
/*
|
||||
* If this is either the last set in a set of SG-list transactions
|
||||
* then setup a link to the dummy slot, this results in all future
|
||||
* events being absorbed and that's OK because we're done
|
||||
*/
|
||||
if (edesc->processed == edesc->pset_nr)
|
||||
edma_link(echan->slot[nslots-1], echan->ecc->dummy_slot);
|
||||
|
||||
edma_resume(echan->ch_num);
|
||||
|
||||
if (edesc->processed <= MAX_NR_SG) {
|
||||
dev_dbg(dev, "first transfer starting %d\n", echan->ch_num);
|
||||
edma_start(echan->ch_num);
|
||||
}
|
||||
|
||||
/*
|
||||
* This happens due to setup times between intermediate transfers
|
||||
* in long SG lists which have to be broken up into transfers of
|
||||
* MAX_NR_SG
|
||||
*/
|
||||
if (echan->missed) {
|
||||
dev_dbg(dev, "missed event in execute detected\n");
|
||||
edma_clean_channel(echan->ch_num);
|
||||
edma_stop(echan->ch_num);
|
||||
edma_start(echan->ch_num);
|
||||
edma_trigger_channel(echan->ch_num);
|
||||
echan->missed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int edma_terminate_all(struct edma_chan *echan)
|
||||
@@ -222,9 +262,9 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
|
||||
enum dma_slave_buswidth dev_width;
|
||||
u32 burst;
|
||||
struct scatterlist *sg;
|
||||
int i;
|
||||
int acnt, bcnt, ccnt, src, dst, cidx;
|
||||
int src_bidx, dst_bidx, src_cidx, dst_cidx;
|
||||
int i, nslots;
|
||||
|
||||
if (unlikely(!echan || !sgl || !sg_len))
|
||||
return NULL;
|
||||
@@ -247,12 +287,6 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sg_len > MAX_NR_SG) {
|
||||
dev_err(dev, "Exceeded max SG segments %d > %d\n",
|
||||
sg_len, MAX_NR_SG);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
edesc = kzalloc(sizeof(*edesc) + sg_len *
|
||||
sizeof(edesc->pset[0]), GFP_ATOMIC);
|
||||
if (!edesc) {
|
||||
@@ -262,8 +296,10 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
|
||||
|
||||
edesc->pset_nr = sg_len;
|
||||
|
||||
for_each_sg(sgl, sg, sg_len, i) {
|
||||
/* Allocate a PaRAM slot, if needed */
|
||||
/* Allocate a PaRAM slot, if needed */
|
||||
nslots = min_t(unsigned, MAX_NR_SG, sg_len);
|
||||
|
||||
for (i = 0; i < nslots; i++) {
|
||||
if (echan->slot[i] < 0) {
|
||||
echan->slot[i] =
|
||||
edma_alloc_slot(EDMA_CTLR(echan->ch_num),
|
||||
@@ -273,6 +309,10 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure PaRAM sets for each SG */
|
||||
for_each_sg(sgl, sg, sg_len, i) {
|
||||
|
||||
acnt = dev_width;
|
||||
|
||||
@@ -330,6 +370,12 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
|
||||
/* Configure A or AB synchronized transfers */
|
||||
if (edesc->absync)
|
||||
edesc->pset[i].opt |= SYNCDIM;
|
||||
|
||||
/* If this is the last in a current SG set of transactions,
|
||||
enable interrupts so that next set is processed */
|
||||
if (!((i+1) % MAX_NR_SG))
|
||||
edesc->pset[i].opt |= TCINTEN;
|
||||
|
||||
/* If this is the last set, enable completion interrupt flag */
|
||||
if (i == sg_len - 1)
|
||||
edesc->pset[i].opt |= TCINTEN;
|
||||
@@ -355,27 +401,65 @@ static void edma_callback(unsigned ch_num, u16 ch_status, void *data)
|
||||
struct device *dev = echan->vchan.chan.device->dev;
|
||||
struct edma_desc *edesc;
|
||||
unsigned long flags;
|
||||
struct edmacc_param p;
|
||||
|
||||
/* Stop the channel */
|
||||
edma_stop(echan->ch_num);
|
||||
/* Pause the channel */
|
||||
edma_pause(echan->ch_num);
|
||||
|
||||
switch (ch_status) {
|
||||
case DMA_COMPLETE:
|
||||
dev_dbg(dev, "transfer complete on channel %d\n", ch_num);
|
||||
|
||||
spin_lock_irqsave(&echan->vchan.lock, flags);
|
||||
|
||||
edesc = echan->edesc;
|
||||
if (edesc) {
|
||||
if (edesc->processed == edesc->pset_nr) {
|
||||
dev_dbg(dev, "Transfer complete, stopping channel %d\n", ch_num);
|
||||
edma_stop(echan->ch_num);
|
||||
vchan_cookie_complete(&edesc->vdesc);
|
||||
} else {
|
||||
dev_dbg(dev, "Intermediate transfer complete on channel %d\n", ch_num);
|
||||
}
|
||||
|
||||
edma_execute(echan);
|
||||
vchan_cookie_complete(&edesc->vdesc);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&echan->vchan.lock, flags);
|
||||
|
||||
break;
|
||||
case DMA_CC_ERROR:
|
||||
dev_dbg(dev, "transfer error on channel %d\n", ch_num);
|
||||
spin_lock_irqsave(&echan->vchan.lock, flags);
|
||||
|
||||
edma_read_slot(EDMA_CHAN_SLOT(echan->slot[0]), &p);
|
||||
|
||||
/*
|
||||
* Issue later based on missed flag which will be sure
|
||||
* to happen as:
|
||||
* (1) we finished transmitting an intermediate slot and
|
||||
* edma_execute is coming up.
|
||||
* (2) or we finished current transfer and issue will
|
||||
* call edma_execute.
|
||||
*
|
||||
* Important note: issuing can be dangerous here and
|
||||
* lead to some nasty recursion when we are in a NULL
|
||||
* slot. So we avoid doing so and set the missed flag.
|
||||
*/
|
||||
if (p.a_b_cnt == 0 && p.ccnt == 0) {
|
||||
dev_dbg(dev, "Error occurred, looks like slot is null, just setting miss\n");
|
||||
echan->missed = 1;
|
||||
} else {
|
||||
/*
|
||||
* The slot is already programmed but the event got
|
||||
* missed, so its safe to issue it here.
|
||||
*/
|
||||
dev_dbg(dev, "Error occurred but slot is non-null, TRIGGERING\n");
|
||||
edma_clean_channel(echan->ch_num);
|
||||
edma_stop(echan->ch_num);
|
||||
edma_start(echan->ch_num);
|
||||
edma_trigger_channel(echan->ch_num);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&echan->vchan.lock, flags);
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -502,8 +586,6 @@ static enum dma_status edma_tx_status(struct dma_chan *chan,
|
||||
} else if (echan->edesc && echan->edesc->vdesc.tx.cookie == cookie) {
|
||||
struct edma_desc *edesc = echan->edesc;
|
||||
txstate->residue = edma_desc_size(edesc);
|
||||
} else {
|
||||
txstate->residue = 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&echan->vchan.lock, flags);
|
||||
|
||||
|
||||
@@ -1313,15 +1313,7 @@ static enum dma_status ep93xx_dma_tx_status(struct dma_chan *chan,
|
||||
dma_cookie_t cookie,
|
||||
struct dma_tx_state *state)
|
||||
{
|
||||
struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
|
||||
enum dma_status ret;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&edmac->lock, flags);
|
||||
ret = dma_cookie_status(chan, cookie, state);
|
||||
spin_unlock_irqrestore(&edmac->lock, flags);
|
||||
|
||||
return ret;
|
||||
return dma_cookie_status(chan, cookie, state);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -979,15 +979,7 @@ static enum dma_status fsl_tx_status(struct dma_chan *dchan,
|
||||
dma_cookie_t cookie,
|
||||
struct dma_tx_state *txstate)
|
||||
{
|
||||
struct fsldma_chan *chan = to_fsl_chan(dchan);
|
||||
enum dma_status ret;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&chan->desc_lock, flags);
|
||||
ret = dma_cookie_status(dchan, cookie, txstate);
|
||||
spin_unlock_irqrestore(&chan->desc_lock, flags);
|
||||
|
||||
return ret;
|
||||
return dma_cookie_status(dchan, cookie, txstate);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
@@ -805,10 +805,8 @@ static void imxdma_free_chan_resources(struct dma_chan *chan)
|
||||
}
|
||||
INIT_LIST_HEAD(&imxdmac->ld_free);
|
||||
|
||||
if (imxdmac->sg_list) {
|
||||
kfree(imxdmac->sg_list);
|
||||
imxdmac->sg_list = NULL;
|
||||
}
|
||||
kfree(imxdmac->sg_list);
|
||||
imxdmac->sg_list = NULL;
|
||||
}
|
||||
|
||||
static struct dma_async_tx_descriptor *imxdma_prep_slave_sg(
|
||||
|
||||
+135
-44
@@ -243,7 +243,6 @@ struct sdma_engine;
|
||||
* @event_id1 for channels that use 2 events
|
||||
* @word_size peripheral access size
|
||||
* @buf_tail ID of the buffer that was processed
|
||||
* @done channel completion
|
||||
* @num_bd max NUM_BD. number of descriptors currently handling
|
||||
*/
|
||||
struct sdma_channel {
|
||||
@@ -255,7 +254,6 @@ struct sdma_channel {
|
||||
unsigned int event_id1;
|
||||
enum dma_slave_buswidth word_size;
|
||||
unsigned int buf_tail;
|
||||
struct completion done;
|
||||
unsigned int num_bd;
|
||||
struct sdma_buffer_descriptor *bd;
|
||||
dma_addr_t bd_phys;
|
||||
@@ -307,9 +305,10 @@ struct sdma_firmware_header {
|
||||
u32 ram_code_size;
|
||||
};
|
||||
|
||||
enum sdma_devtype {
|
||||
IMX31_SDMA, /* runs on i.mx31 */
|
||||
IMX35_SDMA, /* runs on i.mx35 and later */
|
||||
struct sdma_driver_data {
|
||||
int chnenbl0;
|
||||
int num_events;
|
||||
struct sdma_script_start_addrs *script_addrs;
|
||||
};
|
||||
|
||||
struct sdma_engine {
|
||||
@@ -318,8 +317,6 @@ struct sdma_engine {
|
||||
struct sdma_channel channel[MAX_DMA_CHANNELS];
|
||||
struct sdma_channel_control *channel_control;
|
||||
void __iomem *regs;
|
||||
enum sdma_devtype devtype;
|
||||
unsigned int num_events;
|
||||
struct sdma_context_data *context;
|
||||
dma_addr_t context_phys;
|
||||
struct dma_device dma_device;
|
||||
@@ -327,15 +324,118 @@ struct sdma_engine {
|
||||
struct clk *clk_ahb;
|
||||
spinlock_t channel_0_lock;
|
||||
struct sdma_script_start_addrs *script_addrs;
|
||||
const struct sdma_driver_data *drvdata;
|
||||
};
|
||||
|
||||
static struct sdma_driver_data sdma_imx31 = {
|
||||
.chnenbl0 = SDMA_CHNENBL0_IMX31,
|
||||
.num_events = 32,
|
||||
};
|
||||
|
||||
static struct sdma_script_start_addrs sdma_script_imx25 = {
|
||||
.ap_2_ap_addr = 729,
|
||||
.uart_2_mcu_addr = 904,
|
||||
.per_2_app_addr = 1255,
|
||||
.mcu_2_app_addr = 834,
|
||||
.uartsh_2_mcu_addr = 1120,
|
||||
.per_2_shp_addr = 1329,
|
||||
.mcu_2_shp_addr = 1048,
|
||||
.ata_2_mcu_addr = 1560,
|
||||
.mcu_2_ata_addr = 1479,
|
||||
.app_2_per_addr = 1189,
|
||||
.app_2_mcu_addr = 770,
|
||||
.shp_2_per_addr = 1407,
|
||||
.shp_2_mcu_addr = 979,
|
||||
};
|
||||
|
||||
static struct sdma_driver_data sdma_imx25 = {
|
||||
.chnenbl0 = SDMA_CHNENBL0_IMX35,
|
||||
.num_events = 48,
|
||||
.script_addrs = &sdma_script_imx25,
|
||||
};
|
||||
|
||||
static struct sdma_driver_data sdma_imx35 = {
|
||||
.chnenbl0 = SDMA_CHNENBL0_IMX35,
|
||||
.num_events = 48,
|
||||
};
|
||||
|
||||
static struct sdma_script_start_addrs sdma_script_imx51 = {
|
||||
.ap_2_ap_addr = 642,
|
||||
.uart_2_mcu_addr = 817,
|
||||
.mcu_2_app_addr = 747,
|
||||
.mcu_2_shp_addr = 961,
|
||||
.ata_2_mcu_addr = 1473,
|
||||
.mcu_2_ata_addr = 1392,
|
||||
.app_2_per_addr = 1033,
|
||||
.app_2_mcu_addr = 683,
|
||||
.shp_2_per_addr = 1251,
|
||||
.shp_2_mcu_addr = 892,
|
||||
};
|
||||
|
||||
static struct sdma_driver_data sdma_imx51 = {
|
||||
.chnenbl0 = SDMA_CHNENBL0_IMX35,
|
||||
.num_events = 48,
|
||||
.script_addrs = &sdma_script_imx51,
|
||||
};
|
||||
|
||||
static struct sdma_script_start_addrs sdma_script_imx53 = {
|
||||
.ap_2_ap_addr = 642,
|
||||
.app_2_mcu_addr = 683,
|
||||
.mcu_2_app_addr = 747,
|
||||
.uart_2_mcu_addr = 817,
|
||||
.shp_2_mcu_addr = 891,
|
||||
.mcu_2_shp_addr = 960,
|
||||
.uartsh_2_mcu_addr = 1032,
|
||||
.spdif_2_mcu_addr = 1100,
|
||||
.mcu_2_spdif_addr = 1134,
|
||||
.firi_2_mcu_addr = 1193,
|
||||
.mcu_2_firi_addr = 1290,
|
||||
};
|
||||
|
||||
static struct sdma_driver_data sdma_imx53 = {
|
||||
.chnenbl0 = SDMA_CHNENBL0_IMX35,
|
||||
.num_events = 48,
|
||||
.script_addrs = &sdma_script_imx53,
|
||||
};
|
||||
|
||||
static struct sdma_script_start_addrs sdma_script_imx6q = {
|
||||
.ap_2_ap_addr = 642,
|
||||
.uart_2_mcu_addr = 817,
|
||||
.mcu_2_app_addr = 747,
|
||||
.per_2_per_addr = 6331,
|
||||
.uartsh_2_mcu_addr = 1032,
|
||||
.mcu_2_shp_addr = 960,
|
||||
.app_2_mcu_addr = 683,
|
||||
.shp_2_mcu_addr = 891,
|
||||
.spdif_2_mcu_addr = 1100,
|
||||
.mcu_2_spdif_addr = 1134,
|
||||
};
|
||||
|
||||
static struct sdma_driver_data sdma_imx6q = {
|
||||
.chnenbl0 = SDMA_CHNENBL0_IMX35,
|
||||
.num_events = 48,
|
||||
.script_addrs = &sdma_script_imx6q,
|
||||
};
|
||||
|
||||
static struct platform_device_id sdma_devtypes[] = {
|
||||
{
|
||||
.name = "imx25-sdma",
|
||||
.driver_data = (unsigned long)&sdma_imx25,
|
||||
}, {
|
||||
.name = "imx31-sdma",
|
||||
.driver_data = IMX31_SDMA,
|
||||
.driver_data = (unsigned long)&sdma_imx31,
|
||||
}, {
|
||||
.name = "imx35-sdma",
|
||||
.driver_data = IMX35_SDMA,
|
||||
.driver_data = (unsigned long)&sdma_imx35,
|
||||
}, {
|
||||
.name = "imx51-sdma",
|
||||
.driver_data = (unsigned long)&sdma_imx51,
|
||||
}, {
|
||||
.name = "imx53-sdma",
|
||||
.driver_data = (unsigned long)&sdma_imx53,
|
||||
}, {
|
||||
.name = "imx6q-sdma",
|
||||
.driver_data = (unsigned long)&sdma_imx6q,
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
@@ -343,8 +443,11 @@ static struct platform_device_id sdma_devtypes[] = {
|
||||
MODULE_DEVICE_TABLE(platform, sdma_devtypes);
|
||||
|
||||
static const struct of_device_id sdma_dt_ids[] = {
|
||||
{ .compatible = "fsl,imx31-sdma", .data = &sdma_devtypes[IMX31_SDMA], },
|
||||
{ .compatible = "fsl,imx35-sdma", .data = &sdma_devtypes[IMX35_SDMA], },
|
||||
{ .compatible = "fsl,imx6q-sdma", .data = &sdma_imx6q, },
|
||||
{ .compatible = "fsl,imx53-sdma", .data = &sdma_imx53, },
|
||||
{ .compatible = "fsl,imx51-sdma", .data = &sdma_imx51, },
|
||||
{ .compatible = "fsl,imx35-sdma", .data = &sdma_imx35, },
|
||||
{ .compatible = "fsl,imx31-sdma", .data = &sdma_imx31, },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sdma_dt_ids);
|
||||
@@ -356,8 +459,7 @@ MODULE_DEVICE_TABLE(of, sdma_dt_ids);
|
||||
|
||||
static inline u32 chnenbl_ofs(struct sdma_engine *sdma, unsigned int event)
|
||||
{
|
||||
u32 chnenbl0 = (sdma->devtype == IMX31_SDMA ? SDMA_CHNENBL0_IMX31 :
|
||||
SDMA_CHNENBL0_IMX35);
|
||||
u32 chnenbl0 = sdma->drvdata->chnenbl0;
|
||||
return chnenbl0 + event * 4;
|
||||
}
|
||||
|
||||
@@ -547,8 +649,6 @@ static void sdma_tasklet(unsigned long data)
|
||||
{
|
||||
struct sdma_channel *sdmac = (struct sdma_channel *) data;
|
||||
|
||||
complete(&sdmac->done);
|
||||
|
||||
if (sdmac->flags & IMX_DMA_SG_LOOP)
|
||||
sdma_handle_channel_loop(sdmac);
|
||||
else
|
||||
@@ -733,7 +833,7 @@ static int sdma_config_channel(struct sdma_channel *sdmac)
|
||||
sdmac->per_addr = 0;
|
||||
|
||||
if (sdmac->event_id0) {
|
||||
if (sdmac->event_id0 >= sdmac->sdma->num_events)
|
||||
if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events)
|
||||
return -EINVAL;
|
||||
sdma_event_enable(sdmac, sdmac->event_id0);
|
||||
}
|
||||
@@ -812,9 +912,6 @@ static int sdma_request_channel(struct sdma_channel *sdmac)
|
||||
sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
|
||||
|
||||
sdma_set_channel_priority(sdmac, MXC_SDMA_DEFAULT_PRIORITY);
|
||||
|
||||
init_completion(&sdmac->done);
|
||||
|
||||
return 0;
|
||||
out:
|
||||
|
||||
@@ -1120,15 +1217,12 @@ static int sdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
|
||||
}
|
||||
|
||||
static enum dma_status sdma_tx_status(struct dma_chan *chan,
|
||||
dma_cookie_t cookie,
|
||||
struct dma_tx_state *txstate)
|
||||
dma_cookie_t cookie,
|
||||
struct dma_tx_state *txstate)
|
||||
{
|
||||
struct sdma_channel *sdmac = to_sdma_chan(chan);
|
||||
dma_cookie_t last_used;
|
||||
|
||||
last_used = chan->cookie;
|
||||
|
||||
dma_set_tx_state(txstate, chan->completed_cookie, last_used,
|
||||
dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie,
|
||||
sdmac->chn_count - sdmac->chn_real_count);
|
||||
|
||||
return sdmac->status;
|
||||
@@ -1218,19 +1312,6 @@ static int __init sdma_init(struct sdma_engine *sdma)
|
||||
int i, ret;
|
||||
dma_addr_t ccb_phys;
|
||||
|
||||
switch (sdma->devtype) {
|
||||
case IMX31_SDMA:
|
||||
sdma->num_events = 32;
|
||||
break;
|
||||
case IMX35_SDMA:
|
||||
sdma->num_events = 48;
|
||||
break;
|
||||
default:
|
||||
dev_err(sdma->dev, "Unknown sdma type %d. aborting\n",
|
||||
sdma->devtype);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
clk_enable(sdma->clk_ipg);
|
||||
clk_enable(sdma->clk_ahb);
|
||||
|
||||
@@ -1257,7 +1338,7 @@ static int __init sdma_init(struct sdma_engine *sdma)
|
||||
MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control));
|
||||
|
||||
/* disable all channels */
|
||||
for (i = 0; i < sdma->num_events; i++)
|
||||
for (i = 0; i < sdma->drvdata->num_events; i++)
|
||||
writel_relaxed(0, sdma->regs + chnenbl_ofs(sdma, i));
|
||||
|
||||
/* All channels have priority 0 */
|
||||
@@ -1335,10 +1416,21 @@ static int __init sdma_probe(struct platform_device *pdev)
|
||||
int ret;
|
||||
int irq;
|
||||
struct resource *iores;
|
||||
struct sdma_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct sdma_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
int i;
|
||||
struct sdma_engine *sdma;
|
||||
s32 *saddr_arr;
|
||||
const struct sdma_driver_data *drvdata = NULL;
|
||||
|
||||
if (of_id)
|
||||
drvdata = of_id->data;
|
||||
else if (pdev->id_entry)
|
||||
drvdata = (void *)pdev->id_entry->driver_data;
|
||||
|
||||
if (!drvdata) {
|
||||
dev_err(&pdev->dev, "unable to find driver data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sdma = kzalloc(sizeof(*sdma), GFP_KERNEL);
|
||||
if (!sdma)
|
||||
@@ -1347,6 +1439,7 @@ static int __init sdma_probe(struct platform_device *pdev)
|
||||
spin_lock_init(&sdma->channel_0_lock);
|
||||
|
||||
sdma->dev = &pdev->dev;
|
||||
sdma->drvdata = drvdata;
|
||||
|
||||
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
@@ -1396,10 +1489,6 @@ static int __init sdma_probe(struct platform_device *pdev)
|
||||
for (i = 0; i < SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; i++)
|
||||
saddr_arr[i] = -EINVAL;
|
||||
|
||||
if (of_id)
|
||||
pdev->id_entry = of_id->data;
|
||||
sdma->devtype = pdev->id_entry->driver_data;
|
||||
|
||||
dma_cap_set(DMA_SLAVE, sdma->dma_device.cap_mask);
|
||||
dma_cap_set(DMA_CYCLIC, sdma->dma_device.cap_mask);
|
||||
|
||||
@@ -1431,6 +1520,8 @@ static int __init sdma_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
goto err_init;
|
||||
|
||||
if (sdma->drvdata->script_addrs)
|
||||
sdma_add_scripts(sdma, sdma->drvdata->script_addrs);
|
||||
if (pdata && pdata->script_addrs)
|
||||
sdma_add_scripts(sdma, pdata->script_addrs);
|
||||
|
||||
|
||||
Loaded 20 of 54 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user