Skip to content
  • Gustavo Pimentel's avatar
    dmaengine: Add Synopsys eDMA IP core driver · e63d79d1
    Gustavo Pimentel authored
    Add Synopsys PCIe Endpoint eDMA IP core driver to kernel.
    
    This IP is generally distributed with Synopsys PCIe Endpoint IP (depends
    of the use and licensing agreement).
    
    This core driver, initializes and configures the eDMA IP using vma-helpers
    functions and dma-engine subsystem.
    
    This driver can be compile as built-in or external module in kernel.
    
    To enable this driver just select DW_EDMA option in kernel configuration,
    however it requires and selects automatically DMA_ENGINE and
    DMA_VIRTUAL_CHANNELS option too.
    
    In order to transfer data from point A to B as fast as possible this IP
    requires a dedicated memory space containing linked list of elements.
    
    All elements of this linked list are continuous and each one describes a
    data transfer (source and destination addresses, length and a control
    variable).
    
    For the sake of simplicity, lets assume a memory space for channel write
    0 which allows about 42 elements.
    
    +---------+
    | Desc #0 |-+
    +---------+ |
                V
           +----------+
           | Chunk #0 |-+
           |  CB = 1  | |  +----------+  +-----+  +-----------+  +-----+
           +----------+ +->| Burst #0 |->| ... |->| Burst #41 |->| llp |
                |          +----------+  +-----+  +-----------+  +-----+
                V
           +----------+
           | Chunk #1 |-+
           |  CB = 0  | |  +-----------+  +-----+  +-----------+  +-----+
           +----------+ +->| Burst #42 |->| ... |->| Burst #83 |->| llp |
                |          +-----------+  +-----+  +-----------+  +-----+
                V
           +----------+
           | Chunk #2 |-+
           |  CB = 1  | |  +-----------+  +-----+  +------------+  +-----+
           +----------+ +->| Burst #84 |->| ... |->| Burst #125 |->| llp |
                |          +-----------+  +-----+  +------------+  +-----+
                V
           +----------+
           | Chunk #3 |-+
           |  CB = 0  | |  +------------+  +-----+  +------------+  +-----+
           +----------+ +->| Burst #126 |->| ... |->| Burst #129 |->| llp |
                           +------------+  +-----+  +------------+  +-----+
    
    Legend:
     - Linked list, also know as Chunk
     - Linked list element*, also know as Burst *CB*, also know as Change Bit,
    it's a control bit (and typically is toggled) that allows to easily
    identify and differentiate between the current linked list and the
    previous or the next one.
     - LLP, is a special element that indicates the end of the linked list
    element stream also informs that the next CB should be toggle
    
    On every last Burst of the Chunk (Burst #41, Burst #83, Burst #125 or
    even Burst #129
    
    ) is set some flags on their control variable (RIE and
    LIE bits) that will trigger the send of "done" interruption.
    
    On the interruptions callback, is decided whether to recycle the linked
    list memory space by writing a new set of Bursts elements (if still
    exists Chunks to transfer) or is considered completed (if there is no
    Chunks available to transfer).
    
    On scatter-gather transfer mode, the client will submit a scatter-gather
    list of n (on this case 130) elements, that will be divide in multiple
    Chunks, each Chunk will have (on this case 42) a limited number of
    Bursts and after transferring all Bursts, an interrupt will be
    triggered, which will allow to recycle the all linked list dedicated
    memory again with the new information relative to the next Chunk and
    respective Burst associated and repeat the whole cycle again.
    
    On cyclic transfer mode, the client will submit a buffer pointer, length
    of it and number of repetitions, in this case each burst will correspond
    directly to each repetition.
    
    Each Burst can describes a data transfer from point A(source) to point
    B(destination) with a length that can be from 1 byte up to 4 GB. Since
    dedicated the memory space where the linked list will reside is limited,
    the whole n burst elements will be organized in several Chunks, that
    will be used later to recycle the dedicated memory space to initiate a
    new sequence of data transfers.
    
    The whole transfer is considered has completed when it was transferred
    all bursts.
    
    Currently this IP has a set well-known register map, which includes
    support for legacy and unroll modes. Legacy mode is version of this
    register map that has multiplexer register that allows to switch
    registers between all write and read channels and the unroll modes
    repeats all write and read channels registers with an offset between
    them. This register map is called v0.
    
    The IP team is creating a new register map more suitable to the latest
    PCIe features, that very likely will change the map register, which this
    version will be called v1. As soon as this new version is released by
    the IP team the support for this version in be included on this driver.
    
    According to the logic, patches 1, 2 and 3 should be squashed into 1
    unique patch, but for the sake of simplicity of review, it was divided
    in this 3 patches files.
    
    Signed-off-by: default avatarGustavo Pimentel <gustavo.pimentel@synopsys.com>
    Cc: Vinod Koul <vkoul@kernel.org>
    Cc: Dan Williams <dan.j.williams@intel.com>
    Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
    Cc: Russell King <rmk+kernel@armlinux.org.uk>
    Cc: Joao Pinto <jpinto@synopsys.com>
    Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
    e63d79d1