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