16 Mar, 2019

1 commit


13 Mar, 2019

1 commit

  • Commit 71abd29057cb ("spi: imx: Add support for SPI Slave mode") added
    an RX FIFO flush before start of a transfer. In slave mode, the master
    may have sent more data than expected and this data will still be in the
    RX FIFO at the start of the next transfer, and so needs to be flushed.

    However, the code to do the flush was accidentally saving this data into
    the previous transfer's RX buffer, clobbering the contents of whatever
    followed that buffer.

    Change it to empty the FIFO and throw away the data. Every one of the
    RX functions for the different eCSPI versions and modes reads the RX
    FIFO data using the same readl() call, so just use that, rather than
    using the spi_imx->rx function pointer and making sure all the different
    rx functions have a working "throw away" mode.

    There is another issue, which affects master mode when switching from
    DMA to PIO. There can be extra data in the RX FIFO which triggers this
    flush code, causing memory corruption in the same manner. I don't know
    why this data is unexpectedly in the FIFO. It's likely there is a
    different bug or erratum responsible for that. But regardless of that,
    I think this is proper fix the for bug at hand here.

    Fixes: 71abd29057cb ("spi: imx: Add support for SPI Slave mode")
    Cc: Jiada Wang
    Cc: Fabio Estevam
    Cc: Stefan Agner
    Cc: Shawn Guo
    Signed-off-by: Trent Piepho
    Signed-off-by: Mark Brown

    Trent Piepho
     

12 Mar, 2019

1 commit

  • Add the boolean module parameter "use_dma" to control the use of DMA by
    the driver. There are about two dozen other drivers with a "use_dma"
    parameter of some sort.

    DMA may allow faster and more efficient transfers than using PIO, but it
    also adds overhead for small transfers.

    High speed receive operations may be less likely to have issues with
    FIFO overflow when using DMA than when using PIO.

    The eCSPI appears to insert a 4 bit pause after each word in DMA mode,
    not done in PIO mode, which can make DMA transfers 50% slower than PIO.

    In some cases DMA may be a net win while in others PIO might be. It
    depends on the application. So allow DMA to be enabled or disabled at
    the driver level. The default will be to have it enabled when possible.

    Signed-off-by: Trent Piepho
    Signed-off-by: Mark Brown

    Trent Piepho
     

11 Dec, 2018

5 commits

  • The driver data's member variable just caches the transfer's speed_hz
    member. All users of the former now have access directly to the latter.
    So fix them to use the uncached value and remove the cache.

    Signed-off-by: Uwe Kleine-König
    Signed-off-by: Mark Brown

    Uwe Kleine-König
     
  • The config callback is called once per transfer while some things can (and
    should) be done on a per message manner. To have unambiguous naming in the
    end include "transfer" in the callback's name and rename the
    implementations accordingly. Also pass the driver struct and transfer
    which allows further simplifications in the following patch.

    There is no change in behavior intended here.

    Reviewed-by: Marek Vasut
    Signed-off-by: Uwe Kleine-König
    Signed-off-by: Mark Brown

    Uwe Kleine-König
     
  • This change fixes some random style issues that I noticed while debugging
    the driver: Remove some double spaces, use tabs for indention instead
    of spaces if possible, fix comment style.

    Signed-off-by: Uwe Kleine-König
    Signed-off-by: Mark Brown

    Uwe Kleine-König
     
  • The relevant difference between prepare_message and config is that the
    former is run before the CS signal is asserted. So the polarity of the
    CLK line must be configured in prepare_message as an edge generated by
    config might already result in a latch of the MOSI line.

    Signed-off-by: Uwe Kleine-König
    Signed-off-by: Mark Brown

    Uwe Kleine-König
     
  • This is just preparatory work which allows to move some initialisation
    that currently is done in the per transfer hook .config to an earlier
    point in time in the next few patches. There is no change in behaviour
    introduced by this patch.

    Signed-off-by: Uwe Kleine-König
    Signed-off-by: Mark Brown

    Uwe Kleine-König
     

13 Oct, 2018

