On 05/04/19 2:24 PM, Rajat Srivastava wrote:
> Incorporate write enable and status check in the write data
> function itself.
> 
> Formerly, Write data function used to break the data to be
> written into smaller chunks and used to send the smaller
> chunks without write enable or status check for every iteration.
> 
> Signed-off-by: Rajat Srivastava <rajat.srivast...@nxp.com>
> ---
> While writing any data to a SPI flash every write transaction
> shall be preceded by a WRITE_ENABLE command and shall be
> followed by a READ_STATUS process (to check if the flash is
> not busy).
> This sequence can be roughly represented as:
> 1. write_enable  //issue write enable command
> 2. execute_write_operation  //write data to flash or register
> 3. spi_nor_wait_till_ready  //read status of flash
>  
> The current framework has two types of write operation:
> 1. write to register (nor->write_reg)
> 2. write data to flash memory (nor->write)
>  
> There seems to be an issue in writing data to flash memory for which
> the framework uses spi_nor_write_data() function.
> Before every call to spi_nor_write_data() function the framework
> sends a WRITE_ENABLE command and later checks if the flash is busy.
> However, the spi_nor_write_data() function which executes the data
> write to flash, breaks the data into smaller chunks. For all of
> these small transactions there is only a single WRITE_ENABLE
> command issued and a single check made for status, which breaks
> the write operation. Only the first chunk of the whole data is
> successfully written on to the flash.
> 
> This patch fixes the bug making the spi_nor_write_data() function
> issue WRITE_ENABLE command and status checks with every write
> transactions.
> 
> Without this patch write in fsl_qspi.c driver is broken.
> 

I see this is mainly because fsl-qspi uses slave->max_write_size to
restrict max write size which leads to fragmentation of traffic as part
of spi_mem_adjust_op_size().
So, could you please remove while() loop in spi_nor_write_data(), return
actual number of data bytes that is written and make
spi_nor_write() loop around until all the data has been written?

Regards
Vignesh


>  drivers/mtd/spi/spi-nor-core.c | 30 +++++++++---------------------
>  1 file changed, 9 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
> index c4e2f6a08f..757163369b 100644
> --- a/drivers/mtd/spi/spi-nor-core.c
> +++ b/drivers/mtd/spi/spi-nor-core.c
> @@ -23,6 +23,9 @@
>  
>  #include "sf_internal.h"
>  
> +static int spi_nor_wait_till_ready(struct spi_nor *nor);
> +static int write_enable(struct spi_nor *nor);
> +
>  /* Define max times to check status register before we give up. */
>  
>  /*
> @@ -128,6 +131,8 @@ static ssize_t spi_nor_write_data(struct spi_nor *nor, 
> loff_t to, size_t len,
>               op.addr.nbytes = 0;
>  
>       while (remaining) {
> +             write_enable(nor);
> +
>               op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX;
>               ret = spi_mem_adjust_op_size(nor->spi, &op);
>               if (ret)
> @@ -137,6 +142,10 @@ static ssize_t spi_nor_write_data(struct spi_nor *nor, 
> loff_t to, size_t len,
>               if (ret)
>                       return ret;
>  
> +             ret = spi_nor_wait_till_ready(nor);
> +             if (ret)
> +                     return ret;
> +
>               op.addr.val += op.data.nbytes;
>               remaining -= op.data.nbytes;
>               op.data.buf.out += op.data.nbytes;
> @@ -961,14 +970,10 @@ static int sst_write_byteprogram(struct spi_nor *nor, 
> loff_t to, size_t len,
>       for (actual = 0; actual < len; actual++) {
>               nor->program_opcode = SPINOR_OP_BP;
>  
> -             write_enable(nor);
>               /* write one byte. */
>               ret = nor->write(nor, to, 1, buf + actual);
>               if (ret < 0)
>                       goto sst_write_err;
> -             ret = spi_nor_wait_till_ready(nor);
> -             if (ret)
> -                     goto sst_write_err;
>               to++;
>       }
>  
> @@ -989,8 +994,6 @@ static int sst_write(struct mtd_info *mtd, loff_t to, 
> size_t len,
>       if (spi->mode & SPI_TX_BYTE)
>               return sst_write_byteprogram(nor, to, len, retlen, buf);
>  
> -     write_enable(nor);
> -
>       nor->sst_write_second = false;
>  
>       actual = to % 2;
> @@ -1002,9 +1005,6 @@ static int sst_write(struct mtd_info *mtd, loff_t to, 
> size_t len,
>               ret = nor->write(nor, to, 1, buf);
>               if (ret < 0)
>                       goto sst_write_err;
> -             ret = spi_nor_wait_till_ready(nor);
> -             if (ret)
> -                     goto sst_write_err;
>       }
>       to += actual;
>  
> @@ -1016,9 +1016,6 @@ static int sst_write(struct mtd_info *mtd, loff_t to, 
> size_t len,
>               ret = nor->write(nor, to, 2, buf + actual);
>               if (ret < 0)
>                       goto sst_write_err;
> -             ret = spi_nor_wait_till_ready(nor);
> -             if (ret)
> -                     goto sst_write_err;
>               to += 2;
>               nor->sst_write_second = true;
>       }
> @@ -1031,15 +1028,10 @@ static int sst_write(struct mtd_info *mtd, loff_t to, 
> size_t len,
>  
>       /* Write out trailing byte if it exists. */
>       if (actual != len) {
> -             write_enable(nor);
> -
>               nor->program_opcode = SPINOR_OP_BP;
>               ret = nor->write(nor, to, 1, buf + actual);
>               if (ret < 0)
>                       goto sst_write_err;
> -             ret = spi_nor_wait_till_ready(nor);
> -             if (ret)
> -                     goto sst_write_err;
>               write_disable(nor);
>               actual += 1;
>       }
> @@ -1090,15 +1082,11 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t 
> to, size_t len,
>               if (ret < 0)
>                       return ret;
>  #endif
> -             write_enable(nor);
>               ret = nor->write(nor, addr, page_remain, buf + i);
>               if (ret < 0)
>                       goto write_err;
>               written = ret;
>  
> -             ret = spi_nor_wait_till_ready(nor);
> -             if (ret)
> -                     goto write_err;
>               *retlen += written;
>               i += written;
>               if (written != page_remain) {
> 

-- 
Regards
Vignesh
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to