From 9a6cecc846169159bfce511f4c0034bb96eea1ca Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 14 Sep 2012 17:41:57 -0500 Subject: dmaengine: add helper function to request a slave DMA channel Currently slave DMA channels are requested by calling dma_request_channel() and requires DMA clients to pass various filter parameters to obtain the appropriate channel. With device-tree being used by architectures such as arm and the addition of device-tree helper functions to extract the relevant DMA client information from device-tree, add a new function to request a slave DMA channel using device-tree. This function is currently a simple wrapper that calls the device-tree of_dma_request_slave_channel() function. Cc: Nicolas Ferre Cc: Benoit Cousson Cc: Stephen Warren Cc: Grant Likely Cc: Russell King Cc: Rob Herring Cc: Arnd Bergmann Cc: Vinod Koul Cc: Dan Williams Acked-by: Arnd Bergmann Signed-off-by: Jon Hunter Reviewed-by: Stephen Warren Acked-by: Rob Herring Signed-off-by: Vinod Koul --- include/linux/dmaengine.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include/linux') diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index d3201e438d16..8cd0e2556d04 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -974,6 +974,7 @@ enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie); enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx); void dma_issue_pending_all(void); struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param); +struct dma_chan *dma_request_slave_channel(struct device *dev, char *name); void dma_release_channel(struct dma_chan *chan); #else static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx) @@ -988,6 +989,11 @@ static inline struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, { return NULL; } +static inline struct dma_chan *dma_request_slave_channel(struct device *dev, + char *name) +{ + return NULL +} static inline void dma_release_channel(struct dma_chan *chan) { } -- cgit v1.2.3 From aa3da644c76d1c2083d085e453c18f7c51f19bc4 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 14 Sep 2012 17:41:56 -0500 Subject: of: Add generic device tree DMA helpers This is based upon the work by Benoit Cousson [1] and Nicolas Ferre [2] to add some basic helpers to retrieve a DMA controller device_node and the DMA request/channel information. Aim of DMA helpers - The purpose of device-tree is to describe the capabilites of the hardware. Thinking about DMA controllers purely from the context of the hardware to begin with, we can describe a device in terms of a DMA controller as follows ... 1. Number of DMA controllers 2. Number of channels (maybe physical or logical) 3. Mapping of DMA requests signals to DMA controller 4. Number of DMA interrupts 5. Mapping of DMA interrupts to channels - With the above in mind the aim of the DT DMA helper functions is to extract the above information from the DT and provide to the appropriate driver. However, due to the vast number of DMA controllers and not all are using a common driver (such as DMA Engine) it has been seen that this is not a trivial task. In previous discussions on this topic the following concerns have been raised ... 1. How does the binding support devices with multiple DMA controllers? 2. How to support both legacy DMA controllers not using DMA Engine as well as those that support DMA Engine. 3. When using with DMA Engine how do we support the various implementations where the opaque filter function parameter differs between implementations? 4. How do we handle DMA channels that are identified with a string versus a integer? - Hence the design of the DMA helpers has to accomodate the above or align on an agreement what can be or should be supported. Design of DMA helpers 1. Registering DMA controllers In the case of DMA controllers that are using DMA Engine, requesting a channel is performed by calling the following function. struct dma_chan *dma_request_channel(dma_cap_mask_t mask, dma_filter_fn filter_fn, void *filter_param); The mask variable is used to match a type of the device controller in a list of controllers. The filter_fn and filter_param are used to identify the required dma channel and return a handle to the dma channel of type dma_chan. From the examples I have seen, the mask and filter_fn are constant for a given DMA controller and therefore, we can specify these as controller specific data when registering the DMA controller with the device-tree DMA helpers. The filter_param variable is of an unknown type and is typically specific to the DMA engine implementation for a given DMA controller. To allow some flexibility in the type and formating of this filter_param we employ an xlate to translate the device-tree binding information into the appropriate format. The xlate function used for a DMA controller can also be specified when registering the DMA controller with the device-tree DMA helpers. Based upon the above, a function for registering the DMA controller with the DMA helpers now looks like the below. The data variable is used to pass a pointer to DMA controller specific data used by the xlate function. int of_dma_controller_register(struct device_node *np, struct dma_chan *(*of_dma_xlate) (struct of_phandle_args *, struct of_dma *), void *data) For example, in the case where DMA engine is used, we define the following structure (that stores the DMA engine capability mask and filter function) and pass this to the data variable in the above function. struct of_dma_filter_info { dma_cap_mask_t dma_cap; dma_filter_fn filter_fn; }; 2. Representing and requesting channel information Please see the dma binding documentation included in this patch for a description of how DMA controllers and client information should be represented with device-tree. For more information on how this binding came about please see [3]. In addition to this, feedback received from the Linux kernel summit showed a consensus (among those who attended) to use a name to identify DMA client information [4]. A DMA channel can be requested by calling the following function, where name is a required parameter used for identifying a DMA channel. This function has been designed to return a structure of type dma_chan to work with the DMA engine driver. Note that if DMA engine is used then drivers should be using the DMA engine API dma_request_slave_channel() (implemented in part 2 of this series, "dmaengine: add helper function to request a slave DMA channel") which will in turn call the below function if device-tree is present. The aim being to have a common DMA engine interface regardless of whether device tree is being used. struct dma_chan *of_dma_request_slave_channel(struct device_node *np, char *name) 3. Supporting legacy devices not using DMA Engine These devices present a problem, as there may not be a uniform way to easily support them with regard to device tree. Ideally, these should be migrated to DMA engine. However, if this is not possible, then they should still be able to use this binding, the only constaint imposed by this implementation is that when requesting a DMA channel via of_dma_request_slave_channel(), it will return a type of dma_chan. This implementation has been tested on OMAP4430 using the kernel v3.6-rc5. I have validated that MMC is working on the PANDA board with this implementation. My development branch for testing on OMAP can be found here [5]. v6: - minor corrections in DMA binding documentation v5: - minor update to binding documentation - added loop to exhaustively search for a slave channel in the case where there could be alternative channels available v4: - revert the removal of xlate function from v3 - update the proposed binding format and APIs based upon discussions [3] v3: - avoid passing an xlate function and instead pass DMA engine parameters - define number of dma channels and requests in dma-controller node v2: - remove of_dma_to_resource API - make property #dma-cells required (no fallback anymore) - another check in of_dma_xlate_onenumbercell() function [1] http://article.gmane.org/gmane.linux.drivers.devicetree/12022 [2] http://article.gmane.org/gmane.linux.ports.arm.omap/73622 [3] http://marc.info/?l=linux-omap&m=133582085008539&w=2 [4] http://pad.linaro.org/arm-mini-summit-2012 [5] https://github.com/jonhunter/linux/tree/dev-dt-dma Cc: Nicolas Ferre Cc: Benoit Cousson Cc: Stephen Warren Cc: Grant Likely Cc: Russell King Cc: Rob Herring Cc: Arnd Bergmann Cc: Vinod Koul Cc: Dan Williams Reviewed-by: Arnd Bergmann Reviewed-by: Nicolas Ferre Signed-off-by: Jon Hunter Reviewed-by: Stephen Warren Acked-by: Rob Herring Signed-off-by: Vinod Koul --- include/linux/of_dma.h | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 include/linux/of_dma.h (limited to 'include/linux') diff --git a/include/linux/of_dma.h b/include/linux/of_dma.h new file mode 100644 index 000000000000..337823dc6b90 --- /dev/null +++ b/include/linux/of_dma.h @@ -0,0 +1,45 @@ +/* + * OF helpers for DMA request / controller + * + * Based on of_gpio.h + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __LINUX_OF_DMA_H +#define __LINUX_OF_DMA_H + +#include +#include + +struct device_node; + +struct of_dma { + struct list_head of_dma_controllers; + struct device_node *of_node; + int of_dma_nbcells; + struct dma_chan *(*of_dma_xlate) + (struct of_phandle_args *, struct of_dma *); + void *of_dma_data; +}; + +struct of_dma_filter_info { + dma_cap_mask_t dma_cap; + dma_filter_fn filter_fn; +}; + +extern int of_dma_controller_register(struct device_node *np, + struct dma_chan *(*of_dma_xlate) + (struct of_phandle_args *, struct of_dma *), + void *data); +extern void of_dma_controller_free(struct device_node *np); +extern struct dma_chan *of_dma_request_slave_channel(struct device_node *np, + char *name); +extern struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec, + struct of_dma *ofdma); + +#endif /* __LINUX_OF_DMA_H */ -- cgit v1.2.3 From 4c26bc601d20fa67eefcb27477feda130c10790e Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Tue, 25 Sep 2012 09:57:36 +0530 Subject: of: dma- fix build break for !CONFIG_OF Signed-off-by: Vinod Koul --- include/linux/of_dma.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'include/linux') diff --git a/include/linux/of_dma.h b/include/linux/of_dma.h index 337823dc6b90..67158ddd1f3e 100644 --- a/include/linux/of_dma.h +++ b/include/linux/of_dma.h @@ -32,6 +32,7 @@ struct of_dma_filter_info { dma_filter_fn filter_fn; }; +#ifdef CONFIG_OF extern int of_dma_controller_register(struct device_node *np, struct dma_chan *(*of_dma_xlate) (struct of_phandle_args *, struct of_dma *), @@ -41,5 +42,31 @@ extern struct dma_chan *of_dma_request_slave_channel(struct device_node *np, char *name); extern struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec, struct of_dma *ofdma); +#else +static int of_dma_controller_register(struct device_node *np, + struct dma_chan *(*of_dma_xlate) + (struct of_phandle_args *, struct of_dma *), + void *data) +{ + return -ENODEV; +} + +static void of_dma_controller_free(struct device_node *np) +{ +} + +static struct dma_chan *of_dma_request_slave_channel(struct device_node *np, + char *name) +{ + return NULL; +} + +static struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec, + struct of_dma *ofdma) +{ + return NULL; +} + +#endif #endif /* __LINUX_OF_DMA_H */ -- cgit v1.2.3 From d18d5f59797009d86a0ee46feb2a56d53707455a Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Tue, 25 Sep 2012 16:18:55 +0530 Subject: dmaengine: fix build failure due to missing semi-colon Reported-by: Fengguang Wu Signed-off-by: Vinod Koul --- include/linux/dmaengine.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 8cd0e2556d04..c88f302d91c9 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -992,7 +992,7 @@ static inline struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, static inline struct dma_chan *dma_request_slave_channel(struct device *dev, char *name) { - return NULL + return NULL; } static inline void dma_release_channel(struct dma_chan *chan) { -- cgit v1.2.3 From 177d2bf5c7d3ab41bfb4ce2597dde668225958dd Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 16 Oct 2012 09:49:16 +0530 Subject: dmaengine: dw_dmac: Update documentation style comments for dw_dma_platform_data Documentation style comments were missing for few fields in struct dw_dma_platform_data. Add these. Signed-off-by: Viresh Kumar Reviewed-by: Andy Shevchenko Signed-off-by: Vinod Koul --- include/linux/dw_dmac.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h index e1c8c9e919ac..62a6190dee22 100644 --- a/include/linux/dw_dmac.h +++ b/include/linux/dw_dmac.h @@ -19,6 +19,8 @@ * @nr_channels: Number of channels supported by hardware (max 8) * @is_private: The device channels should be marked as private and not for * by the general purpose DMA channel allocator. + * @chan_allocation_order: Allocate channels starting from 0 or 7 + * @chan_priority: Set channel priority increasing from 0 to 7 or 7 to 0. * @block_size: Maximum block size supported by the controller * @nr_masters: Number of AHB masters supported by the controller * @data_width: Maximum data width supported by hardware per AHB master -- cgit v1.2.3 From a9ddb575d6d6c58c39e8c44a22b84445fedb0521 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 16 Oct 2012 09:49:17 +0530 Subject: dmaengine: dw_dmac: Enhance device tree support dw_dmac driver already supports device tree but it used to have its platform data passed the non-DT way. This patch does following changes: - pass platform data via DT, non-DT way still takes precedence if both are used. - create generic filter routine - Earlier slave information was made available by slave specific filter routines in chan->private field. Now, this information would be passed from within dmac DT node. Slave drivers would now be required to pass bus_id (a string) as parameter to this generic filter(), which would be compared against the slave data passed from DT, by the generic filter routine. - Update binding document Signed-off-by: Viresh Kumar Reviewed-by: Andy Shevchenko [Fixed __devinit usage] Signed-off-by: Vinod Koul --- include/linux/dw_dmac.h | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) (limited to 'include/linux') diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h index 62a6190dee22..41766de66e33 100644 --- a/include/linux/dw_dmac.h +++ b/include/linux/dw_dmac.h @@ -14,6 +14,26 @@ #include +/** + * struct dw_dma_slave - Controller-specific information about a slave + * + * @dma_dev: required DMA master device. Depricated. + * @bus_id: name of this device channel, not just a device name since + * devices may have more than one channel e.g. "foo_tx" + * @cfg_hi: Platform-specific initializer for the CFG_HI register + * @cfg_lo: Platform-specific initializer for the CFG_LO register + * @src_master: src master for transfers on allocated channel. + * @dst_master: dest master for transfers on allocated channel. + */ +struct dw_dma_slave { + struct device *dma_dev; + const char *bus_id; + u32 cfg_hi; + u32 cfg_lo; + u8 src_master; + u8 dst_master; +}; + /** * struct dw_dma_platform_data - Controller configuration parameters * @nr_channels: Number of channels supported by hardware (max 8) @@ -25,6 +45,8 @@ * @nr_masters: Number of AHB masters supported by the controller * @data_width: Maximum data width supported by hardware per AHB master * (0 - 8bits, 1 - 16bits, ..., 5 - 256bits) + * @sd: slave specific data. Used for configuring channels + * @sd_count: count of slave data structures passed. */ struct dw_dma_platform_data { unsigned int nr_channels; @@ -38,6 +60,9 @@ struct dw_dma_platform_data { unsigned short block_size; unsigned char nr_masters; unsigned char data_width[4]; + + struct dw_dma_slave *sd; + unsigned int sd_count; }; /* bursts size */ @@ -52,23 +77,6 @@ enum dw_dma_msize { DW_DMA_MSIZE_256, }; -/** - * struct dw_dma_slave - Controller-specific information about a slave - * - * @dma_dev: required DMA master device - * @cfg_hi: Platform-specific initializer for the CFG_HI register - * @cfg_lo: Platform-specific initializer for the CFG_LO register - * @src_master: src master for transfers on allocated channel. - * @dst_master: dest master for transfers on allocated channel. - */ -struct dw_dma_slave { - struct device *dma_dev; - u32 cfg_hi; - u32 cfg_lo; - u8 src_master; - u8 dst_master; -}; - /* Platform-configurable bits in CFG_HI */ #define DWC_CFGH_FCMODE (1 << 0) #define DWC_CFGH_FIFO_MODE (1 << 1) @@ -106,5 +114,6 @@ void dw_dma_cyclic_stop(struct dma_chan *chan); dma_addr_t dw_dma_get_src_addr(struct dma_chan *chan); dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan); +bool dw_dma_generic_filter(struct dma_chan *chan, void *param); #endif /* DW_DMAC_H */ -- cgit v1.2.3 From e5a087fdc1ebe5bba40bcecb53c28a0af70e3b47 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Fri, 26 Oct 2012 23:35:15 +0900 Subject: dmaengine: use for_each_set_bit Use for_each_set_bit() to implement for_each_dma_cap_mask() and remove unused first_dma_cap() and next_dma_cap(). Signed-off-by: Akinobu Mita Cc: Vinod Koul Cc: Dan Williams Acked-by: Linus Walleij Signed-off-by: Vinod Koul --- include/linux/dmaengine.h | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'include/linux') diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index c88f302d91c9..4c8643794e0d 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -849,20 +849,6 @@ static inline bool async_tx_test_ack(struct dma_async_tx_descriptor *tx) return (tx->flags & DMA_CTRL_ACK) == DMA_CTRL_ACK; } -#define first_dma_cap(mask) __first_dma_cap(&(mask)) -static inline int __first_dma_cap(const dma_cap_mask_t *srcp) -{ - return min_t(int, DMA_TX_TYPE_END, - find_first_bit(srcp->bits, DMA_TX_TYPE_END)); -} - -#define next_dma_cap(n, mask) __next_dma_cap((n), &(mask)) -static inline int __next_dma_cap(int n, const dma_cap_mask_t *srcp) -{ - return min_t(int, DMA_TX_TYPE_END, - find_next_bit(srcp->bits, DMA_TX_TYPE_END, n+1)); -} - #define dma_cap_set(tx, mask) __dma_cap_set((tx), &(mask)) static inline void __dma_cap_set(enum dma_transaction_type tx_type, dma_cap_mask_t *dstp) @@ -891,9 +877,7 @@ __dma_has_cap(enum dma_transaction_type tx_type, dma_cap_mask_t *srcp) } #define for_each_dma_cap_mask(cap, mask) \ - for ((cap) = first_dma_cap(mask); \ - (cap) < DMA_TX_TYPE_END; \ - (cap) = next_dma_cap((cap), (mask))) + for_each_set_bit(cap, mask.bits, DMA_TX_TYPE_END) /** * dma_async_issue_pending - flush pending transactions to HW -- cgit v1.2.3 From 9743a3b62dee8c9d8af1319f8d1c1ff39130267d Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 11 Oct 2012 14:43:01 -0500 Subject: of: dma: fix protection of DMA controller data stored by DMA helpers In the current implementation of the OF DMA helpers, read-copy-update (RCU) linked lists are being used for storing and accessing the DMA controller data. This part of implementation is based upon V2 of the DMA helpers by Nicolas [1]. During a recent review of RCU, it became apparent that the code is missing the required rcu_read_lock()/unlock() calls as well as synchronisation calls before freeing any memory protected by RCU. Having looked into adding the appropriate RCU calls to protect the DMA data it became apparent that with the current DMA helper implementation, using RCU is not as attractive as it may have been before. The main reasons being that ... 1. We need to protect the DMA data around calls to the xlate function. 2. The of_dma_simple_xlate() function calls the DMA engine function dma_request_channel() which employs a mutex and so could sleep. 3. The RCU read-side critical sections must not sleep and so we cannot hold an RCU read lock around the xlate function. Therefore, instead of using RCU, an alternative for this use-case is to employ a simple spinlock inconjunction with a usage count variable to keep track of how many current users of the DMA data structure there are. With this implementation, the DMA data cannot be freed until all current users of the DMA data are finished. This patch is based upon the DMA helpers fix for potential deadlock [2]. [1] http://article.gmane.org/gmane.linux.ports.arm.omap/73622 [2] http://marc.info/?l=linux-arm-kernel&m=134859982520984&w=2 Signed-off-by: Jon Hunter Signed-off-by: Vinod Koul --- include/linux/of_dma.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/of_dma.h b/include/linux/of_dma.h index 67158ddd1f3e..84b64f857e23 100644 --- a/include/linux/of_dma.h +++ b/include/linux/of_dma.h @@ -25,6 +25,7 @@ struct of_dma { struct dma_chan *(*of_dma_xlate) (struct of_phandle_args *, struct of_dma *); void *of_dma_data; + int use_count; }; struct of_dma_filter_info { @@ -37,7 +38,7 @@ extern int of_dma_controller_register(struct device_node *np, struct dma_chan *(*of_dma_xlate) (struct of_phandle_args *, struct of_dma *), void *data); -extern void of_dma_controller_free(struct device_node *np); +extern int of_dma_controller_free(struct device_node *np); extern struct dma_chan *of_dma_request_slave_channel(struct device_node *np, char *name); extern struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec, @@ -51,7 +52,7 @@ static int of_dma_controller_register(struct device_node *np, return -ENODEV; } -static void of_dma_controller_free(struct device_node *np) +static int of_dma_controller_free(struct device_node *np) { } -- cgit v1.2.3 From 91f8aecc501e456c97a6f49f7ea3797e874d5d89 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 29 Nov 2012 12:17:22 +0530 Subject: dmaengine: fix !of_dma compilation warning Reported-by: Stephen Rothwell Reported-by: Fengguang Wu Signed-off-by: Vinod Koul --- include/linux/of_dma.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/of_dma.h b/include/linux/of_dma.h index 84b64f857e23..d15073e080dd 100644 --- a/include/linux/of_dma.h +++ b/include/linux/of_dma.h @@ -44,7 +44,7 @@ extern struct dma_chan *of_dma_request_slave_channel(struct device_node *np, extern struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec, struct of_dma *ofdma); #else -static int of_dma_controller_register(struct device_node *np, +static inline int of_dma_controller_register(struct device_node *np, struct dma_chan *(*of_dma_xlate) (struct of_phandle_args *, struct of_dma *), void *data) @@ -52,17 +52,18 @@ static int of_dma_controller_register(struct device_node *np, return -ENODEV; } -static int of_dma_controller_free(struct device_node *np) +static inline int of_dma_controller_free(struct device_node *np) { + return -ENODEV; } -static struct dma_chan *of_dma_request_slave_channel(struct device_node *np, +static inline struct dma_chan *of_dma_request_slave_channel(struct device_node *np, char *name) { return NULL; } -static struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec, +static inline struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec, struct of_dma *ofdma) { return NULL; -- cgit v1.2.3 From a14acb4ac2a1486f6633c55eb7f7ded07f3ec9fc Mon Sep 17 00:00:00 2001 From: Barry Song Date: Tue, 6 Nov 2012 21:32:39 +0800 Subject: DMAEngine: add dmaengine_prep_interleaved_dma wrapper for interleaved api commit b14dab792dee(DMAEngine: Define interleaved transfer request api) adds interleaved request api, this patch adds the dmaengine_prep_interleaved_dma just like we have dmaengine_prep_ for other modes to avoid drivers call: xxx_chan->device->device_prep_interleaved_dma(). Signed-off-by: Barry Song Cc: Jassi Brar Signed-off-by: Vinod Koul --- include/linux/dmaengine.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/linux') diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 4c8643794e0d..3aa76dbed166 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -660,6 +660,13 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic( period_len, dir, flags, NULL); } +static inline struct dma_async_tx_descriptor *dmaengine_prep_interleaved_dma( + struct dma_chan *chan, struct dma_interleaved_template *xt, + unsigned long flags) +{ + return chan->device->device_prep_interleaved_dma(chan, xt, flags); +} + static inline int dmaengine_terminate_all(struct dma_chan *chan) { return dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0); -- cgit v1.2.3 From 944ea4dd38b8575e30a5699633c81945bff1864d Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Sun, 11 Nov 2012 23:03:20 +0000 Subject: dmatest: Fix NULL pointer dereference on ioat device_control is an optional and not implemented in all DMA drivers. Any calls to these will result in a NULL pointer dereference. dmatest makes two of these calls when completing the kernel thread and removing the module. These are corrected by calling the dmaengine_device_control wrapper and checking for a non-existant device_control function pointer there. Signed-off-by: Jon Mason CC: Vinod Koul CC: Dan Williams Reviewed-by: Viresh Kumar Signed-off-by: Vinod Koul --- include/linux/dmaengine.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 3aa76dbed166..be6e95395b11 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -608,7 +608,10 @@ static inline int dmaengine_device_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg) { - return chan->device->device_control(chan, cmd, arg); + if (chan->device->device_control) + return chan->device->device_control(chan, cmd, arg); + else + return -ENOSYS; } static inline int dmaengine_slave_config(struct dma_chan *chan, -- cgit v1.2.3 From b9ee86830f34737a08deead93872a79a37419a13 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 8 Nov 2012 09:59:54 +0000 Subject: dmaengine: remove dma_async_memcpy_pending() macro Just use dma_async_issue_pending() directly. Cc: Vinod Koul Cc: Tomasz Figa Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Kyungmin Park Signed-off-by: Dan Williams --- include/linux/dmaengine.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index be6e95395b11..cd15958d4d1d 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -901,8 +901,6 @@ static inline void dma_async_issue_pending(struct dma_chan *chan) chan->device->device_issue_pending(chan); } -#define dma_async_memcpy_issue_pending(chan) dma_async_issue_pending(chan) - /** * dma_async_is_tx_complete - poll for transaction completion * @chan: DMA channel -- cgit v1.2.3 From e239345f642e6a255d0ba1e3d92c2f9ec5a44fbe Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 8 Nov 2012 10:01:01 +0000 Subject: dmaengine: remove dma_async_memcpy_complete() macro Just use dma_async_is_tx_complete() directly. Cc: Vinod Koul Cc: Tomasz Figa Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Kyungmin Park Signed-off-by: Dan Williams --- include/linux/dmaengine.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index cd15958d4d1d..4ca9cf73ad3f 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -926,16 +926,13 @@ static inline enum dma_status dma_async_is_tx_complete(struct dma_chan *chan, return status; } -#define dma_async_memcpy_complete(chan, cookie, last, used)\ - dma_async_is_tx_complete(chan, cookie, last, used) - /** * dma_async_is_complete - test a cookie against chan state * @cookie: transaction identifier to test status of * @last_complete: last know completed transaction * @last_used: last cookie value handed out * - * dma_async_is_complete() is used in dma_async_memcpy_complete() + * dma_async_is_complete() is used in dma_async_is_tx_complete() * the test logic is separated for lightweight testing of multiple cookies */ static inline enum dma_status dma_async_is_complete(dma_cookie_t cookie, -- cgit v1.2.3 From 61cc13a51bcff737ce02d2047834171c0365b00d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 10 Jan 2013 10:52:56 +0200 Subject: dmaengine: introduce is_slave_direction function This function helps to distinguish the slave type of transfer by checking the direction parameter. Signed-off-by: Andy Shevchenko Reviewed-by: Viresh Kumar Reviewed-by: Mika Westerberg Reviewed-by: Linus Walleij Cc: Nicolas Ferre Cc: Guennadi Liakhovetski Signed-off-by: Vinod Koul --- include/linux/dmaengine.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include/linux') diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 4ca9cf73ad3f..bfcdecb5d87a 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -621,6 +621,11 @@ static inline int dmaengine_slave_config(struct dma_chan *chan, (unsigned long)config); } +static inline bool is_slave_direction(enum dma_transfer_direction direction) +{ + return (direction == DMA_MEM_TO_DEV) || (direction == DMA_DEV_TO_MEM); +} + static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( struct dma_chan *chan, dma_addr_t buf, size_t len, enum dma_transfer_direction dir, unsigned long flags) -- cgit v1.2.3 From 3a95b9fbba893ebfa9b83de105707539e0228e0c Mon Sep 17 00:00:00 2001 From: Alessandro Rubini Date: Sat, 24 Nov 2012 00:22:56 +0000 Subject: pl080.h: moved from arm/include/asm/hardware to include/linux/amba/ The header is used by drivers/dma/amba-pl08x.c, which can be compiled under x86, where PL080 exists under a PCI-to-AMBA bridge. This patche moves it where it can be accessed by other architectures, and fixes all users. Signed-off-by: Alessandro Rubini Acked-by: Giancarlo Asnaghi Acked-by: Linus Walleij Signed-off-by: Vinod Koul --- include/linux/amba/pl080.h | 146 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 include/linux/amba/pl080.h (limited to 'include/linux') diff --git a/include/linux/amba/pl080.h b/include/linux/amba/pl080.h new file mode 100644 index 000000000000..3e7b62fbefbd --- /dev/null +++ b/include/linux/amba/pl080.h @@ -0,0 +1,146 @@ +/* include/linux/amba/pl080.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks + * + * ARM PrimeCell PL080 DMA controller + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/* Note, there are some Samsung updates to this controller block which + * make it not entierly compatible with the PL080 specification from + * ARM. When in doubt, check the Samsung documentation first. + * + * The Samsung defines are PL080S, and add an extra control register, + * the ability to move more than 2^11 counts of data and some extra + * OneNAND features. +*/ + +#ifndef ASM_PL080_H +#define ASM_PL080_H + +#define PL080_INT_STATUS (0x00) +#define PL080_TC_STATUS (0x04) +#define PL080_TC_CLEAR (0x08) +#define PL080_ERR_STATUS (0x0C) +#define PL080_ERR_CLEAR (0x10) +#define PL080_RAW_TC_STATUS (0x14) +#define PL080_RAW_ERR_STATUS (0x18) +#define PL080_EN_CHAN (0x1c) +#define PL080_SOFT_BREQ (0x20) +#define PL080_SOFT_SREQ (0x24) +#define PL080_SOFT_LBREQ (0x28) +#define PL080_SOFT_LSREQ (0x2C) + +#define PL080_CONFIG (0x30) +#define PL080_CONFIG_M2_BE (1 << 2) +#define PL080_CONFIG_M1_BE (1 << 1) +#define PL080_CONFIG_ENABLE (1 << 0) + +#define PL080_SYNC (0x34) + +/* Per channel configuration registers */ + +#define PL080_Cx_STRIDE (0x20) +#define PL080_Cx_BASE(x) ((0x100 + (x * 0x20))) +#define PL080_Cx_SRC_ADDR(x) ((0x100 + (x * 0x20))) +#define PL080_Cx_DST_ADDR(x) ((0x104 + (x * 0x20))) +#define PL080_Cx_LLI(x) ((0x108 + (x * 0x20))) +#define PL080_Cx_CONTROL(x) ((0x10C + (x * 0x20))) +#define PL080_Cx_CONFIG(x) ((0x110 + (x * 0x20))) +#define PL080S_Cx_CONTROL2(x) ((0x110 + (x * 0x20))) +#define PL080S_Cx_CONFIG(x) ((0x114 + (x * 0x20))) + +#define PL080_CH_SRC_ADDR (0x00) +#define PL080_CH_DST_ADDR (0x04) +#define PL080_CH_LLI (0x08) +#define PL080_CH_CONTROL (0x0C) +#define PL080_CH_CONFIG (0x10) +#define PL080S_CH_CONTROL2 (0x10) +#define PL080S_CH_CONFIG (0x14) + +#define PL080_LLI_ADDR_MASK (0x3fffffff << 2) +#define PL080_LLI_ADDR_SHIFT (2) +#define PL080_LLI_LM_AHB2 (1 << 0) + +#define PL080_CONTROL_TC_IRQ_EN (1 << 31) +#define PL080_CONTROL_PROT_MASK (0x7 << 28) +#define PL080_CONTROL_PROT_SHIFT (28) +#define PL080_CONTROL_PROT_CACHE (1 << 30) +#define PL080_CONTROL_PROT_BUFF (1 << 29) +#define PL080_CONTROL_PROT_SYS (1 << 28) +#define PL080_CONTROL_DST_INCR (1 << 27) +#define PL080_CONTROL_SRC_INCR (1 << 26) +#define PL080_CONTROL_DST_AHB2 (1 << 25) +#define PL080_CONTROL_SRC_AHB2 (1 << 24) +#define PL080_CONTROL_DWIDTH_MASK (0x7 << 21) +#define PL080_CONTROL_DWIDTH_SHIFT (21) +#define PL080_CONTROL_SWIDTH_MASK (0x7 << 18) +#define PL080_CONTROL_SWIDTH_SHIFT (18) +#define PL080_CONTROL_DB_SIZE_MASK (0x7 << 15) +#define PL080_CONTROL_DB_SIZE_SHIFT (15) +#define PL080_CONTROL_SB_SIZE_MASK (0x7 << 12) +#define PL080_CONTROL_SB_SIZE_SHIFT (12) +#define PL080_CONTROL_TRANSFER_SIZE_MASK (0xfff << 0) +#define PL080_CONTROL_TRANSFER_SIZE_SHIFT (0) + +#define PL080_BSIZE_1 (0x0) +#define PL080_BSIZE_4 (0x1) +#define PL080_BSIZE_8 (0x2) +#define PL080_BSIZE_16 (0x3) +#define PL080_BSIZE_32 (0x4) +#define PL080_BSIZE_64 (0x5) +#define PL080_BSIZE_128 (0x6) +#define PL080_BSIZE_256 (0x7) + +#define PL080_WIDTH_8BIT (0x0) +#define PL080_WIDTH_16BIT (0x1) +#define PL080_WIDTH_32BIT (0x2) + +#define PL080N_CONFIG_ITPROT (1 << 20) +#define PL080N_CONFIG_SECPROT (1 << 19) +#define PL080_CONFIG_HALT (1 << 18) +#define PL080_CONFIG_ACTIVE (1 << 17) /* RO */ +#define PL080_CONFIG_LOCK (1 << 16) +#define PL080_CONFIG_TC_IRQ_MASK (1 << 15) +#define PL080_CONFIG_ERR_IRQ_MASK (1 << 14) +#define PL080_CONFIG_FLOW_CONTROL_MASK (0x7 << 11) +#define PL080_CONFIG_FLOW_CONTROL_SHIFT (11) +#define PL080_CONFIG_DST_SEL_MASK (0xf << 6) +#define PL080_CONFIG_DST_SEL_SHIFT (6) +#define PL080_CONFIG_SRC_SEL_MASK (0xf << 1) +#define PL080_CONFIG_SRC_SEL_SHIFT (1) +#define PL080_CONFIG_ENABLE (1 << 0) + +#define PL080_FLOW_MEM2MEM (0x0) +#define PL080_FLOW_MEM2PER (0x1) +#define PL080_FLOW_PER2MEM (0x2) +#define PL080_FLOW_SRC2DST (0x3) +#define PL080_FLOW_SRC2DST_DST (0x4) +#define PL080_FLOW_MEM2PER_PER (0x5) +#define PL080_FLOW_PER2MEM_PER (0x6) +#define PL080_FLOW_SRC2DST_SRC (0x7) + +/* DMA linked list chain structure */ + +struct pl080_lli { + u32 src_addr; + u32 dst_addr; + u32 next_lli; + u32 control0; +}; + +struct pl080s_lli { + u32 src_addr; + u32 dst_addr; + u32 next_lli; + u32 control0; + u32 control1; +}; + +#endif /* ASM_PL080_H */ -- cgit v1.2.3 From 47db92f4a63499b1605b4c66f9347ba5479e7b19 Mon Sep 17 00:00:00 2001 From: Gerald Baeza Date: Fri, 21 Sep 2012 21:21:37 +0200 Subject: dmaengine: ste_dma40: physical channels number correction DMAC_ICFG[0:2]=SCHNB only allows to count 'multiple of 4' physical channels so it was ok with platforms having 8 channels but cannot be used for next versions (with 10 or 14 channels). This patch allows to provide the number of physical channels for a DMA device via platform_data, or still rely on SCHNB if platform_data announces 0 channel. Signed-off-by: Gerald Baeza Reviewed-by: Per Forlin Acked-by: Linus Walleij Acked-by: Vinod Koul Signed-off-by: Fabio Baltieri --- include/linux/platform_data/dma-ste-dma40.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/linux') diff --git a/include/linux/platform_data/dma-ste-dma40.h b/include/linux/platform_data/dma-ste-dma40.h index 9ff93b065686..833cb959f3df 100644 --- a/include/linux/platform_data/dma-ste-dma40.h +++ b/include/linux/platform_data/dma-ste-dma40.h @@ -147,6 +147,9 @@ struct stedma40_chan_cfg { * @memcpy_conf_log: default configuration of logical channel memcpy * @disabled_channels: A vector, ending with -1, that marks physical channels * that are for different reasons not available for the driver. + * @num_of_phy_chans: The number of physical channels implemented in HW. + * 0 means reading the number of channels from DMA HW but this is only valid + * for 'multiple of 4' channels, like 8. */ struct stedma40_platform_data { u32 dev_len; @@ -158,6 +161,7 @@ struct stedma40_platform_data { struct stedma40_chan_cfg *memcpy_conf_log; int disabled_channels[STEDMA40_MAX_PHYS]; bool use_esram_lcla; + int num_of_phy_chans; }; #ifdef CONFIG_STE_DMA40 -- cgit v1.2.3 From 762eb33fdebed34d98943d85ee1425663d7cceaa Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Thu, 13 Dec 2012 11:38:39 +0100 Subject: dmaengine: ste_dma40: add missing kernel-doc entry Acked-by: Linus Walleij Acked-by: Vinod Koul Signed-off-by: Fabio Baltieri --- include/linux/platform_data/dma-ste-dma40.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/platform_data/dma-ste-dma40.h b/include/linux/platform_data/dma-ste-dma40.h index 833cb959f3df..b99024ba94ec 100644 --- a/include/linux/platform_data/dma-ste-dma40.h +++ b/include/linux/platform_data/dma-ste-dma40.h @@ -147,6 +147,7 @@ struct stedma40_chan_cfg { * @memcpy_conf_log: default configuration of logical channel memcpy * @disabled_channels: A vector, ending with -1, that marks physical channels * that are for different reasons not available for the driver. + * @use_esram_lcla: flag for mapping the lcla into esram region * @num_of_phy_chans: The number of physical channels implemented in HW. * 0 means reading the number of channels from DMA HW but this is only valid * for 'multiple of 4' channels, like 8. -- cgit v1.2.3 From 7407048bec896268b50e3c43c1d012a4764dc210 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Tue, 18 Dec 2012 12:25:14 +0100 Subject: dmaengine: ste_dma40: add software lli support This patch add support to manage LLI by SW for select phy channels. There is a HW issue in certain controllers due to which on certain occassions HW LLI cannot be used on some physical channels. To avoid the HW issue on a specific phy channel, the phy channel number can be added to the list of soft_lli_channels and there after all the transfers on that channel will use software LLI, for peripheral to memory transfers. SoftLLI introduces relink overhead, that could impact performace for certain use cases. This is based on a previous patch of Narayanan Gopalakrishnan. Cc: Shreshtha Kumar Sahu Acked-by: Linus Walleij Acked-by: Vinod Koul Signed-off-by: Fabio Baltieri --- include/linux/platform_data/dma-ste-dma40.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include/linux') diff --git a/include/linux/platform_data/dma-ste-dma40.h b/include/linux/platform_data/dma-ste-dma40.h index b99024ba94ec..4b781014b0a0 100644 --- a/include/linux/platform_data/dma-ste-dma40.h +++ b/include/linux/platform_data/dma-ste-dma40.h @@ -147,6 +147,12 @@ struct stedma40_chan_cfg { * @memcpy_conf_log: default configuration of logical channel memcpy * @disabled_channels: A vector, ending with -1, that marks physical channels * that are for different reasons not available for the driver. + * @soft_lli_chans: A vector, that marks physical channels will use LLI by SW + * which avoids HW bug that exists in some versions of the controller. + * SoftLLI introduces relink overhead that could impact performace for + * certain use cases. + * @num_of_soft_lli_chans: The number of channels that needs to be configured + * to use SoftLLI. * @use_esram_lcla: flag for mapping the lcla into esram region * @num_of_phy_chans: The number of physical channels implemented in HW. * 0 means reading the number of channels from DMA HW but this is only valid @@ -161,6 +167,8 @@ struct stedma40_platform_data { struct stedma40_chan_cfg *memcpy_conf_phy; struct stedma40_chan_cfg *memcpy_conf_log; int disabled_channels[STEDMA40_MAX_PHYS]; + int *soft_lli_chans; + int num_of_soft_lli_chans; bool use_esram_lcla; int num_of_phy_chans; }; -- cgit v1.2.3 From 978c4172af48f0adc082f8b1d94acb817d947730 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 14 Feb 2013 11:00:16 +0200 Subject: dmaengine.h: remove redundant else keyword dmaengine_device_control returns -ENOSYS in case the dma driver doesn't have such functionality. Signed-off-by: Andy Shevchenko Acked-by: Viresh Kumar Signed-off-by: Vinod Koul --- include/linux/dmaengine.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index bfcdecb5d87a..f5939999cb65 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -610,8 +610,8 @@ static inline int dmaengine_device_control(struct dma_chan *chan, { if (chan->device->device_control) return chan->device->device_control(chan, cmd, arg); - else - return -ENOSYS; + + return -ENOSYS; } static inline int dmaengine_slave_config(struct dma_chan *chan, -- cgit v1.2.3