3 commits

  • Use PIO mode instead if size is smaller than fifo size, since
    dma may be less efficient.

    Signed-off-by: Robin Gong
    Signed-off-by: Mark Brown

    Robin Gong
     
  • Correct wml as the last rx sg length instead of the whole transfer
    length. Otherwise, mtd_stresstest will be failed as below:

    insmod mtd_stresstest.ko dev=0
    =================================================
    mtd_stresstest: MTD device: 0
    mtd_stresstest: not NAND flash, assume page size is 512 bytes.
    mtd_stresstest: MTD device size 4194304, eraseblock size 65536, page size 512, count of eraseblocks 64, pa0
    mtd_stresstest: doing operations
    mtd_stresstest: 0 operations done
    mtd_test: mtd_read from 1ff532, size 880
    mtd_test: mtd_read from 20c267, size 64998
    spi_master spi0: I/O Error in DMA RX
    m25p80 spi0.0: SPI transfer failed: -110
    spi_master spi0: failed to transfer one message from queue
    mtd_test: error: read failed at 0x20c267
    mtd_stresstest: error -110 occurred
    =================================================
    insmod: ERROR: could not insert module mtd_stresstest.ko: Connection timed out

    Signed-off-by: Robin Gong
    Signed-off-by: Mark Brown

    Robin Gong
     
  • Current dynamic burst length is based on the whole transfer length,
    that's ok if there is only one sg, but is not right in case multi sgs
    in one transfer,because the tail data should be based on the last sg
    length instead of the whole transfer length. Move wml setting for DMA
    to the later place, thus, the next patch could get the right last sg
    length for wml setting. This patch is a preparation one, no any
    function change involved.

    Signed-off-by: Robin Gong
    Signed-off-by: Mark Brown

    Robin Gong
     

24 Jul, 2018

5 commits

  • Dynamic burst mode allows to group together multiple words and send them
    in one continuous burst. When the number of bytes to be sent is not a
    strict multiple of the FIFO entry size (32 bits), the controller expects
    the non aligned bits to be sent first.

    This commit adds support for this particular constraint, avoiding the
    need to send the non-aligned bytes one by one at the end of the
    transfer, speeding-up transfer speed in that case.

    With this method, a transfer is divided into multiple bursts, limited in
    size by the maximum amount of data that the controller can transfer in
    one continuous burst (which is 512 bytes).

    The non-512 byte part of the transfer is sent first. The remaining bytes
    to be transferred in the current burst is stored in the 'remainder'
    field.

    With this method, the read_u32 field is no longer necessary, and is
    removed.

    This was tested on imx6 solo and imx6 quad.

    Signed-off-by: Maxime Chevallier
    Signed-off-by: Mark Brown

    Maxime Chevallier
     
  • The spi_imx_can_dma function computes the watermark level so that
    the transfer will fit in exactly N bursts (without a remainder).

    The smallest watermark level possible being one FIFO entry per burst, we
    can't never have a case where the transfer size isn't divsiible by 1.

    Remove the extra check for the wml being different than 0.

    Signed-off-by: Maxime Chevallier
    Signed-off-by: Mark Brown

    Maxime Chevallier
     
  • The SPI core enforces that we always use the next power-of-two number of
    bytes to store words. As a result, a 24 bits word will be stored in 4
    bytes.

    This commit fixes the spi_imx_bytes_per_word function to return the
    correct number of bytes.

    This also allows to get rid of unnecessary checks in the can_dma
    function, since the SPI core validates that we always have a transfer
    length that is a multiple of the number of bytes per word.

    Signed-off-by: Maxime Chevallier
    Signed-off-by: Mark Brown

    Maxime Chevallier
     
  • The dynamic bursts mode allows to group together multiple words into a
    single burst. To do so, it's necessary that words can be packed into the
    32-bits FIFO entries, so we can't allow using this mode with bit_per_words
    different to 8, 16 or 32.

    This prevents shitfing out extra clock ticks for transfers with
    bit_per_word values not aligned on 8 bits.

    With that , we are sure that only the correct number of bits is
    shifted out at each transfer, so we don't need to mask out the remaining
    parts of the words.

    Signed-off-by: Maxime Chevallier
    Signed-off-by: Mark Brown

    Maxime Chevallier
     
  • Some fields in struct spi_imx_data are assigned a different value twice
    in a row, in spi_imx_setupxfer.

    Signed-off-by: Maxime Chevallier
    Signed-off-by: Mark Brown

    Maxime Chevallier
     

13 Jun, 2018

