[U-Boot] [PATCH 1/5] DW SPI: fix tx data loss on FIFO flush

Jagan Teki jagannadh.teki at gmail.com
Wed Mar 21 19:14:46 UTC 2018


On Mon, Mar 5, 2018 at 6:47 PM, Eugeniy Paltsev
<Eugeniy.Paltsev at synopsys.com> wrote:
> In current implementation if some data still exists in Tx FIFO it
> can be silently flushed, i.e. dropped on disabling of the controller,
> which happens when writing 0 to DW_SPI_SSIENR (it happens in the
> beginning of new transfer)
>
> So add wait for current transmit operation to complete to be sure
> that current transmit operation is finished before new one.
>
> Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev at synopsys.com>
> ---
>  drivers/spi/designware_spi.c | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>
> diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
> index c501aeea16..71d8839d55 100644
> --- a/drivers/spi/designware_spi.c
> +++ b/drivers/spi/designware_spi.c
> @@ -338,6 +338,7 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
>  {
>         struct udevice *bus = dev->parent;
>         struct dw_spi_priv *priv = dev_get_priv(bus);
> +       unsigned long start;
>         const u8 *tx = dout;
>         u8 *rx = din;
>         int ret = 0;
> @@ -394,6 +395,22 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
>         /* Start transfer in a polling loop */
>         ret = poll_transfer(priv);
>
> +       /*
> +        * Wait for current transmit operation to complete.
> +        * Otherwise if some data still exists in Tx FIFO it can be
> +        * silently flushed, i.e. dropped on disabling of the controller,
> +        * which happens when writing 0 to DW_SPI_SSIENR which happens
> +        * in the beginning of new transfer.
> +        */
> +       start = get_timer(0);
> +       while (!(dw_readl(priv, DW_SPI_SR) & SR_TF_EMPT) ||
> +               (dw_readl(priv, DW_SPI_SR) & SR_BUSY)) {
> +               if (get_timer(start) > RX_TIMEOUT) {
> +                       ret = -ETIMEDOUT;
> +                       break;
> +               }
> +       }

Use wait_for_bit


More information about the U-Boot mailing list