diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-13 01:59:53 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-13 01:59:53 +0300 |
commit | 87c779baabff157f09db6fce417a7544220f9f00 (patch) | |
tree | 3a11ac4b554a3fe52d331f1f4f72997582e87cac /Documentation | |
parent | eea0cf3fcd3243666e0bb792c560ec128b1f06a1 (diff) | |
parent | a9507ca3fb90987db5c6cc385885782cb05d4967 (diff) | |
download | linux-87c779baabff157f09db6fce417a7544220f9f00.tar.xz |
Merge branch 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma
Pull dmaengine updates from Vinod Koul:
"Main features this time are:
- BAM v1.3.0 support form qcom bam dma
- support for Allwinner sun8i dma
- atmels eXtended DMA Controller driver
- chancnt cleanup by Maxime
- fixes spread over drivers"
* 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma: (56 commits)
dmaenegine: Delete a check before free_percpu()
dmaengine: ioatdma: fix dma mapping errors
dma: cppi41: add a delay while setting the TD bit
dma: cppi41: wait longer for the HW to return the descriptor
dmaengine: fsl-edma: fixup reg offset and hw S/G support in big-endian model
dmaengine: fsl-edma: fix calculation of remaining bytes
drivers/dma/pch_dma: declare pch_dma_id_table as static
dmaengine: ste_dma40: fix error return code
dma: imx-sdma: clarify about firmware not found error
Documentation: devicetree: Fix Xilinx VDMA specification
dmaengine: pl330: update author info
dmaengine: clarify the issue_pending expectations
dmaengine: at_xdmac: Add DMA_PRIVATE
ARM: dts: at_xdmac: fix bad value of dma-cells in documentation
dmaengine: at_xdmac: fix missing spin_unlock
dmaengine: at_xdmac: fix a bug in transfer residue computation
dmaengine: at_xdmac: fix software lockup at_xdmac_tx_status()
dmaengine: at_xdmac: remove chancnt affectation
dmaengine: at_xdmac: prefer usage of readl/writel_relaxed
dmaengine: xdmac: fix print warning on dma_addr_t variable
...
Diffstat (limited to 'Documentation')
-rw-r--r-- | Documentation/devicetree/bindings/dma/atmel-xdma.txt | 54 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt | 1 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/dma/qcom_bam_dma.txt | 4 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/dma/sun6i-dma.txt | 2 | ||||
-rw-r--r-- | Documentation/dmaengine/client.txt (renamed from Documentation/dmaengine.txt) | 0 | ||||
-rw-r--r-- | Documentation/dmaengine/dmatest.txt (renamed from Documentation/dmatest.txt) | 0 | ||||
-rw-r--r-- | Documentation/dmaengine/provider.txt | 366 |
7 files changed, 425 insertions, 2 deletions
diff --git a/Documentation/devicetree/bindings/dma/atmel-xdma.txt b/Documentation/devicetree/bindings/dma/atmel-xdma.txt new file mode 100644 index 000000000000..0eb2b3207e08 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/atmel-xdma.txt @@ -0,0 +1,54 @@ +* Atmel Extensible Direct Memory Access Controller (XDMAC) + +* XDMA Controller +Required properties: +- compatible: Should be "atmel,<chip>-dma". + <chip> compatible description: + - sama5d4: first SoC adding the XDMAC +- reg: Should contain DMA registers location and length. +- interrupts: Should contain DMA interrupt. +- #dma-cells: Must be <1>, used to represent the number of integer cells in +the dmas property of client devices. + - The 1st cell specifies the channel configuration register: + - bit 13: SIF, source interface identifier, used to get the memory + interface identifier, + - bit 14: DIF, destination interface identifier, used to get the peripheral + interface identifier, + - bit 30-24: PERID, peripheral identifier. + +Example: + +dma1: dma-controller@f0004000 { + compatible = "atmel,sama5d4-dma"; + reg = <0xf0004000 0x200>; + interrupts = <50 4 0>; + #dma-cells = <1>; +}; + + +* DMA clients +DMA clients connected to the Atmel XDMA controller must use the format +described in the dma.txt file, using a one-cell specifier for each channel. +The two cells in order are: +1. A phandle pointing to the DMA controller. +2. Channel configuration register. Configurable fields are: + - bit 13: SIF, source interface identifier, used to get the memory + interface identifier, + - bit 14: DIF, destination interface identifier, used to get the peripheral + interface identifier, + - bit 30-24: PERID, peripheral identifier. + +Example: + +i2c2: i2c@f8024000 { + compatible = "atmel,at91sam9x5-i2c"; + reg = <0xf8024000 0x4000>; + interrupts = <34 4 6>; + dmas = <&dma1 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) + | AT91_XDMAC_DT_PERID(6))>, + <&dma1 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) + | AT91_XDMAC_DT_PERID(7))>; + dma-names = "tx", "rx"; +}; diff --git a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt index 4659fd952301..dc8d3aac1aa9 100644 --- a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt +++ b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt @@ -48,6 +48,7 @@ The full ID of peripheral types can be found below. 21 ESAI 22 SSI Dual FIFO (needs firmware ver >= 2) 23 Shared ASRC + 24 SAI The third cell specifies the transfer priority as below. diff --git a/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt b/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt index d75a9d767022..f8c3311b7153 100644 --- a/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt +++ b/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt @@ -1,7 +1,9 @@ QCOM BAM DMA controller Required properties: -- compatible: must contain "qcom,bam-v1.4.0" for MSM8974 +- compatible: must be one of the following: + * "qcom,bam-v1.4.0" for MSM8974, APQ8074 and APQ8084 + * "qcom,bam-v1.3.0" for APQ8064, IPQ8064 and MSM8960 - reg: Address range for DMA registers - interrupts: Should contain the one interrupt shared by all channels - #dma-cells: must be <1>, the cell in the dmas property of the client device diff --git a/Documentation/devicetree/bindings/dma/sun6i-dma.txt b/Documentation/devicetree/bindings/dma/sun6i-dma.txt index 3e145c1675b1..9cdcba24d7c3 100644 --- a/Documentation/devicetree/bindings/dma/sun6i-dma.txt +++ b/Documentation/devicetree/bindings/dma/sun6i-dma.txt @@ -4,7 +4,7 @@ This driver follows the generic DMA bindings defined in dma.txt. Required properties: -- compatible: Must be "allwinner,sun6i-a31-dma" +- compatible: Must be "allwinner,sun6i-a31-dma" or "allwinner,sun8i-a23-dma" - reg: Should contain the registers base address and length - interrupts: Should contain a reference to the interrupt used by this device - clocks: Should contain a reference to the parent AHB clock diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine/client.txt index 11fb87ff6cd0..11fb87ff6cd0 100644 --- a/Documentation/dmaengine.txt +++ b/Documentation/dmaengine/client.txt diff --git a/Documentation/dmatest.txt b/Documentation/dmaengine/dmatest.txt index dd77a81bdb80..dd77a81bdb80 100644 --- a/Documentation/dmatest.txt +++ b/Documentation/dmaengine/dmatest.txt diff --git a/Documentation/dmaengine/provider.txt b/Documentation/dmaengine/provider.txt new file mode 100644 index 000000000000..766658ccf235 --- /dev/null +++ b/Documentation/dmaengine/provider.txt @@ -0,0 +1,366 @@ +DMAengine controller documentation +================================== + +Hardware Introduction ++++++++++++++++++++++ + +Most of the Slave DMA controllers have the same general principles of +operations. + +They have a given number of channels to use for the DMA transfers, and +a given number of requests lines. + +Requests and channels are pretty much orthogonal. Channels can be used +to serve several to any requests. To simplify, channels are the +entities that will be doing the copy, and requests what endpoints are +involved. + +The request lines actually correspond to physical lines going from the +DMA-eligible devices to the controller itself. Whenever the device +will want to start a transfer, it will assert a DMA request (DRQ) by +asserting that request line. + +A very simple DMA controller would only take into account a single +parameter: the transfer size. At each clock cycle, it would transfer a +byte of data from one buffer to another, until the transfer size has +been reached. + +That wouldn't work well in the real world, since slave devices might +require a specific number of bits to be transferred in a single +cycle. For example, we may want to transfer as much data as the +physical bus allows to maximize performances when doing a simple +memory copy operation, but our audio device could have a narrower FIFO +that requires data to be written exactly 16 or 24 bits at a time. This +is why most if not all of the DMA controllers can adjust this, using a +parameter called the transfer width. + +Moreover, some DMA controllers, whenever the RAM is used as a source +or destination, can group the reads or writes in memory into a buffer, +so instead of having a lot of small memory accesses, which is not +really efficient, you'll get several bigger transfers. This is done +using a parameter called the burst size, that defines how many single +reads/writes it's allowed to do without the controller splitting the +transfer into smaller sub-transfers. + +Our theoretical DMA controller would then only be able to do transfers +that involve a single contiguous block of data. However, some of the +transfers we usually have are not, and want to copy data from +non-contiguous buffers to a contiguous buffer, which is called +scatter-gather. + +DMAEngine, at least for mem2dev transfers, require support for +scatter-gather. So we're left with two cases here: either we have a +quite simple DMA controller that doesn't support it, and we'll have to +implement it in software, or we have a more advanced DMA controller, +that implements in hardware scatter-gather. + +The latter are usually programmed using a collection of chunks to +transfer, and whenever the transfer is started, the controller will go +over that collection, doing whatever we programmed there. + +This collection is usually either a table or a linked list. You will +then push either the address of the table and its number of elements, +or the first item of the list to one channel of the DMA controller, +and whenever a DRQ will be asserted, it will go through the collection +to know where to fetch the data from. + +Either way, the format of this collection is completely dependent on +your hardware. Each DMA controller will require a different structure, +but all of them will require, for every chunk, at least the source and +destination addresses, whether it should increment these addresses or +not and the three parameters we saw earlier: the burst size, the +transfer width and the transfer size. + +The one last thing is that usually, slave devices won't issue DRQ by +default, and you have to enable this in your slave device driver first +whenever you're willing to use DMA. + +These were just the general memory-to-memory (also called mem2mem) or +memory-to-device (mem2dev) kind of transfers. Most devices often +support other kind of transfers or memory operations that dmaengine +support and will be detailed later in this document. + +DMA Support in Linux +++++++++++++++++++++ + +Historically, DMA controller drivers have been implemented using the +async TX API, to offload operations such as memory copy, XOR, +cryptography, etc., basically any memory to memory operation. + +Over time, the need for memory to device transfers arose, and +dmaengine was extended. Nowadays, the async TX API is written as a +layer on top of dmaengine, and acts as a client. Still, dmaengine +accommodates that API in some cases, and made some design choices to +ensure that it stayed compatible. + +For more information on the Async TX API, please look the relevant +documentation file in Documentation/crypto/async-tx-api.txt. + +DMAEngine Registration +++++++++++++++++++++++ + +struct dma_device Initialization +-------------------------------- + +Just like any other kernel framework, the whole DMAEngine registration +relies on the driver filling a structure and registering against the +framework. In our case, that structure is dma_device. + +The first thing you need to do in your driver is to allocate this +structure. Any of the usual memory allocators will do, but you'll also +need to initialize a few fields in there: + + * channels: should be initialized as a list using the + INIT_LIST_HEAD macro for example + + * dev: should hold the pointer to the struct device associated + to your current driver instance. + +Supported transaction types +--------------------------- + +The next thing you need is to set which transaction types your device +(and driver) supports. + +Our dma_device structure has a field called cap_mask that holds the +various types of transaction supported, and you need to modify this +mask using the dma_cap_set function, with various flags depending on +transaction types you support as an argument. + +All those capabilities are defined in the dma_transaction_type enum, +in include/linux/dmaengine.h + +Currently, the types available are: + * DMA_MEMCPY + - The device is able to do memory to memory copies + + * DMA_XOR + - The device is able to perform XOR operations on memory areas + - Used to accelerate XOR intensive tasks, such as RAID5 + + * DMA_XOR_VAL + - The device is able to perform parity check using the XOR + algorithm against a memory buffer. + + * DMA_PQ + - The device is able to perform RAID6 P+Q computations, P being a + simple XOR, and Q being a Reed-Solomon algorithm. + + * DMA_PQ_VAL + - The device is able to perform parity check using RAID6 P+Q + algorithm against a memory buffer. + + * DMA_INTERRUPT + - The device is able to trigger a dummy transfer that will + generate periodic interrupts + - Used by the client drivers to register a callback that will be + called on a regular basis through the DMA controller interrupt + + * DMA_SG + - The device supports memory to memory scatter-gather + transfers. + - Even though a plain memcpy can look like a particular case of a + scatter-gather transfer, with a single chunk to transfer, it's a + distinct transaction type in the mem2mem transfers case + + * DMA_PRIVATE + - The devices only supports slave transfers, and as such isn't + available for async transfers. + + * DMA_ASYNC_TX + - Must not be set by the device, and will be set by the framework + if needed + - /* TODO: What is it about? */ + + * DMA_SLAVE + - The device can handle device to memory transfers, including + scatter-gather transfers. + - While in the mem2mem case we were having two distinct types to + deal with a single chunk to copy or a collection of them, here, + we just have a single transaction type that is supposed to + handle both. + - If you want to transfer a single contiguous memory buffer, + simply build a scatter list with only one item. + + * DMA_CYCLIC + - The device can handle cyclic transfers. + - A cyclic transfer is a transfer where the chunk collection will + loop over itself, with the last item pointing to the first. + - It's usually used for audio transfers, where you want to operate + on a single ring buffer that you will fill with your audio data. + + * DMA_INTERLEAVE + - The device supports interleaved transfer. + - These transfers can transfer data from a non-contiguous buffer + to a non-contiguous buffer, opposed to DMA_SLAVE that can + transfer data from a non-contiguous data set to a continuous + destination buffer. + - It's usually used for 2d content transfers, in which case you + want to transfer a portion of uncompressed data directly to the + display to print it + +These various types will also affect how the source and destination +addresses change over time. + +Addresses pointing to RAM are typically incremented (or decremented) +after each transfer. In case of a ring buffer, they may loop +(DMA_CYCLIC). Addresses pointing to a device's register (e.g. a FIFO) +are typically fixed. + +Device operations +----------------- + +Our dma_device structure also requires a few function pointers in +order to implement the actual logic, now that we described what +operations we were able to perform. + +The functions that we have to fill in there, and hence have to +implement, obviously depend on the transaction types you reported as +supported. + + * device_alloc_chan_resources + * device_free_chan_resources + - These functions will be called whenever a driver will call + dma_request_channel or dma_release_channel for the first/last + time on the channel associated to that driver. + - They are in charge of allocating/freeing all the needed + resources in order for that channel to be useful for your + driver. + - These functions can sleep. + + * device_prep_dma_* + - These functions are matching the capabilities you registered + previously. + - These functions all take the buffer or the scatterlist relevant + for the transfer being prepared, and should create a hardware + descriptor or a list of hardware descriptors from it + - These functions can be called from an interrupt context + - Any allocation you might do should be using the GFP_NOWAIT + flag, in order not to potentially sleep, but without depleting + the emergency pool either. + - Drivers should try to pre-allocate any memory they might need + during the transfer setup at probe time to avoid putting to + much pressure on the nowait allocator. + + - It should return a unique instance of the + dma_async_tx_descriptor structure, that further represents this + particular transfer. + + - This structure can be initialized using the function + dma_async_tx_descriptor_init. + - You'll also need to set two fields in this structure: + + flags: + TODO: Can it be modified by the driver itself, or + should it be always the flags passed in the arguments + + + tx_submit: A pointer to a function you have to implement, + that is supposed to push the current + transaction descriptor to a pending queue, waiting + for issue_pending to be called. + + * device_issue_pending + - Takes the first transaction descriptor in the pending queue, + and starts the transfer. Whenever that transfer is done, it + should move to the next transaction in the list. + - This function can be called in an interrupt context + + * device_tx_status + - Should report the bytes left to go over on the given channel + - Should only care about the transaction descriptor passed as + argument, not the currently active one on a given channel + - The tx_state argument might be NULL + - Should use dma_set_residue to report it + - In the case of a cyclic transfer, it should only take into + account the current period. + - This function can be called in an interrupt context. + + * device_control + - Used by client drivers to control and configure the channel it + has a handle on. + - Called with a command and an argument + + The command is one of the values listed by the enum + dma_ctrl_cmd. The valid commands are: + + DMA_PAUSE + + Pauses a transfer on the channel + + This command should operate synchronously on the channel, + pausing right away the work of the given channel + + DMA_RESUME + + Restarts a transfer on the channel + + This command should operate synchronously on the channel, + resuming right away the work of the given channel + + DMA_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 + + DMA_SLAVE_CONFIG + + Reconfigures the channel with passed configuration + + This command should NOT perform synchronously, or on any + currently queued transfers, but only on subsequent ones + + In this case, the function will receive a + dma_slave_config structure pointer as an argument, that + will detail which configuration to use. + + Even though that structure contains a direction field, + this field is deprecated in favor of the direction + argument given to the prep_* functions + + FSLDMA_EXTERNAL_START + + TODO: Why does that even exist? + + The argument is an opaque unsigned long. This actually is a + pointer to a struct dma_slave_config that should be used only + in the DMA_SLAVE_CONFIG. + + * device_slave_caps + - Called through the framework by client drivers in order to have + an idea of what are the properties of the channel allocated to + them. + - Such properties are the buswidth, available directions, etc. + - Required for every generic layer doing DMA transfers, such as + ASoC. + +Misc notes (stuff that should be documented, but don't really know +where to put them) +------------------------------------------------------------------ + * dma_run_dependencies + - Should be called at the end of an async TX transfer, and can be + ignored in the slave transfers case. + - Makes sure that dependent operations are run before marking it + as complete. + + * dma_cookie_t + - it's a DMA transaction ID that will increment over time. + - Not really relevant any more since the introduction of virt-dma + that abstracts it away. + + * DMA_CTRL_ACK + - Undocumented feature + - No one really has an idea of what it's about, besides being + related to reusing the DMA transaction descriptors or having + additional transactions added to it in the async-tx API + - Useless in the case of the slave API + +General Design Notes +-------------------- + +Most of the DMAEngine drivers you'll see are based on a similar design +that handles the end of transfer interrupts in the handler, but defer +most work to a tasklet, including the start of a new transfer whenever +the previous transfer ended. + +This is a rather inefficient design though, because the inter-transfer +latency will be not only the interrupt latency, but also the +scheduling latency of the tasklet, which will leave the channel idle +in between, which will slow down the global transfer rate. + +You should avoid this kind of practice, and instead of electing a new +transfer in your tasklet, move that part to the interrupt handler in +order to have a shorter idle window (that we can't really avoid +anyway). + +Glossary +-------- + +Burst: A number of consecutive read or write operations + that can be queued to buffers before being flushed to + memory. +Chunk: A contiguous collection of bursts +Transfer: A collection of chunks (be it contiguous or not) |