[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