Am 09.08.25 um 03:04 schrieb Mikhail Kshevetskiy:
> also call schedule() to allow periodic actions

I don't think "simulate" is a good verb here. What about the following:

###
mtd: spinand: Extend spinand_wait() to match Linux kernel implementation

This aligns spinand_wait() with the kernel. Instead of calling into
spi_mem_poll_status() which is not implemented in U-Boot, we open-code
the polling logic and make sure that schedule() is called periodically.
###

> Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevets...@iopsys.eu>
> ---
>  drivers/mtd/nand/spi/core.c | 35 ++++++++++++++++++++++++++++-------
>  include/linux/mtd/spinand.h | 22 ++++++++++++++++++++++
>  2 files changed, 50 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
> index 34e5ac33c63..f99568050fb 100644
> --- a/drivers/mtd/nand/spi/core.c
> +++ b/drivers/mtd/nand/spi/core.c
> @@ -32,6 +32,7 @@
>  #include <linux/bug.h>
>  #include <linux/mtd/spinand.h>
>  #include <linux/printk.h>
> +#include <linux/delay.h>
>  #endif
>  
>  struct spinand_plat {
> @@ -362,21 +363,29 @@ static int spinand_erase_op(struct spinand_device 
> *spinand,
>       return spi_mem_exec_op(spinand->slave, &op);
>  }
>  
> -static int spinand_wait(struct spinand_device *spinand, u8 *s)
> +static int spinand_wait(struct spinand_device *spinand,

You are adding the kdoc header for this function in patch 17 of this
series. It would be nice to include it here in this patch instead.

> +                     unsigned long initial_delay_us,
> +                     unsigned long poll_delay_us,
> +                     u8 *s)
>  {
>       unsigned long start, stop;
>       u8 status;
>       int ret;
>  
> +     udelay(initial_delay_us);
>       start = get_timer(0);
> -     stop = 400;
> +     stop = SPINAND_WAITRDY_TIMEOUT_MS;
>       do {
> +             schedule();
> +
>               ret = spinand_read_status(spinand, &status);
>               if (ret)
>                       return ret;
>  
>               if (!(status & STATUS_BUSY))
>                       goto out;
> +
> +             udelay(poll_delay_us);
>       } while (get_timer(start) < stop);
>  
>       /*
> @@ -418,7 +427,10 @@ static int spinand_reset_op(struct spinand_device 
> *spinand)
>       if (ret)
>               return ret;
>  
> -     return spinand_wait(spinand, NULL);
> +     return spinand_wait(spinand,
> +                         SPINAND_RESET_INITIAL_DELAY_US,
> +                         SPINAND_RESET_POLL_DELAY_US,
> +                         NULL);
>  }
>  
>  static int spinand_lock_block(struct spinand_device *spinand, u8 lock)
> @@ -466,7 +478,10 @@ static int spinand_read_page(struct spinand_device 
> *spinand,
>       if (ret)
>               return ret;
>  
> -     ret = spinand_wait(spinand, &status);
> +     ret = spinand_wait(spinand,
> +                        SPINAND_READ_INITIAL_DELAY_US,
> +                        SPINAND_READ_POLL_DELAY_US,
> +                        &status);
>       if (ret < 0)
>               return ret;
>  
> @@ -498,9 +513,12 @@ static int spinand_write_page(struct spinand_device 
> *spinand,
>       if (ret)
>               return ret;
>  
> -     ret = spinand_wait(spinand, &status);
> +     ret = spinand_wait(spinand,
> +                        SPINAND_WRITE_INITIAL_DELAY_US,
> +                        SPINAND_WRITE_POLL_DELAY_US,
> +                        &status);
>       if (!ret && (status & STATUS_PROG_FAILED))
> -             ret = -EIO;
> +             return -EIO;
>  
>       return ret;
>  }
> @@ -702,7 +720,10 @@ static int spinand_erase(struct nand_device *nand, const 
> struct nand_pos *pos)
>       if (ret)
>               return ret;
>  
> -     ret = spinand_wait(spinand, &status);
> +     ret = spinand_wait(spinand,
> +                        SPINAND_ERASE_INITIAL_DELAY_US,
> +                        SPINAND_ERASE_POLL_DELAY_US,
> +                        &status);
>       if (!ret && (status & STATUS_ERASE_FAILED))
>               ret = -EIO;
>  
> diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
> index 163269313f6..ba6c2ba149d 100644
> --- a/include/linux/mtd/spinand.h
> +++ b/include/linux/mtd/spinand.h
> @@ -176,6 +176,28 @@ struct spinand_op;
>  struct spinand_device;
>  
>  #define SPINAND_MAX_ID_LEN   4
> +/*
> + * For erase, write and read operation, we got the following timings :
> + * tBERS (erase) 1ms to 4ms
> + * tPROG 300us to 400us
> + * tREAD 25us to 100us
> + * In order to minimize latency, the min value is divided by 4 for the
> + * initial delay, and dividing by 20 for the poll delay.
> + * For reset, 5us/10us/500us if the device is respectively
> + * reading/programming/erasing when the RESET occurs. Since we always
> + * issue a RESET when the device is IDLE, 5us is selected for both initial
> + * and poll delay.
> + */
> +#define SPINAND_READ_INITIAL_DELAY_US        6
> +#define SPINAND_READ_POLL_DELAY_US   5
> +#define SPINAND_RESET_INITIAL_DELAY_US       5
> +#define SPINAND_RESET_POLL_DELAY_US  5
> +#define SPINAND_WRITE_INITIAL_DELAY_US       75
> +#define SPINAND_WRITE_POLL_DELAY_US  15
> +#define SPINAND_ERASE_INITIAL_DELAY_US       250
> +#define SPINAND_ERASE_POLL_DELAY_US  50
> +
> +#define SPINAND_WAITRDY_TIMEOUT_MS   400
>  
>  /**
>   * struct spinand_id - SPI NAND id structure

Reply via email to