Commit d6a32277 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'dmaengine-4.5-rc1' of git://git.infradead.org/users/vkoul/slave-dma

Pull dmaengine updates from Vinod Koul:
 "This round we have few new features, new driver and updates to few
  drivers.

  The new features to dmaengine core are:
   - Synchronized transfer termination API to terminate the dmaengine
     transfers in synchronized and async fashion as required by users.
     We have its user now in ALSA dmaengine lib, img, at_xdma, axi_dmac
     drivers.
   - Universal API for channel request and start consolidation of
     request flows.  It's user is ompa-dma driver.
   - Introduce reuse of descriptors and use in pxa_dma driver

  Add/Remove:
   - New STM32 DMA driver
   - Removal of unused R-Car HPB-DMAC driver

  Updates:
   - ti-dma-crossbar updates for supporting eDMA
   - tegra-apb pm updates
   - idma64
   - mv_xor updates
   - ste_dma updates"

* tag 'dmaengine-4.5-rc1' of git://git.infradead.org/users/vkoul/slave-dma: (54 commits)
  dmaengine: mv_xor: add suspend/resume support
  dmaengine: mv_xor: de-duplicate mv_chan_set_mode*()
  dmaengine: mv_xor: remove mv_xor_chan->current_type field
  dmaengine: omap-dma: Add support for DMA filter mapping to slave devices
  dmaengine: edma: Add support for DMA filter mapping to slave devices
  dmaengine: core: Introduce new, universal API to request a channel
  dmaengine: core: Move and merge the code paths using private_candidate
  dmaengine: core: Skip mask matching when it is not provided to private_candidate
  dmaengine: mdc: Correct terminate_all handling
  dmaengine: edma: Add probe callback to edma_tptc_driver
  dmaengine: dw: fix potential memory leak in dw_dma_parse_dt()
  dmaengine: stm32-dma: Fix unchecked deference of chan->desc
  dmaengine: sh: Remove unused R-Car HPB-DMAC driver
  dmaengine: usb-dmac: Document SoC specific compatibility strings
  ste_dma40: Delete an unnecessary variable initialisation in d40_probe()
  ste_dma40: Delete another unnecessary check in d40_probe()
  ste_dma40: Delete an unnecessary check before the function call "kmem_cache_destroy"
  dmaengine: tegra-apb: Free interrupts before killing tasklets
  dmaengine: tegra-apb: Update driver to use GFP_NOWAIT
  dmaengine: tegra-apb: Only save channel state for those in use
  ...