1 commit

  • The devm_kzalloc() function has a 2-factor argument form, devm_kcalloc().
    This patch replaces cases of:

    devm_kzalloc(handle, a * b, gfp)

    with:
    devm_kcalloc(handle, a * b, gfp)

    as well as handling cases of:

    devm_kzalloc(handle, a * b * c, gfp)

    with:

    devm_kzalloc(handle, array3_size(a, b, c), gfp)

    as it's slightly less ugly than:

    devm_kcalloc(handle, array_size(a, b), c, gfp)

    This does, however, attempt to ignore constant size factors like:

    devm_kzalloc(handle, 4 * 1024, gfp)

    though any constants defined via macros get caught up in the conversion.

    Any factors with a sizeof() of "unsigned char", "char", and "u8" were
    dropped, since they're redundant.

    Some manual whitespace fixes were needed in this patch, as Coccinelle
    really liked to write "=devm_kcalloc..." instead of "= devm_kcalloc...".

    The Coccinelle script used for this was:

    // Fix redundant parens around sizeof().
    @@
    expression HANDLE;
    type TYPE;
    expression THING, E;
    @@

    (
    devm_kzalloc(HANDLE,
    - (sizeof(TYPE)) * E
    + sizeof(TYPE) * E
    , ...)
    |
    devm_kzalloc(HANDLE,
    - (sizeof(THING)) * E
    + sizeof(THING) * E
    , ...)
    )

    // Drop single-byte sizes and redundant parens.
    @@
    expression HANDLE;
    expression COUNT;
    typedef u8;
    typedef __u8;
    @@

    (
    devm_kzalloc(HANDLE,
    - sizeof(u8) * (COUNT)
    + COUNT
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(__u8) * (COUNT)
    + COUNT
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(char) * (COUNT)
    + COUNT
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(unsigned char) * (COUNT)
    + COUNT
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(u8) * COUNT
    + COUNT
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(__u8) * COUNT
    + COUNT
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(char) * COUNT
    + COUNT
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(unsigned char) * COUNT
    + COUNT
    , ...)
    )

    // 2-factor product with sizeof(type/expression) and identifier or constant.
    @@
    expression HANDLE;
    type TYPE;
    expression THING;
    identifier COUNT_ID;
    constant COUNT_CONST;
    @@

    (
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(TYPE) * (COUNT_ID)
    + COUNT_ID, sizeof(TYPE)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(TYPE) * COUNT_ID
    + COUNT_ID, sizeof(TYPE)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(TYPE) * (COUNT_CONST)
    + COUNT_CONST, sizeof(TYPE)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(TYPE) * COUNT_CONST
    + COUNT_CONST, sizeof(TYPE)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(THING) * (COUNT_ID)
    + COUNT_ID, sizeof(THING)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(THING) * COUNT_ID
    + COUNT_ID, sizeof(THING)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(THING) * (COUNT_CONST)
    + COUNT_CONST, sizeof(THING)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(THING) * COUNT_CONST
    + COUNT_CONST, sizeof(THING)
    , ...)
    )

    // 2-factor product, only identifiers.
    @@
    expression HANDLE;
    identifier SIZE, COUNT;
    @@

    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - SIZE * COUNT
    + COUNT, SIZE
    , ...)

    // 3-factor product with 1 sizeof(type) or sizeof(expression), with
    // redundant parens removed.
    @@
    expression HANDLE;
    expression THING;
    identifier STRIDE, COUNT;
    type TYPE;
    @@

    (
    devm_kzalloc(HANDLE,
    - sizeof(TYPE) * (COUNT) * (STRIDE)
    + array3_size(COUNT, STRIDE, sizeof(TYPE))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(TYPE) * (COUNT) * STRIDE
    + array3_size(COUNT, STRIDE, sizeof(TYPE))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(TYPE) * COUNT * (STRIDE)
    + array3_size(COUNT, STRIDE, sizeof(TYPE))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(TYPE) * COUNT * STRIDE
    + array3_size(COUNT, STRIDE, sizeof(TYPE))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(THING) * (COUNT) * (STRIDE)
    + array3_size(COUNT, STRIDE, sizeof(THING))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(THING) * (COUNT) * STRIDE
    + array3_size(COUNT, STRIDE, sizeof(THING))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(THING) * COUNT * (STRIDE)
    + array3_size(COUNT, STRIDE, sizeof(THING))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(THING) * COUNT * STRIDE
    + array3_size(COUNT, STRIDE, sizeof(THING))
    , ...)
    )

    // 3-factor product with 2 sizeof(variable), with redundant parens removed.
    @@
    expression HANDLE;
    expression THING1, THING2;
    identifier COUNT;
    type TYPE1, TYPE2;
    @@

    (
    devm_kzalloc(HANDLE,
    - sizeof(TYPE1) * sizeof(TYPE2) * COUNT
    + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(TYPE1) * sizeof(THING2) * (COUNT)
    + array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(THING1) * sizeof(THING2) * COUNT
    + array3_size(COUNT, sizeof(THING1), sizeof(THING2))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(THING1) * sizeof(THING2) * (COUNT)
    + array3_size(COUNT, sizeof(THING1), sizeof(THING2))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(TYPE1) * sizeof(THING2) * COUNT
    + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
    , ...)
    |
    devm_kzalloc(HANDLE,
    - sizeof(TYPE1) * sizeof(THING2) * (COUNT)
    + array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
    , ...)
    )

    // 3-factor product, only identifiers, with redundant parens removed.
    @@
    expression HANDLE;
    identifier STRIDE, SIZE, COUNT;
    @@

    (
    devm_kzalloc(HANDLE,
    - (COUNT) * STRIDE * SIZE
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    devm_kzalloc(HANDLE,
    - COUNT * (STRIDE) * SIZE
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    devm_kzalloc(HANDLE,
    - COUNT * STRIDE * (SIZE)
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    devm_kzalloc(HANDLE,
    - (COUNT) * (STRIDE) * SIZE
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    devm_kzalloc(HANDLE,
    - COUNT * (STRIDE) * (SIZE)
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    devm_kzalloc(HANDLE,
    - (COUNT) * STRIDE * (SIZE)
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    devm_kzalloc(HANDLE,
    - (COUNT) * (STRIDE) * (SIZE)
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    |
    devm_kzalloc(HANDLE,
    - COUNT * STRIDE * SIZE
    + array3_size(COUNT, STRIDE, SIZE)
    , ...)
    )

    // Any remaining multi-factor products, first at least 3-factor products,
    // when they're not all constants...
    @@
    expression HANDLE;
    expression E1, E2, E3;
    constant C1, C2, C3;
    @@

    (
    devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
    |
    devm_kzalloc(HANDLE,
    - (E1) * E2 * E3
    + array3_size(E1, E2, E3)
    , ...)
    |
    devm_kzalloc(HANDLE,
    - (E1) * (E2) * E3
    + array3_size(E1, E2, E3)
    , ...)
    |
    devm_kzalloc(HANDLE,
    - (E1) * (E2) * (E3)
    + array3_size(E1, E2, E3)
    , ...)
    |
    devm_kzalloc(HANDLE,
    - E1 * E2 * E3
    + array3_size(E1, E2, E3)
    , ...)
    )

    // And then all remaining 2 factors products when they're not all constants,
    // keeping sizeof() as the second factor argument.
    @@
    expression HANDLE;
    expression THING, E1, E2;
    type TYPE;
    constant C1, C2, C3;
    @@

    (
    devm_kzalloc(HANDLE, sizeof(THING) * C2, ...)
    |
    devm_kzalloc(HANDLE, sizeof(TYPE) * C2, ...)
    |
    devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
    |
    devm_kzalloc(HANDLE, C1 * C2, ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(TYPE) * (E2)
    + E2, sizeof(TYPE)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(TYPE) * E2
    + E2, sizeof(TYPE)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(THING) * (E2)
    + E2, sizeof(THING)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - sizeof(THING) * E2
    + E2, sizeof(THING)
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - (E1) * E2
    + E1, E2
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - (E1) * (E2)
    + E1, E2
    , ...)
    |
    - devm_kzalloc
    + devm_kcalloc
    (HANDLE,
    - E1 * E2
    + E1, E2
    , ...)
    )

    Signed-off-by: Kees Cook

    Kees Cook
     

03 May, 2018

1 commit


13 Apr, 2018

1 commit


27 Jan, 2018

1 commit


08 Jan, 2018

1 commit

  • Since clocks are disabled except during message transfer clocks
    are also disabled when spi_imx_remove gets called. Accessing
    registers leads to a freeeze at least on a i.MX 6ULL. Enable
    clocks before disabling accessing the MXC_CSPICTRL register.

    Fixes: 9e556dcc55774 ("spi: spi-imx: only enable the clocks when we start to transfer a message")
    Signed-off-by: Stefan Agner
    Signed-off-by: Mark Brown
    Cc: stable@vger.kernel.org

    Stefan Agner
     

11 Nov, 2017

3 commits

  • If the array is not present, assume all chip selects are native. This
    is the standard behavior for SPI masters configured via the device
    tree and the behavior of this driver as well when it is configured via
    device tree.

    This reduces platform data vs DT differences and allows most of the
    platform data based boards to remove their chip select arrays.

    CC: Shawn Guo
    CC: Sascha Hauer
    CC: Fabio Estevam
    CC: Mark Brown
    Signed-off-by: Trent Piepho
    Signed-off-by: Mark Brown

    Trent Piepho
     
  • If the code that requests any chip select GPIOs fails, the cleanup of
    spi_bitbang_start() by calling spi_bitbang_stop() is not done. Add this
    to the failure path.

    Note that spi_bitbang_start() has to be called before requesting GPIOs
    because the GPIO data in the spi master is populated when the master is
    registed, and that doesn't happen until spi_bitbang_start() is called.

    CC: Shawn Guo
    CC: Sascha Hauer
    CC: Fabio Estevam
    CC: Mark Brown
    CC: Oleksij Rempel
    Signed-off-by: Trent Piepho
    Signed-off-by: Mark Brown

    Trent Piepho
     
  • The driver will fail to load if no gpio chip selects are specified,
    this patch changes this so that it no longer fails.

    It's possible to use all native chip selects, in which case there is
    no reason to have a gpio chip select array. This is what happens if
    the *optional* device tree property "cs-gpios" is omitted.

    The spi core already checks for the absence of gpio chip selects in
    the master and assigns any slaves the gpio_cs value of -ENOENT.

    Also have the driver respect the standard SPI device tree property "num-cs"
    to allow setting the number of chip selects without using cs-gpios.

    CC: Mark Brown
    CC: Shawn Guo
    CC: Sascha Hauer
    CC: Fabio Estevam
    CC: Oleksij Rempel
    Signed-off-by: Trent Piepho
    Signed-off-by: Mark Brown

    Trent Piepho
     

07 Nov, 2017

1 commit

  • In commit 974488e4ce1e ("spi: imx: Fix failure path leak on GPIO request
    error"), spi_bitbang_start() was moved later in the probe sequence. But
    this doesn't work, as spi_bitbang_start() has to be called before
    requesting GPIOs because the GPIO data in the spi master is populated when
    the master is registed, and that doesn't happen until spi_bitbang_start()
    is called. The default only works if one uses one CS.

    So add a failure path call to spi_bitbang_stop() to fix the leak.

    CC: Shawn Guo
    CC: Sascha Hauer
    CC: Fabio Estevam
    CC: Mark Brown
    CC: Oleksij Rempel
    Signed-off-by: Trent Piepho
    Reviewed-by: Oleksij Rempel
    Signed-off-by: Mark Brown

    Trent Piepho
     

31 Oct, 2017

1 commit

  • If the code that requests any chip select GPIOs fails, the cleanup of
    spi_bitbang_start() by calling spi_bitbang_stop() is not done.

    Fix this by moving spi_bitbang_start() to after the code that requets
    GPIOs. The GPIOs are dev managed and don't need explicit cleanup.
    Since spi_bitbang_start() is now the last operation, it doesn't need
    to be cleaned up in the failure path.

    CC: Shawn Guo
    CC: Sascha Hauer
    CC: Fabio Estevam
    CC: Mark Brown
    Reviewed-by: Oleksij Rempel
    Signed-off-by: Trent Piepho
    Signed-off-by: Mark Brown

    Trent Piepho
     

19 Sep, 2017

1 commit

  • Previously i.MX SPI controller only works in Master mode.
    This patch adds support to i.MX51, i.MX53 and i.MX6 ECSPI
    controller to work also in Slave mode.

    Currently SPI Slave mode support patch has the following limitations:
    1. The stale data in RXFIFO will be dropped when the Slave does any new
    transfer.
    2. One transfer can be finished only after all transfer->len data been
    transferred to master device
    3. Slave device only accepts transfer->len data. Any data longer than this
    from master device will be dropped. Any data shorter than this from
    master will cause SPI to stuck due to mentioned HW limitation 2.
    4. Only PIO transfer is supported in Slave mode.
    5. Dynamic burst size adjust isn't supported in Slave mode.

    Following HW limitation applies:
    1. ECSPI has a HW issue when works in Slave mode, after 64
    words written to TXFIFO, even TXFIFO becomes empty,
    ECSPI_TXDATA keeps shift out the last word data,
    so we have to disable ECSPI when in slave mode after the
    transfer completes
    2. Due to Freescale errata ERR003775 "eCSPI: Burst completion by Chip
    Select (SS) signal in Slave mode is not functional" burst size must
    be set exactly to the size of the transfer. This limit SPI transaction
    with maximum 2^12 bits. This errata affects i.MX53 and i.MX6 ECSPI
    controllers.

    Signed-off-by: Jiada Wang
    Signed-off-by: Mark Brown

    jiada wang
     

30 Aug, 2017

1 commit

  • The commonly used mechanism of specifying the hardware or native
    chip-select on an SPI device in devicetree (that is "cs-gpios = ")
    does not result in the native chip-select being configured for use.
    So external SPI devices that require use of the native chip-select
    will not work.

    You can successfully specify native chip-selects if using a platform
    setup by specifying the cs-gpio as negative offset by 32. And that
    works correctly. You cannot use the same method in devicetree.

    The logic in the spi-imx.c driver during probe uses core spi function
    of_spi_register_master() in spi.c to parse the "cs-gpios" devicetree tag.
    For valid GPIO values that will be recorded for use, all other entries in
    the cs_gpios list will be set to -ENOENT. So entries like "" will be
    set to -ENOENT in the cs_gpios list.

    When the SPI device registers are setup the code will use the GPIO
    listed in the cs_gpios list for the desired chip-select. If the cs_gpio
    is less then 0 then it is intended to be for a native chip-select, and
    its cs_gpio value is added to 32 to get the chipselect number to use.
    Problem is that with devicetree this can only ever be -ENOENT (which
    is -2), and that alone results in an invalid chip-select number. But also
    doesn't allow selection of the native chip-select at all.

    To fix, if the cs_gpio specified for this spi device is not a
    valid GPIO then use the "chip_select" (that is the native chip-select
    number) for hardware setup.

    Signed-off-by: Greg Ungerer
    Reviewed-by: Vladimir Zapolskiy
    Tested-by: Vladimir Zapolskiy
    Signed-off-by: Mark Brown

    Greg Ungerer
     

23 Aug, 2017

1 commit

  • The newly added dynamic burst code produces a harmless warning
    on big-endian configurations:

    drivers/spi/spi-imx.c: In function 'spi_imx_buf_rx_swap_u32':
    drivers/spi/spi-imx.c:284:15: error: unused variable 'bytes_per_word' [-Werror=unused-variable]
    unsigned int bytes_per_word;
    ^~~~~~~~~~~~~~
    drivers/spi/spi-imx.c: In function 'spi_imx_buf_tx_swap_u32':
    drivers/spi/spi-imx.c:319:15: error: unused variable 'bytes_per_word' [-Werror=unused-variable]
    unsigned int bytes_per_word;

    This adds another #ifdef around the variable declaration matching
    the one on the use.

    Fixes: 1673c81d9435 ("spi: imx: dynamic burst length adjust for PIO mode")
    Signed-off-by: Arnd Bergmann
    Signed-off-by: Mark Brown

    Arnd Bergmann
     

17 Aug, 2017

1 commit

  • previously burst length (BURST_LENGTH) is always set to equal
    to bits_per_word, causes a 10us gap between each word in
    transfer, which significantly affects performance.

    This patch uses 32 bits transfer to simulate lower bits transfer,
    and adjusts burst length runtimely to use biggeest burst length
    as possible to reduce the gaps in transfer for PIO mode.

    Signed-off-by: Jiada Wang
    Signed-off-by: Mark Brown

    jiada wang
     

26 Jul, 2017

1 commit

  • To run spi-loopback-tests on HW without modifications, we need to
    disable Chip Select. This should avoid surprising side effects for SPI devices
    by testing patterns.

    Signed-off-by: Oleksij Rempel
    Signed-off-by: Mark Brown

    Oleksij Rempel
     

17 Jul, 2017

2 commits


21 Jun, 2017

1 commit


07 Jun, 2017

6 commits