09 Oct, 2020

2 commits

  • The DW SSI errors handling method can be generically implemented for all
    types of the transfers: IRQ, DMA and poll-based ones. It will be a
    function which checks the overflow/underflow error flags and resets the
    controller if any of them is set. In the framework of this commit we make
    use of the new method to detect the errors in the IRQ- and DMA-based SPI
    transfer execution procedures.

    Signed-off-by: Serge Semin
    Link: https://lore.kernel.org/r/20201007235511.4935-17-Sergey.Semin@baikalelectronics.ru
    Signed-off-by: Mark Brown

    Serge Semin
     
  • The parameter will be needed for another wait-done method being added in
    the framework of the SPI memory operation modification in a further
    commit.

    Signed-off-by: Serge Semin
    Link: https://lore.kernel.org/r/20201007235511.4935-16-Sergey.Semin@baikalelectronics.ru
    Signed-off-by: Mark Brown

    Serge Semin
     

29 Sep, 2020

11 commits

  • In case if at least one of the requested DMA engine channels doesn't
    support the hardware accelerated SG list entries traverse, the DMA driver
    will most likely work that around by performing the IRQ-based SG list
    entries resubmission. That might and will cause a problem if the DMA Tx
    channel is recharged and re-executed before the Rx DMA channel. Due to
    non-deterministic IRQ-handler execution latency the DMA Tx channel will
    start pushing data to the SPI bus before the Rx DMA channel is even
    reinitialized with the next inbound SG list entry. By doing so the DMA
    Tx channel will implicitly start filling the DW APB SSI Rx FIFO up, which
    while the DMA Rx channel being recharged and re-executed will eventually
    be overflown.

    In order to solve the problem we have to feed the DMA engine with SG
    list entries one-by-one. It shall keep the DW APB SSI Tx and Rx FIFOs
    synchronized and prevent the Rx FIFO overflow. Since in general the SPI
    tx_sg and rx_sg lists may have different number of entries of different
    lengths (though total length should match) we virtually split the
    SG-lists to the set of DMA transfers, which length is a minimum of the
    ordered SG-entries lengths.

    The solution described above is only executed if a full-duplex SPI
    transfer is requested and the DMA engine hasn't provided channels with
    hardware accelerated SG list traverse capability to handle both SG
    lists at once.

    Signed-off-by: Serge Semin
    Suggested-by: Andy Shevchenko
    Link: https://lore.kernel.org/r/20200920112322.24585-12-Sergey.Semin@baikalelectronics.ru
    Signed-off-by: Mark Brown

    Serge Semin
     
  • In order to use the DMA submission and waiting methods in both generic
    DMA-based SPI transfer and one-by-one DMA SG entries transmission
    functions, we need to modify the dw_spi_dma_wait() and
    dw_spi_dma_submit_tx()/dw_spi_dma_submit_rx() prototypes. So instead of
    getting the SPI transfer object as the second argument they must accept
    the exact data structure instances they imply to use. Those are the
    current transfer length and the SPI bus frequency in case of
    dw_spi_dma_wait(), and SG list together with number of list entries in
    case of the DMA Tx/Rx submission methods.

    Signed-off-by: Serge Semin
    Link: https://lore.kernel.org/r/20200920112322.24585-11-Sergey.Semin@baikalelectronics.ru
    Signed-off-by: Mark Brown

    Serge Semin
     
  • DW APB SSI DMA driver doesn't use the native SPI core wait API since
    commit bdbdf0f06337 ("spi: dw: Locally wait for the DMA transfers
    completion"). Due to that the driver can now clear the DMAC register
    in a single place synchronously with the DMA transactions completion
    or failure. After that all the possible code paths are still covered:
    1) DMA completion callbacks are executed in case if the corresponding DMA
    transactions are finished. When they are, one of them will eventually wake
    the SPI messages pump kernel thread and dw_spi_dma_transfer_all() method
    will clean the DMAC register as implied by this patch.
    2) dma_stop is called when the SPI core detects an error either returned
    from the transfer_one() callback or set in the SPI message status field.
    Both types of errors will be noticed by the dw_spi_dma_transfer_all()
    method.
    3) dma_exit is called when either SPI controller driver or the
    corresponding device is removed. In any case the SPI core will first
    flush the SPI messages pump kernel thread, so any pending or in-fly
    SPI transfers will be finished before that.

    Due to all of that let's simplify the DW APB SSI DMA driver a bit and
    move the DMAC register cleanup to a single place in the
    dw_spi_dma_transfer_all() method.

    Signed-off-by: Serge Semin
    Link: https://lore.kernel.org/r/20200920112322.24585-10-Sergey.Semin@baikalelectronics.ru
    Signed-off-by: Mark Brown

    Serge Semin
     
  • In order to add an alternative method of DMA-based SPI transfer first we
    need to detach the currently available one from the common code. Here we
    move the normal DMA-based SPI transfer execution functionality into a
    dedicated method. It will be utilized if either the DMA engine supports
    an unlimited number SG entries or Tx-only SPI transfer is requested. But
    currently just use it for any SPI transfer.

    Signed-off-by: Serge Semin
    Link: https://lore.kernel.org/r/20200920112322.24585-9-Sergey.Semin@baikalelectronics.ru
    Signed-off-by: Mark Brown

    Serge Semin
     
  • It's pointless to pass the Rx and Tx transfers DMA Tx-descriptors, since
    they are used in the Tx/Rx submit method only. Instead just return the
    submission status from these methods. This alteration will make the code
    less complex.

    Signed-off-by: Serge Semin
    Link: https://lore.kernel.org/r/20200920112322.24585-8-Sergey.Semin@baikalelectronics.ru
    Signed-off-by: Mark Brown

    Serge Semin
     
  • We suggest to add the dmaengine_submit() return value test for errors. It
    has been unnecessary while the driver was expected to be utilized in pair
    with DW DMAC. But since now the driver can be used with any DMA engine, it
    might be useful to track the errors on DMA submissions so not miss them
    and get into an unpredictable driver behaviour.

    Signed-off-by: Serge Semin
    Link: https://lore.kernel.org/r/20200920112322.24585-7-Sergey.Semin@baikalelectronics.ru
    Signed-off-by: Mark Brown

    Serge Semin
     
  • Indeed we can freely move the dmaengine_submit() method invocation and the
    Tx and Rx busy flag setting into the DMA Tx/Rx prepare methods. Since the
    Tx/Rx preparation method is now mainly used for the DMA transfers
    submission, here we suggest to rename it to have the _submit_{r,t}x suffix
    instead.

    By having this alteration applied first we implement another code
    preparation before adding the one-by-one DMA SG entries transmission,
    second we now have the dma_async_tx_descriptor descriptor used locally
    only in the new DMA transfers submission methods (this will be cleaned up
    a bit later), third we make the generic transfer method more readable,
    where now the functionality of submission, execution and wait procedures
    is transparently split up instead of having a preparation, intermixed
    submission/execution and wait procedures.

    Signed-off-by: Serge Semin
    Link: https://lore.kernel.org/r/20200920112322.24585-6-Sergey.Semin@baikalelectronics.ru
    Signed-off-by: Mark Brown

    Serge Semin
     
  • Checking rx_buf for being NULL and returning NULL from the Rx-channel
    preparation method doesn't let us to distinguish that situation from
    errors happening during the Rx SG-list preparation. So it's better to make
    sure that the rx_buf not-NULL and full-duplex communication is requested
    prior calling the Rx preparation method.

    Signed-off-by: Serge Semin
    Link: https://lore.kernel.org/r/20200920112322.24585-5-Sergey.Semin@baikalelectronics.ru
    Signed-off-by: Mark Brown

    Serge Semin
     
  • Mainly this is a preparation patch before adding one-by-one DMA SG entries
    transmission. But logically the Tx and Rx DMA channels setup should be
    performed in the dma_setup() callback anyway. So we'll move the DMA slave
    channels src/dst burst lengths, address and address width configuration
    from the Tx/Rx channels preparation methods to the dedicated functions and
    then make sure it's called at the DMA setup stage.

    Note we now make sure the return value of the dmaengine_slave_config()
    method doesn't indicate an error. It has been unnecessary in case if Dw
    DMAC is utilized as a DMA engine, since its device_config() callback
    always returns zero (though it might change in future). But since DW APB
    SSI driver now supports any DMA back-end we must make sure the DMA device
    configuration has been successful before proceeding with further setups.

    Signed-off-by: Serge Semin
    Link: https://lore.kernel.org/r/20200920112322.24585-4-Sergey.Semin@baikalelectronics.ru
    Signed-off-by: Mark Brown

    Serge Semin
     
  • Since commit 46164fde6b78 ("spi: dw: Fix Rx-only DMA transfers") if DMA
    interface is enabled, then Tx-buffer must be available in each SPI
    transfer. It's required since in order to activate the incoming data
    reception either DMA or CPU must be pushing data out to the SPI bus.
    But the DW APB SSI DMA driver code is still left in state as if Tx-buffer
    might be optional, which is no longer true. Let's fix it so an error would
    be returned if no Tx-buffer detected and DMA Tx would be always
    enabled.

    Signed-off-by: Serge Semin
    Link: https://lore.kernel.org/r/20200920112322.24585-3-Sergey.Semin@baikalelectronics.ru
    Signed-off-by: Mark Brown

    Serge Semin
     
  • Indeed the registers content doesn't get cleared when the SPI controller
    is disabled and enabled. Max burst lengths aren't changed since the Rx and
    Tx DMA channels are requested on init stage and are kept acquired until
    the device is removed. Obviously SPI controller FIFO depth can't be
    changed. Due to all of that we can safely move the DMA Transmit and
    Receive data level registers initialization to the SPI controller DMA init
    stage (when the SPI controller is being probed) instead of doing it for
    each SPI transfer when dma_setup is called. This shall speed the DMA-based
    SPI transfer initialization up a bit, particularly if the APB bus is
    relatively slow.

    Signed-off-by: Serge Semin
    Link: https://lore.kernel.org/r/20200920112322.24585-2-Sergey.Semin@baikalelectronics.ru
    Signed-off-by: Mark Brown

    Serge Semin
     