parents 4c257ec3 8b648436
* Renesas USB DMA Controller Device Tree bindings
Required Properties:
- compatible: must contain "renesas,usb-dmac"
-compatible: "renesas,<soctype>-usb-dmac", "renesas,usb-dmac" as fallback.
Examples with soctypes are:
- "renesas,r8a7790-usb-dmac" (R-Car H2)
- "renesas,r8a7791-usb-dmac" (R-Car M2-W)
- "renesas,r8a7793-usb-dmac" (R-Car M2-N)
- "renesas,r8a7794-usb-dmac" (R-Car E2)
- "renesas,r8a7795-usb-dmac" (R-Car H3)
- reg: base address and length of the registers block for the DMAC
- interrupts: interrupt specifiers for the DMAC, one for each entry in
interrupt-names.
......@@ -15,7 +21,7 @@ Required Properties:
Example: R8A7790 (R-Car H2) USB-DMACs
usb_dmac0: dma-controller@e65a0000 {
compatible = "renesas,usb-dmac";
compatible = "renesas,r8a7790-usb-dmac", "renesas,usb-dmac";
reg = <0 0xe65a0000 0 0x100>;
interrupts = <0 109 IRQ_TYPE_LEVEL_HIGH
0 109 IRQ_TYPE_LEVEL_HIGH>;
......
* STMicroelectronics STM32 DMA controller
The STM32 DMA is a general-purpose direct memory access controller capable of
supporting 8 independent DMA channels. Each channel can have up to 8 requests.
Required properties:
- compatible: Should be "st,stm32-dma"
- reg: Should contain DMA registers location and length. This should include
all of the per-channel registers.
- interrupts: Should contain all of the per-channel DMA interrupts in
ascending order with respect to the DMA channel index.
- clocks: Should contain the input clock of the DMA instance.
- #dma-cells : Must be <4>. See DMA client paragraph for more details.
Optional properties:
- resets: Reference to a reset controller asserting the DMA controller
- st,mem2mem: boolean; if defined, it indicates that the controller supports
memory-to-memory transfer
Example:
dma2: dma-controller@40026400 {
compatible = "st,stm32-dma";
reg = <0x40026400 0x400>;
interrupts = <56>,
<57>,
<58>,
<59>,
<60>,
<68>,
<69>,
<70>;
clocks = <&clk_hclk>;
#dma-cells = <4>;
st,mem2mem;
resets = <&rcc 150>;
};
* DMA client
DMA clients connected to the STM32 DMA controller must use the format
described in the dma.txt file, using a five-cell specifier for each
channel: a phandle plus four integer cells.
The four cells in order are:
1. The channel id
2. The request line number
3. A 32bit mask specifying the DMA channel configuration which are device
dependent:
-bit 9: Peripheral Increment Address
0x0: no address increment between transfers
0x1: increment address between transfers
-bit 10: Memory Increment Address
0x0: no address increment between transfers
0x1: increment address between transfers
-bit 15: Peripheral Increment Offset Size
0x0: offset size is linked to the peripheral bus width
0x1: offset size is fixed to 4 (32-bit alignment)
-bit 16-17: Priority level
0x0: low
0x1: medium
0x2: high
0x3: very high
5. A 32bit mask specifying the DMA FIFO threshold configuration which are device
dependent:
-bit 0-1: Fifo threshold
0x0: 1/4 full FIFO
0x1: 1/2 full FIFO
0x2: 3/4 full FIFO
0x3: full FIFO
Example:
usart1: serial@40011000 {
compatible = "st,stm32-usart", "st,stm32-uart";
reg = <0x40011000 0x400>;
interrupts = <37>;
clocks = <&clk_pclk2>;
dmas = <&dma2 2 4 0x10400 0x3>,
<&dma2 7 5 0x10200 0x3>;
dma-names = "rx", "tx";
};
......@@ -14,6 +14,10 @@ The DMA controller node need to have the following poroperties:
Optional properties:
- ti,dma-safe-map: Safe routing value for unused request lines
- ti,reserved-dma-request-ranges: DMA request ranges which should not be used
when mapping xbar input to DMA request, they are either
allocated to be used by for example the DSP or they are used as
memcpy channels in eDMA.
Notes:
When requesting channel via ti,dra7-dma-crossbar, the DMA clinet must request
......@@ -46,6 +50,8 @@ sdma_xbar: dma-router@4a002b78 {
#dma-cells = <1>;
dma-requests = <205>;
ti,dma-safe-map = <0>;
/* Protect the sDMA request ranges: 10-14 and 100-126 */
ti,reserved-dma-request-ranges = <10 5>, <100 27>;
dma-masters = <&sdma>;
};
......
......@@ -22,25 +22,14 @@ The slave DMA usage consists of following steps:
Channel allocation is slightly different in the slave DMA context,
client drivers typically need a channel from a particular DMA
controller only and even in some cases a specific channel is desired.
To request a channel dma_request_channel() API is used.
To request a channel dma_request_chan() API is used.
Interface:
struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
dma_filter_fn filter_fn,
void *filter_param);
where dma_filter_fn is defined as:
typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
struct dma_chan *dma_request_chan(struct device *dev, const char *name);
The 'filter_fn' parameter is optional, but highly recommended for
slave and cyclic channels as they typically need to obtain a specific
DMA channel.
When the optional 'filter_fn' parameter is NULL, dma_request_channel()
simply returns the first channel that satisfies the capability mask.
Otherwise, the 'filter_fn' routine will be called once for each free
channel which has a capability in 'mask'. 'filter_fn' is expected to
return 'true' when the desired DMA channel is found.
Which will find and return the 'name' DMA channel associated with the 'dev'
device. The association is done via DT, ACPI or board file based
dma_slave_map matching table.
A channel allocated via this interface is exclusive to the caller,
until dma_release_channel() is called.
......@@ -128,7 +117,7 @@ The slave DMA usage consists of following steps:
transaction.
For cyclic DMA, a callback function may wish to terminate the
DMA via dmaengine_terminate_all().
DMA via dmaengine_terminate_async().
Therefore, it is important that DMA engine drivers drop any
locks before calling the callback function which may cause a
......@@ -166,12 +155,29 @@ The slave DMA usage consists of following steps:
Further APIs:
1. int dmaengine_terminate_all(struct dma_chan *chan)
1. int dmaengine_terminate_sync(struct dma_chan *chan)
int dmaengine_terminate_async(struct dma_chan *chan)
int dmaengine_terminate_all(struct dma_chan *chan) /* DEPRECATED */
This causes all activity for the DMA channel to be stopped, and may
discard data in the DMA FIFO which hasn't been fully transferred.
No callback functions will be called for any incomplete transfers.
Two variants of this function are available.
dmaengine_terminate_async() might not wait until the DMA has been fully
stopped or until any running complete callbacks have finished. But it is
possible to call dmaengine_terminate_async() from atomic context or from
within a complete callback. dmaengine_synchronize() must be called before it
is safe to free the memory accessed by the DMA transfer or free resources
accessed from within the complete callback.
dmaengine_terminate_sync() will wait for the transfer and any running
complete callbacks to finish before it returns. But the function must not be
called from atomic context or from within a complete callback.
dmaengine_terminate_all() is deprecated and should not be used in new code.
2. int dmaengine_pause(struct dma_chan *chan)
This pauses activity on the DMA channel without data loss.
......@@ -197,3 +203,20 @@ Further APIs:
a running DMA channel. It is recommended that DMA engine users
pause or stop (via dmaengine_terminate_all()) the channel before
using this API.
5. void dmaengine_synchronize(struct dma_chan *chan)
Synchronize the termination of the DMA channel to the current context.
This function should be used after dmaengine_terminate_async() to synchronize
the termination of the DMA channel to the current context. The function will
wait for the transfer and any running complete callbacks to finish before it
returns.
If dmaengine_terminate_async() is used to stop the DMA channel this function
must be called before it is safe to free memory accessed by previously
submitted descriptors or to free any resources accessed within the complete
callback of previously submitted descriptors.
The behavior of this function is undefined if dma_async_issue_pending() has
been called between dmaengine_terminate_async() and this function.
......@@ -327,8 +327,24 @@ supported.
* device_terminate_all
- Aborts all the pending and ongoing transfers on the channel
- This command should operate synchronously on the channel,
terminating right away all the channels
- For aborted transfers the complete callback should not be called
- Can be called from atomic context or from within a complete
callback of a descriptor. Must not sleep. Drivers must be able
to handle this correctly.
- Termination may be asynchronous. The driver does not have to
wait until the currently active transfer has completely stopped.
See device_synchronize.
* device_synchronize
- Must synchronize the termination of a channel to the current
context.
- Must make sure that memory for previously submitted
descriptors is no longer accessed by the DMA controller.
- Must make sure that all complete callbacks for previously
submitted descriptors have finished running and none are
scheduled to run.
- May sleep.
Misc notes (stuff that should be documented, but don't really know
where to put them)
......
......@@ -54,6 +54,8 @@ CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_DMADEVICES=y
CONFIG_STM32_DMA=y
# CONFIG_FILE_LOCKING is not set
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY_USER is not set
......
......@@ -321,7 +321,8 @@ EXPORT_SYMBOL_GPL(dca_get_tag);
* @ops - pointer to struct of dca operation function pointers
* @priv_size - size of extra mem to be added for provider's needs
*/
struct dca_provider *alloc_dca_provider(struct dca_ops *ops, int priv_size)
struct dca_provider *alloc_dca_provider(const struct dca_ops *ops,
int priv_size)
{
struct dca_provider *dca;
int alloc_size;
......
......@@ -431,6 +431,18 @@ config STE_DMA40
help
Support for ST-Ericsson DMA40 controller
config STM32_DMA
bool "STMicroelectronics STM32 DMA support"
depends on ARCH_STM32
select DMA_ENGINE
select DMA_OF
select DMA_VIRTUAL_CHANNELS
help
Enable support for the on-chip DMA controller on STMicroelectronics
STM32 MCUs.
If you have a board based on such a MCU and wish to use DMA say Y or M
here.
config S3C24XX_DMAC
tristate "Samsung S3C24XX DMA support"
depends on ARCH_S3C24XX
......
......@@ -56,6 +56,7 @@ obj-$(CONFIG_QCOM_BAM_DMA) += qcom_bam_dma.o
obj-$(CONFIG_RENESAS_DMA) += sh/
obj-$(CONFIG_SIRF_DMA) += sirf-dma.o
obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
obj-$(CONFIG_STM32_DMA) += stm32-dma.o
obj-$(CONFIG_S3C24XX_DMAC) += s3c24xx-dma.o
obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o
obj-$(CONFIG_TEGRA20_APB_DMA) += tegra20-apb-dma.o
......
......@@ -15,6 +15,7 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/slab.h>
......@@ -72,7 +73,9 @@ static int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp,
si = (const struct acpi_csrt_shared_info *)&grp[1];
/* Match device by MMIO and IRQ */
if (si->mmio_base_low != mem || si->gsi_interrupt != irq)
if (si->mmio_base_low != lower_32_bits(mem) ||
si->mmio_base_high != upper_32_bits(mem) ||
si->gsi_interrupt != irq)
return 0;
dev_dbg(&adev->dev, "matches with %.4s%04X (rev %u)\n",
......
......@@ -863,8 +863,12 @@ at_xdmac_interleaved_queue_desc(struct dma_chan *chan,
* access. Hopefully we can access DDR through both ports (at least on
* SAMA5D4x), so we can use the same interface for source and dest,
* that solves the fact we don't know the direction.
* ERRATA: Even if useless for memory transfers, the PERID has to not
* match the one of another channel. If not, it could lead to spurious
* flag status.
*/
u32 chan_cc = AT_XDMAC_CC_DIF(0)
u32 chan_cc = AT_XDMAC_CC_PERID(0x3f)
| AT_XDMAC_CC_DIF(0)
| AT_XDMAC_CC_SIF(0)
| AT_XDMAC_CC_MBSIZE_SIXTEEN
| AT_XDMAC_CC_TYPE_MEM_TRAN;
......@@ -1041,8 +1045,12 @@ at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
* access DDR through both ports (at least on SAMA5D4x), so we can use
* the same interface for source and dest, that solves the fact we
* don't know the direction.
* ERRATA: Even if useless for memory transfers, the PERID has to not
* match the one of another channel. If not, it could lead to spurious
* flag status.
*/
u32 chan_cc = AT_XDMAC_CC_DAM_INCREMENTED_AM
u32 chan_cc = AT_XDMAC_CC_PERID(0x3f)
| AT_XDMAC_CC_DAM_INCREMENTED_AM
| AT_XDMAC_CC_SAM_INCREMENTED_AM
| AT_XDMAC_CC_DIF(0)
| AT_XDMAC_CC_SIF(0)
......@@ -1143,8 +1151,12 @@ static struct at_xdmac_desc *at_xdmac_memset_create_desc(struct dma_chan *chan,
* access. Hopefully we can access DDR through both ports (at least on
* SAMA5D4x), so we can use the same interface for source and dest,
* that solves the fact we don't know the direction.
* ERRATA: Even if useless for memory transfers, the PERID has to not
* match the one of another channel. If not, it could lead to spurious
* flag status.
*/
u32 chan_cc = AT_XDMAC_CC_DAM_UBS_AM
u32 chan_cc = AT_XDMAC_CC_PERID(0x3f)
| AT_XDMAC_CC_DAM_UBS_AM
| AT_XDMAC_CC_SAM_INCREMENTED_AM
| AT_XDMAC_CC_DIF(0)
| AT_XDMAC_CC_SIF(0)
......@@ -1998,8 +2010,6 @@ static int at_xdmac_remove(struct platform_device *pdev)
dma_async_device_unregister(&atxdmac->dma);
clk_disable_unprepare(atxdmac->clk);
synchronize_irq(atxdmac->irq);
free_irq(atxdmac->irq, atxdmac->dma.dev);
for (i = 0; i < atxdmac->dma.chancnt; i++) {
......
......@@ -307,6 +307,13 @@ static int axi_dmac_terminate_all(struct dma_chan *c)
return 0;
}
static void axi_dmac_synchronize(struct dma_chan *c)
{
struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
vchan_synchronize(&chan->vchan);
}
static void axi_dmac_issue_pending(struct dma_chan *c)
{
struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
......@@ -613,6 +620,7 @@ static int axi_dmac_probe(struct platform_device *pdev)
dma_dev->device_prep_dma_cyclic = axi_dmac_prep_dma_cyclic;
dma_dev->device_prep_interleaved_dma = axi_dmac_prep_interleaved;
dma_dev->device_terminate_all = axi_dmac_terminate_all;
dma_dev->device_synchronize = axi_dmac_synchronize;
dma_dev->dev = &pdev->dev;
dma_dev->chancnt = 1;
dma_dev->src_addr_widths = BIT(dmac->chan.src_width);
......
......@@ -43,6 +43,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/module.h>
......@@ -265,8 +266,11 @@ static void dma_chan_put(struct dma_chan *chan)
module_put(dma_chan_to_owner(chan));
/* This channel is not in use anymore, free it */
if (!chan->client_count && chan->device->device_free_chan_resources)
if (!chan->client_count && chan->device->device_free_chan_resources) {
/* Make sure all operations have completed */
dmaengine_synchronize(chan);
chan->device->device_free_chan_resources(chan);
}
/* If the channel is used via a DMA request router, free the mapping */
if (chan->router && chan->router->route_free) {
......@@ -493,6 +497,7 @@ int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps)
caps->dst_addr_widths = device->dst_addr_widths;
caps->directions = device->directions;
caps->residue_granularity = device->residue_granularity;
caps->descriptor_reuse = device->descriptor_reuse;
/*
* Some devices implement only pause (e.g. to get residuum) but no
......@@ -511,7 +516,7 @@ static struct dma_chan *private_candidate(const dma_cap_mask_t *mask,
{
struct dma_chan *chan;
if (!__dma_device_satisfies_mask(dev, mask)) {
if (mask && !__dma_device_satisfies_mask(dev, mask)) {
pr_debug("%s: wrong capabilities\n", __func__);
return NULL;
}
......@@ -542,6 +547,42 @@ static struct dma_chan *private_candidate(const dma_cap_mask_t *mask,
return NULL;
}
static struct dma_chan *find_candidate(struct dma_device *device,
const dma_cap_mask_t *mask,
dma_filter_fn fn, void *fn_param)
{
struct dma_chan *chan = private_candidate(mask, device, fn, fn_param);
int err;
if (chan) {
/* Found a suitable channel, try to grab, prep, and return it.
* We first set DMA_PRIVATE to disable balance_ref_count as this
* channel will not be published in the general-purpose
* allocator
*/
dma_cap_set(DMA_PRIVATE, device->cap_mask);
device->privatecnt++;
err = dma_chan_get(chan);
if (err) {
if (err == -ENODEV) {
pr_debug("%s: %s module removed\n", __func__,
dma_chan_name(chan));
list_del_rcu(&device->global_node);
} else
pr_debug("%s: failed to get %s: (%d)\n",
__func__, dma_chan_name(chan), err);
if (--device->privatecnt == 0)
dma_cap_clear(DMA_PRIVATE, device->cap_mask);
chan = ERR_PTR(err);
}
}
return chan ? chan : ERR_PTR(-EPROBE_DEFER);
}
/**
* dma_get_slave_channel - try to get specific channel exclusively
* @chan: target channel
......@@ -580,7 +621,6 @@ struct dma_chan *dma_get_any_slave_channel(struct dma_device *device)
{
dma_cap_mask_t mask;
struct dma_chan *chan;
int err;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
......@@ -588,23 +628,11 @@ struct dma_chan *dma_get_any_slave_channel(struct dma_device *device)
/* lock against __dma_request_channel */
mutex_lock(&dma_list_mutex);
chan = private_candidate(&mask, device, NULL, NULL);
if (chan) {
dma_cap_set(DMA_PRIVATE, device->cap_mask);
device->privatecnt++;
err = dma_chan_get(chan);
if (err) {
pr_debug("%s: failed to get %s: (%d)\n",
__func__, dma_chan_name(chan), err);
chan = NULL;
if (--device->privatecnt == 0)
dma_cap_clear(DMA_PRIVATE, device->cap_mask);
}
}
chan = find_candidate(device, &mask, NULL, NULL);
mutex_unlock(&dma_list_mutex);
return chan;
return IS_ERR(chan) ? NULL : chan;
}
EXPORT_SYMBOL_GPL(dma_get_any_slave_channel);
......@@ -621,35 +649,15 @@ struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
{
struct dma_device *device, *_d;
struct dma_chan *chan = NULL;
int err;
/* Find a channel */
mutex_lock(&dma_list_mutex);
list_for_each_entry_safe(device, _d, &dma_device_list, global_node) {
chan = private_candidate(mask, device, fn, fn_param);
if (chan) {
/* Found a suitable channel, try to grab, prep, and
* return it. We first set DMA_PRIVATE to disable
* balance_ref_count as this channel will not be
* published in the general-purpose allocator
*/
dma_cap_set(DMA_PRIVATE, device->cap_mask);
device->privatecnt++;
err = dma_chan_get(chan);
chan = find_candidate(device, mask, fn, fn_param);
if (!IS_ERR(chan))
break;
if (err == -ENODEV) {
pr_debug("%s: %s module removed\n",
__func__, dma_chan_name(chan));
list_del_rcu(&device->global_node);
} else if (err)
pr_debug("%s: failed to get %s: (%d)\n",
__func__, dma_chan_name(chan), err);
else
break;
if (--device->privatecnt == 0)
dma_cap_clear(DMA_PRIVATE, device->cap_mask);
chan = NULL;
}
chan = NULL;
}
mutex_unlock(&dma_list_mutex);
......@@ -662,27 +670,73 @@ struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
}
EXPORT_SYMBOL_GPL(__dma_request_channel);
static const struct dma_slave_map *dma_filter_match(struct dma_device *device,
const char *name,
struct device *dev)
{
int i;
if (!device->filter.mapcnt)
return NULL;
for (i = 0; i < device->filter.mapcnt; i++) {
const struct dma_slave_map *map = &device->filter.map[i];
if (!strcmp(map->devname, dev_name(dev)) &&
!strcmp(map->slave, name))
return map;
}
return NULL;
}
/**
* dma_request_slave_channel_reason - try to allocate an exclusive slave channel
* dma_request_chan - try to allocate an exclusive slave channel
* @dev: pointer to client device structure
* @name: slave channel name
*
* Returns pointer to appropriate DMA channel on success or an error pointer.
*/
struct dma_chan *dma_request_slave_channel_reason(struct device *dev,
const char *name)
struct dma_chan *dma_request_chan(struct device *dev, const char *name)
{
struct dma_device *d, *_d;
struct dma_chan *chan = NULL;
/* If device-tree is present get slave info from here */
if (dev->of_node)
return of_dma_request_slave_channel(dev->of_node, name);
chan = of_dma_request_slave_channel(dev->of_node, name);
/* If device was enumerated by ACPI get slave info from here */
if (ACPI_HANDLE(dev))
return acpi_dma_request_slave_chan_by_name(dev, name);
if (has_acpi_companion(dev) && !chan)
chan = acpi_dma_request_slave_chan_by_name(dev, name);
if (chan) {
/* Valid channel found or requester need to be deferred */
if (!IS_ERR(chan) || PTR_ERR(chan) == -EPROBE_DEFER)
return chan;
}
return ERR_PTR(-ENODEV);
/* Try to find the channel via the DMA filter map(s) */
mutex_lock(&dma_list_mutex);
list_for_each_entry_safe(d, _d, &dma_device_list, global_node) {
dma_cap_mask_t mask;
const struct dma_slave_map *map = dma_filter_match(d, name, dev);
if (!map)
continue;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
chan = find_candidate(d, &mask, d->filter.fn, map->param);
if (!IS_ERR(chan))
break;
}
mutex_unlock(&dma_list_mutex);
return chan ? chan : ERR_PTR(-EPROBE_DEFER);
}
EXPORT_SYMBOL_GPL(dma_request_slave_channel_reason);
EXPORT_SYMBOL_GPL(dma_request_chan);
/**
* dma_request_slave_channel - try to allocate an exclusive slave channel
......@@ -694,17 +748,35 @@ EXPORT_SYMBOL_GPL(dma_request_slave_channel_reason);
struct dma_chan *dma_request_slave_channel(struct device *dev,
const char *name)
{
struct dma_chan *ch = dma_request_slave_channel_reason(dev, name);
struct dma_chan *ch = dma_request_chan(dev, name);
if (IS_ERR(ch))
return NULL;
dma_cap_set(DMA_PRIVATE, ch->device->cap_mask);
ch->device->privatecnt++;
return ch;
}
EXPORT_SYMBOL_GPL(dma_request_slave_channel);
/**
* dma_request_chan_by_mask - allocate a channel satisfying certain capabilities
* @mask: capabilities that the channel must satisfy
*
* Returns pointer to appropriate DMA channel on success or an error pointer.
*/
struct dma_chan *dma_request_chan_by_mask(const dma_cap_mask_t *mask)
{
struct dma_chan *chan;
if (!mask)
return ERR_PTR(-ENODEV);
chan = __dma_request_channel(mask, NULL, NULL);
if (!chan)
chan = ERR_PTR(-ENODEV);
return chan;
}
EXPORT_SYMBOL_GPL(dma_request_chan_by_mask);
void dma_release_channel(struct dma_chan *chan)
{
mutex_lock(&dma_list_mutex);
......
......@@ -103,18 +103,21 @@ dw_dma_parse_dt(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct dw_dma_platform_data *pdata;
u32 tmp, arr[DW_DMA_MAX_NR_MASTERS];
u32 nr_channels;
if (!np) {
dev_err(&pdev->dev, "Missing DT data\n");
return NULL;
}
if (of_property_read_u32(np, "dma-channels", &nr_channels))
return NULL;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return NULL;
if (of_property_read_u32(np, "dma-channels", &pdata->nr_channels))
return NULL;
pdata->nr_channels = nr_channels;
if (of_property_read_bool(np, "is_private"))
pdata->is_private = true;
......
......@@ -2314,6 +2314,10 @@ static int edma_probe(struct platform_device *pdev)
edma_set_chmap(&ecc->slave_chans[i], ecc->dummy_slot);
}
ecc->dma_slave.filter.map = info->slave_map;
ecc->dma_slave.filter.mapcnt = info->slavecnt;
ecc->dma_slave.filter.fn = edma_filter_fn;
ret = dma_async_device_register(&ecc->dma_slave);
if (ret) {
dev_err(dev, "slave ddev registration failed (%d)\n", ret);
......@@ -2421,7 +2425,13 @@ static struct platform_driver edma_driver = {
},
};
static int edma_tptc_probe(struct platform_device *pdev)
{
return 0;
}
static struct platform_driver edma_tptc_driver = {
.probe = edma_tptc_probe,
.driver = {
.name = "edma3-tptc",
.of_match_table = edma_tptc_of_ids,
......
......@@ -116,6 +116,10 @@
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | \
BIT(DMA_SLAVE_BUSWIDTH_8_BYTES)
enum fsl_edma_pm_state {
RUNNING = 0,
SUSPENDED,
};
struct fsl_edma_hw_tcd {
__le32 saddr;
......@@ -147,6 +151,9 @@ struct fsl_edma_slave_config {
struct fsl_edma_chan {
struct virt_dma_chan vchan;
enum dma_status status;
enum fsl_edma_pm_state pm_state;
bool idle;
u32 slave_id;
struct fsl_edma_engine *edma;
struct fsl_edma_desc *edesc;
struct fsl_edma_slave_config fsc;
......@@ -298,6 +305,7 @@ static int fsl_edma_terminate_all(struct dma_chan *chan)
spin_lock_irqsave(&fsl_chan->vchan.lock, flags);
fsl_edma_disable_request(fsl_chan);
fsl_chan->edesc = NULL;
fsl_chan->idle = true;