question: Why the nand_wait() wait for 20ms for nand program.

Huang Shijie b32955 at freescale.com
Sun Jan 20 22:34:53 EST 2013


于 2013年01月18日 20:26, Matthieu CASTET 写道:
> Huang Shijie a écrit :
>> Hi all:
>> Why the nand_wait() wait for 20ms for nand program. could we
>> expand this time to 40ms? I have a nand chip : Micron MT29F64G08CBABAWP.
>> The chip's BUSY/READY pin may needs more then 20ms to become ready,
>> though its
>> datasheet tells me the tPROG's max value is 2.5ms.
>>
> Don't you have an hardware problem (missing pullup/down on ready busy pin) ?
>
> If the datasheet say the max value is 2.5 ms , how it can be more than 20 ms.

I finally found the root cause.

I added the do_gettimeofday() in the nand_wait() to measure the 
READY/BUSY time. The code is like this:
---------------------------------------------------- code start 
-----------------------------------------------------------------------

+static struct timeval start, finish;
+static int my_nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
+{
+
+ unsigned long timeo = jiffies;
+ int status, state = chip->state;
+ int check = 0;
+
+ if (state == FL_ERASING)
+ timeo += (HZ * 400) / 1000;
+ else
+ timeo += (HZ * 20) / 1000;
+
+ led_trigger_event(nand_led_trigger, LED_FULL);
+
+ /*
+ * Apply this short delay always to ensure that we do wait tWB in any
+ * case on any machine.
+ */
+ ndelay(100);
+
+ if ((state == FL_ERASING) && (chip->options & NAND_IS_AND))
+ chip->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1);
+ else
+ chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
+
+ do_gettimeofday(&start);
+
+ if (in_interrupt() || oops_in_progress)
+ panic_nand_wait(mtd, chip, timeo);
+ else {
+ while (time_before(jiffies, timeo)) {
+ if (chip->dev_ready) {
+ if (chip->dev_ready(mtd)) {
+ do_gettimeofday(&finish);
+ check = 1;
+ break;
+ }
+ } else {
+ if (chip->read_byte(mtd) & NAND_STATUS_READY)
+ break;
+ }
+ cond_resched();
+ }
+ }
+ led_trigger_event(nand_led_trigger, LED_OFF);
+
+ status = (int)chip->read_byte(mtd);
+ if (check == 0) {
+ long ms, us;
+
+ /* get it here. */
+ do_gettimeofday(&finish);
+
+ us = (finish.tv_sec * USEC_PER_SEC + finish.tv_usec)
+ - (start.tv_sec * USEC_PER_SEC + start.tv_usec);
+ ms = us / USEC_PER_MSEC;
+
+ printk("[ %s : ], status : %x, <%lu, %lu>, < %lu, %lu>, <%lu, %lu>, Js 
<%lu, %lu>\n",
+ __func__, status, finish.tv_sec, start.tv_sec,
+ finish.tv_usec, start.tv_usec, ms, us);
+
+ }
+ start = finish = (struct timeval) {0, 0};
+ return status;
+}

/**
* __nand_unlock - [REPLACEABLE] unlocks specified locked blocks
* @mtd: mtd info
@@ -2180,7 +2247,8 @@ static int nand_write_page(struct mtd_info *mtd, 
struct nand_chip *chip,
if (!cached || !(chip->options & NAND_CACHEPRG)) {

chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
- status = chip->waitfunc(mtd, chip);
+ status = my_nand_wait(mtd, chip);
+
/*
* See if operation failed and additional status checks are
* available.
-- 
------------------------------------------------------------------------code 
end 
here.----------------------------------------------------------------------------


The code tells me that it will wait for 20ms, but in actually, the 
kernel may breaks the while loop in JUST 1ms.
My CONFIG_HZ is 100.

Any idea about this?

thanks.
Huang Shijie









>
> Matthieu
>





More information about the linux-mtd mailing list