22 Jul, 2020

1 commit

  • It turns out having a Rx DMA channel serviced with higher priority than
    a Tx DMA channel is not enough to provide a well balanced DMA-based SPI
    transfer interface. There might still be moments when the Tx DMA channel
    is occasionally handled faster than the Rx DMA channel. That in its turn
    will eventually cause the SPI Rx FIFO overflow if SPI bus speed is high
    enough to fill the SPI Rx FIFO in before it's cleared by the Rx DMA
    channel. That's why having the DMA-based SPI Tx interface too optimized
    is the errors prone, so the commit 0b2b66514fc9 ("spi: dw: Use DMA max
    burst to set the request thresholds") though being perfectly normal from
    the standard functionality point of view implicitly introduced the problem
    described above. In order to fix that the Tx DMA activity is intentionally
    slowed down by limiting the SPI Tx FIFO depth with a value twice bigger
    than the Tx burst length calculated earlier by the
    dw_spi_dma_maxburst_init() method.

    Fixes: 0b2b66514fc9 ("spi: dw: Use DMA max burst to set the request thresholds")
    Signed-off-by: Serge Semin
    Reviewed-by: Andy Shevchenko
    Cc: Andy Shevchenko
    Cc: Alexey Malahov
    Cc: Feng Tang
    Link: https://lore.kernel.org/r/20200721203951.2159-1-Sergey.Semin@baikalelectronics.ru
    Signed-off-by: Mark Brown

    Serge Semin
     

30 May, 2020

2 commits

  • It's better to understand what bits are set for DMA and for IRQ handling
    in mid_spi_dma_setup() if they are grouped accordingly. Thus,
    refactor mid_spi_dma_setup() to separate DMA and IRQ configuration.

    Signed-off-by: Andy Shevchenko
    Link: https://lore.kernel.org/r/20200529183150.44149-2-andriy.shevchenko@linux.intel.com
    Signed-off-by: Mark Brown

    Andy Shevchenko
     
  • The 2afccbd283ae ("spi: dw: Discard static DW DMA slave structures")
    did a clean up of global variables, which is fine, but messed up with
    the carefully provided information in the custom DMA slave structures.
    There reader can find an assignment of the DMA request lines in use.

    Partially revert the above mentioned commit to restore readability
    and maintainability of the code.

    Signed-off-by: Andy Shevchenko
    Link: https://lore.kernel.org/r/20200529183150.44149-1-andriy.shevchenko@linux.intel.com
    Signed-off-by: Mark Brown

    Andy Shevchenko
     

29 May, 2020

2 commits

  • Since from now the former Intel MID platform layer is used as a generic
    DW SPI DMA module, let's alter the internal methods naming to be
    DMA-related instead of having the "mid_" prefix.

    Co-developed-by: Georgy Vlasov
    Co-developed-by: Ramil Zaripov
    Signed-off-by: Georgy Vlasov
    Signed-off-by: Ramil Zaripov
    Signed-off-by: Serge Semin
    Reviewed-by: Andy Shevchenko
    Cc: Alexey Malahov
    Cc: Thomas Bogendoerfer
    Cc: Arnd Bergmann
    Cc: Feng Tang
    Cc: Rob Herring
    Cc: linux-mips@vger.kernel.org
    Cc: devicetree@vger.kernel.org
    Link: https://lore.kernel.org/r/20200529131205.31838-14-Sergey.Semin@baikalelectronics.ru
    Signed-off-by: Mark Brown

    Serge Semin
     
  • This is a preparation patch before adding the DW DMA support into the
    DW SPI MMIO driver. We need to unpin the Non-DMA-specific code from the
    intended to be generic DW APB SSI DMA code. This isn't that hard,
    since the most part of the spi-dw-mid.c driver in fact implements a
    generic DMA interface for the DW SPI controller driver. The only Intel
    MID specifics concern getting the max frequency from the MRST Clock
    Control Unit and fetching the DMA controller channels from
    corresponding PCIe DMA controller. Since first one is related with the
    SPI interface configuration we moved it' implementation into the
    DW PCIe-SPI driver module. After that former spi-dw-mid.c file
    can be just renamed to be the DW SPI DMA module optionally compiled in to
    the DW APB SSI core driver.

    Co-developed-by: Georgy Vlasov
    Co-developed-by: Ramil Zaripov
    Signed-off-by: Georgy Vlasov
    Signed-off-by: Ramil Zaripov
    Signed-off-by: Serge Semin
    Reviewed-by: Andy Shevchenko
    Cc: Alexey Malahov
    Cc: Thomas Bogendoerfer
    Cc: Arnd Bergmann
    Cc: Feng Tang
    Cc: Rob Herring
    Cc: linux-mips@vger.kernel.org
    Cc: devicetree@vger.kernel.org
    Link: https://lore.kernel.org/r/20200529131205.31838-11-Sergey.Semin@baikalelectronics.ru
    Signed-off-by: Mark Brown

    Serge Semin