7cbbcf588c4fbf3c0a05ae440bfda6d935a3b8f1
[oweals/openwrt.git] /
1 commit 97d90da8a886949f09bb4754843fb0b504956ad2
2 Author: Boris Brezillon <boris.brezillon@free-electrons.com>
3 Date:   Thu Nov 30 18:01:29 2017 +0100
4
5     mtd: nand: provide several helpers to do common NAND operations
6     
7     This is part of the process of removing direct calls to ->cmdfunc()
8     outside of the core in order to introduce a better interface to execute
9     NAND operations.
10     
11     Here we provide several helpers and make use of them to remove all
12     direct calls to ->cmdfunc(). This way, we can easily modify those
13     helpers to make use of the new ->exec_op() interface when available.
14     
15     Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
16     [miquel.raynal@free-electrons.com: rebased and fixed some conflicts]
17     Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
18     Acked-by: Masahiro Yamada <yamada.masahiro@socionext.com>
19
20 --- a/drivers/mtd/nand/nand_base.c
21 +++ b/drivers/mtd/nand/nand_base.c
22 @@ -561,14 +561,19 @@ static int nand_block_markbad_lowlevel(s
23  static int nand_check_wp(struct mtd_info *mtd)
24  {
25         struct nand_chip *chip = mtd_to_nand(mtd);
26 +       u8 status;
27 +       int ret;
28  
29         /* Broken xD cards report WP despite being writable */
30         if (chip->options & NAND_BROKEN_XD)
31                 return 0;
32  
33         /* Check the WP bit */
34 -       chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
35 -       return (chip->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1;
36 +       ret = nand_status_op(chip, &status);
37 +       if (ret)
38 +               return ret;
39 +
40 +       return status & NAND_STATUS_WP ? 0 : 1;
41  }
42  
43  /**
44 @@ -667,10 +672,17 @@ EXPORT_SYMBOL_GPL(nand_wait_ready);
45  static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo)
46  {
47         register struct nand_chip *chip = mtd_to_nand(mtd);
48 +       int ret;
49  
50         timeo = jiffies + msecs_to_jiffies(timeo);
51         do {
52 -               if ((chip->read_byte(mtd) & NAND_STATUS_READY))
53 +               u8 status;
54 +
55 +               ret = nand_read_data_op(chip, &status, sizeof(status), true);
56 +               if (ret)
57 +                       return;
58 +
59 +               if (status & NAND_STATUS_READY)
60                         break;
61                 touch_softlockup_watchdog();
62         } while (time_before(jiffies, timeo));
63 @@ -1016,7 +1028,15 @@ static void panic_nand_wait(struct mtd_i
64                         if (chip->dev_ready(mtd))
65                                 break;
66                 } else {
67 -                       if (chip->read_byte(mtd) & NAND_STATUS_READY)
68 +                       int ret;
69 +                       u8 status;
70 +
71 +                       ret = nand_read_data_op(chip, &status, sizeof(status),
72 +                                               true);
73 +                       if (ret)
74 +                               return;
75 +
76 +                       if (status & NAND_STATUS_READY)
77                                 break;
78                 }
79                 mdelay(1);
80 @@ -1033,8 +1053,9 @@ static void panic_nand_wait(struct mtd_i
81  static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
82  {
83  
84 -       int status;
85         unsigned long timeo = 400;
86 +       u8 status;
87 +       int ret;
88  
89         /*
90          * Apply this short delay always to ensure that we do wait tWB in any
91 @@ -1042,7 +1063,9 @@ static int nand_wait(struct mtd_info *mt
92          */
93         ndelay(100);
94  
95 -       chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
96 +       ret = nand_status_op(chip, NULL);
97 +       if (ret)
98 +               return ret;
99  
100         if (in_interrupt() || oops_in_progress)
101                 panic_nand_wait(mtd, chip, timeo);
102 @@ -1053,14 +1076,22 @@ static int nand_wait(struct mtd_info *mt
103                                 if (chip->dev_ready(mtd))
104                                         break;
105                         } else {
106 -                               if (chip->read_byte(mtd) & NAND_STATUS_READY)
107 +                               ret = nand_read_data_op(chip, &status,
108 +                                                       sizeof(status), true);
109 +                               if (ret)
110 +                                       return ret;
111 +
112 +                               if (status & NAND_STATUS_READY)
113                                         break;
114                         }
115                         cond_resched();
116                 } while (time_before(jiffies, timeo));
117         }
118  
119 -       status = (int)chip->read_byte(mtd);
120 +       ret = nand_read_data_op(chip, &status, sizeof(status), true);
121 +       if (ret)
122 +               return ret;
123 +
124         /* This can happen if in case of timeout or buggy dev_ready */
125         WARN_ON(!(status & NAND_STATUS_READY));
126         return status;
127 @@ -1215,6 +1246,516 @@ static void nand_release_data_interface(
128  }
129  
130  /**
131 + * nand_read_page_op - Do a READ PAGE operation
132 + * @chip: The NAND chip
133 + * @page: page to read
134 + * @offset_in_page: offset within the page
135 + * @buf: buffer used to store the data
136 + * @len: length of the buffer
137 + *
138 + * This function issues a READ PAGE operation.
139 + * This function does not select/unselect the CS line.
140 + *
141 + * Returns 0 on success, a negative error code otherwise.
142 + */
143 +int nand_read_page_op(struct nand_chip *chip, unsigned int page,
144 +                     unsigned int offset_in_page, void *buf, unsigned int len)
145 +{
146 +       struct mtd_info *mtd = nand_to_mtd(chip);
147 +
148 +       if (len && !buf)
149 +               return -EINVAL;
150 +
151 +       if (offset_in_page + len > mtd->writesize + mtd->oobsize)
152 +               return -EINVAL;
153 +
154 +       chip->cmdfunc(mtd, NAND_CMD_READ0, offset_in_page, page);
155 +       if (len)
156 +               chip->read_buf(mtd, buf, len);
157 +
158 +       return 0;
159 +}
160 +EXPORT_SYMBOL_GPL(nand_read_page_op);
161 +
162 +/**
163 + * nand_read_param_page_op - Do a READ PARAMETER PAGE operation
164 + * @chip: The NAND chip
165 + * @page: parameter page to read
166 + * @buf: buffer used to store the data
167 + * @len: length of the buffer
168 + *
169 + * This function issues a READ PARAMETER PAGE operation.
170 + * This function does not select/unselect the CS line.
171 + *
172 + * Returns 0 on success, a negative error code otherwise.
173 + */
174 +static int nand_read_param_page_op(struct nand_chip *chip, u8 page, void *buf,
175 +                                  unsigned int len)
176 +{
177 +       struct mtd_info *mtd = nand_to_mtd(chip);
178 +       unsigned int i;
179 +       u8 *p = buf;
180 +
181 +       if (len && !buf)
182 +               return -EINVAL;
183 +
184 +       chip->cmdfunc(mtd, NAND_CMD_PARAM, page, -1);
185 +       for (i = 0; i < len; i++)
186 +               p[i] = chip->read_byte(mtd);
187 +
188 +       return 0;
189 +}
190 +
191 +/**
192 + * nand_change_read_column_op - Do a CHANGE READ COLUMN operation
193 + * @chip: The NAND chip
194 + * @offset_in_page: offset within the page
195 + * @buf: buffer used to store the data
196 + * @len: length of the buffer
197 + * @force_8bit: force 8-bit bus access
198 + *
199 + * This function issues a CHANGE READ COLUMN operation.
200 + * This function does not select/unselect the CS line.
201 + *
202 + * Returns 0 on success, a negative error code otherwise.
203 + */
204 +int nand_change_read_column_op(struct nand_chip *chip,
205 +                              unsigned int offset_in_page, void *buf,
206 +                              unsigned int len, bool force_8bit)
207 +{
208 +       struct mtd_info *mtd = nand_to_mtd(chip);
209 +
210 +       if (len && !buf)
211 +               return -EINVAL;
212 +
213 +       if (offset_in_page + len > mtd->writesize + mtd->oobsize)
214 +               return -EINVAL;
215 +
216 +       chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset_in_page, -1);
217 +       if (len)
218 +               chip->read_buf(mtd, buf, len);
219 +
220 +       return 0;
221 +}
222 +EXPORT_SYMBOL_GPL(nand_change_read_column_op);
223 +
224 +/**
225 + * nand_read_oob_op - Do a READ OOB operation
226 + * @chip: The NAND chip
227 + * @page: page to read
228 + * @offset_in_oob: offset within the OOB area
229 + * @buf: buffer used to store the data
230 + * @len: length of the buffer
231 + *
232 + * This function issues a READ OOB operation.
233 + * This function does not select/unselect the CS line.
234 + *
235 + * Returns 0 on success, a negative error code otherwise.
236 + */
237 +int nand_read_oob_op(struct nand_chip *chip, unsigned int page,
238 +                    unsigned int offset_in_oob, void *buf, unsigned int len)
239 +{
240 +       struct mtd_info *mtd = nand_to_mtd(chip);
241 +
242 +       if (len && !buf)
243 +               return -EINVAL;
244 +
245 +       if (offset_in_oob + len > mtd->oobsize)
246 +               return -EINVAL;
247 +
248 +       chip->cmdfunc(mtd, NAND_CMD_READOOB, offset_in_oob, page);
249 +       if (len)
250 +               chip->read_buf(mtd, buf, len);
251 +
252 +       return 0;
253 +}
254 +EXPORT_SYMBOL_GPL(nand_read_oob_op);
255 +
256 +/**
257 + * nand_prog_page_begin_op - starts a PROG PAGE operation
258 + * @chip: The NAND chip
259 + * @page: page to write
260 + * @offset_in_page: offset within the page
261 + * @buf: buffer containing the data to write to the page
262 + * @len: length of the buffer
263 + *
264 + * This function issues the first half of a PROG PAGE operation.
265 + * This function does not select/unselect the CS line.
266 + *
267 + * Returns 0 on success, a negative error code otherwise.
268 + */
269 +int nand_prog_page_begin_op(struct nand_chip *chip, unsigned int page,
270 +                           unsigned int offset_in_page, const void *buf,
271 +                           unsigned int len)
272 +{
273 +       struct mtd_info *mtd = nand_to_mtd(chip);
274 +
275 +       if (len && !buf)
276 +               return -EINVAL;
277 +
278 +       if (offset_in_page + len > mtd->writesize + mtd->oobsize)
279 +               return -EINVAL;
280 +
281 +       chip->cmdfunc(mtd, NAND_CMD_SEQIN, offset_in_page, page);
282 +
283 +       if (buf)
284 +               chip->write_buf(mtd, buf, len);
285 +
286 +       return 0;
287 +}
288 +EXPORT_SYMBOL_GPL(nand_prog_page_begin_op);
289 +
290 +/**
291 + * nand_prog_page_end_op - ends a PROG PAGE operation
292 + * @chip: The NAND chip
293 + *
294 + * This function issues the second half of a PROG PAGE operation.
295 + * This function does not select/unselect the CS line.
296 + *
297 + * Returns 0 on success, a negative error code otherwise.
298 + */
299 +int nand_prog_page_end_op(struct nand_chip *chip)
300 +{
301 +       struct mtd_info *mtd = nand_to_mtd(chip);
302 +       int status;
303 +
304 +       chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
305 +
306 +       status = chip->waitfunc(mtd, chip);
307 +       if (status & NAND_STATUS_FAIL)
308 +               return -EIO;
309 +
310 +       return 0;
311 +}
312 +EXPORT_SYMBOL_GPL(nand_prog_page_end_op);
313 +
314 +/**
315 + * nand_prog_page_op - Do a full PROG PAGE operation
316 + * @chip: The NAND chip
317 + * @page: page to write
318 + * @offset_in_page: offset within the page
319 + * @buf: buffer containing the data to write to the page
320 + * @len: length of the buffer
321 + *
322 + * This function issues a full PROG PAGE operation.
323 + * This function does not select/unselect the CS line.
324 + *
325 + * Returns 0 on success, a negative error code otherwise.
326 + */
327 +int nand_prog_page_op(struct nand_chip *chip, unsigned int page,
328 +                     unsigned int offset_in_page, const void *buf,
329 +                     unsigned int len)
330 +{
331 +       struct mtd_info *mtd = nand_to_mtd(chip);
332 +       int status;
333 +
334 +       if (!len || !buf)
335 +               return -EINVAL;
336 +
337 +       if (offset_in_page + len > mtd->writesize + mtd->oobsize)
338 +               return -EINVAL;
339 +
340 +       chip->cmdfunc(mtd, NAND_CMD_SEQIN, offset_in_page, page);
341 +       chip->write_buf(mtd, buf, len);
342 +       chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
343 +
344 +       status = chip->waitfunc(mtd, chip);
345 +       if (status & NAND_STATUS_FAIL)
346 +               return -EIO;
347 +
348 +       return 0;
349 +}
350 +EXPORT_SYMBOL_GPL(nand_prog_page_op);
351 +
352 +/**
353 + * nand_change_write_column_op - Do a CHANGE WRITE COLUMN operation
354 + * @chip: The NAND chip
355 + * @offset_in_page: offset within the page
356 + * @buf: buffer containing the data to send to the NAND
357 + * @len: length of the buffer
358 + * @force_8bit: force 8-bit bus access
359 + *
360 + * This function issues a CHANGE WRITE COLUMN operation.
361 + * This function does not select/unselect the CS line.
362 + *
363 + * Returns 0 on success, a negative error code otherwise.
364 + */
365 +int nand_change_write_column_op(struct nand_chip *chip,
366 +                               unsigned int offset_in_page,
367 +                               const void *buf, unsigned int len,
368 +                               bool force_8bit)
369 +{
370 +       struct mtd_info *mtd = nand_to_mtd(chip);
371 +
372 +       if (len && !buf)
373 +               return -EINVAL;
374 +
375 +       if (offset_in_page + len > mtd->writesize + mtd->oobsize)
376 +               return -EINVAL;
377 +
378 +       chip->cmdfunc(mtd, NAND_CMD_RNDIN, offset_in_page, -1);
379 +       if (len)
380 +               chip->write_buf(mtd, buf, len);
381 +
382 +       return 0;
383 +}
384 +EXPORT_SYMBOL_GPL(nand_change_write_column_op);
385 +
386 +/**
387 + * nand_readid_op - Do a READID operation
388 + * @chip: The NAND chip
389 + * @addr: address cycle to pass after the READID command
390 + * @buf: buffer used to store the ID
391 + * @len: length of the buffer
392 + *
393 + * This function sends a READID command and reads back the ID returned by the
394 + * NAND.
395 + * This function does not select/unselect the CS line.
396 + *
397 + * Returns 0 on success, a negative error code otherwise.
398 + */
399 +int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf,
400 +                  unsigned int len)
401 +{
402 +       struct mtd_info *mtd = nand_to_mtd(chip);
403 +       unsigned int i;
404 +       u8 *id = buf;
405 +
406 +       if (len && !buf)
407 +               return -EINVAL;
408 +
409 +       chip->cmdfunc(mtd, NAND_CMD_READID, addr, -1);
410 +
411 +       for (i = 0; i < len; i++)
412 +               id[i] = chip->read_byte(mtd);
413 +
414 +       return 0;
415 +}
416 +EXPORT_SYMBOL_GPL(nand_readid_op);
417 +
418 +/**
419 + * nand_status_op - Do a STATUS operation
420 + * @chip: The NAND chip
421 + * @status: out variable to store the NAND status
422 + *
423 + * This function sends a STATUS command and reads back the status returned by
424 + * the NAND.
425 + * This function does not select/unselect the CS line.
426 + *
427 + * Returns 0 on success, a negative error code otherwise.
428 + */
429 +int nand_status_op(struct nand_chip *chip, u8 *status)
430 +{
431 +       struct mtd_info *mtd = nand_to_mtd(chip);
432 +
433 +       chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
434 +       if (status)
435 +               *status = chip->read_byte(mtd);
436 +
437 +       return 0;
438 +}
439 +EXPORT_SYMBOL_GPL(nand_status_op);
440 +
441 +/**
442 + * nand_exit_status_op - Exit a STATUS operation
443 + * @chip: The NAND chip
444 + *
445 + * This function sends a READ0 command to cancel the effect of the STATUS
446 + * command to avoid reading only the status until a new read command is sent.
447 + *
448 + * This function does not select/unselect the CS line.
449 + *
450 + * Returns 0 on success, a negative error code otherwise.
451 + */
452 +int nand_exit_status_op(struct nand_chip *chip)
453 +{
454 +       struct mtd_info *mtd = nand_to_mtd(chip);
455 +
456 +       chip->cmdfunc(mtd, NAND_CMD_READ0, -1, -1);
457 +
458 +       return 0;
459 +}
460 +EXPORT_SYMBOL_GPL(nand_exit_status_op);
461 +
462 +/**
463 + * nand_erase_op - Do an erase operation
464 + * @chip: The NAND chip
465 + * @eraseblock: block to erase
466 + *
467 + * This function sends an ERASE command and waits for the NAND to be ready
468 + * before returning.
469 + * This function does not select/unselect the CS line.
470 + *
471 + * Returns 0 on success, a negative error code otherwise.
472 + */
473 +int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock)
474 +{
475 +       struct mtd_info *mtd = nand_to_mtd(chip);
476 +       unsigned int page = eraseblock <<
477 +                           (chip->phys_erase_shift - chip->page_shift);
478 +       int status;
479 +
480 +       chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
481 +       chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
482 +
483 +       status = chip->waitfunc(mtd, chip);
484 +       if (status < 0)
485 +               return status;
486 +
487 +       if (status & NAND_STATUS_FAIL)
488 +               return -EIO;
489 +
490 +       return 0;
491 +}
492 +EXPORT_SYMBOL_GPL(nand_erase_op);
493 +
494 +/**
495 + * nand_set_features_op - Do a SET FEATURES operation
496 + * @chip: The NAND chip
497 + * @feature: feature id
498 + * @data: 4 bytes of data
499 + *
500 + * This function sends a SET FEATURES command and waits for the NAND to be
501 + * ready before returning.
502 + * This function does not select/unselect the CS line.
503 + *
504 + * Returns 0 on success, a negative error code otherwise.
505 + */
506 +static int nand_set_features_op(struct nand_chip *chip, u8 feature,
507 +                               const void *data)
508 +{
509 +       struct mtd_info *mtd = nand_to_mtd(chip);
510 +       const u8 *params = data;
511 +       int i, status;
512 +
513 +       chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, feature, -1);
514 +       for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
515 +               chip->write_byte(mtd, params[i]);
516 +
517 +       status = chip->waitfunc(mtd, chip);
518 +       if (status & NAND_STATUS_FAIL)
519 +               return -EIO;
520 +
521 +       return 0;
522 +}
523 +
524 +/**
525 + * nand_get_features_op - Do a GET FEATURES operation
526 + * @chip: The NAND chip
527 + * @feature: feature id
528 + * @data: 4 bytes of data
529 + *
530 + * This function sends a GET FEATURES command and waits for the NAND to be
531 + * ready before returning.
532 + * This function does not select/unselect the CS line.
533 + *
534 + * Returns 0 on success, a negative error code otherwise.
535 + */
536 +static int nand_get_features_op(struct nand_chip *chip, u8 feature,
537 +                               void *data)
538 +{
539 +       struct mtd_info *mtd = nand_to_mtd(chip);
540 +       u8 *params = data;
541 +       int i;
542 +
543 +       chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, feature, -1);
544 +       for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
545 +               params[i] = chip->read_byte(mtd);
546 +
547 +       return 0;
548 +}
549 +
550 +/**
551 + * nand_reset_op - Do a reset operation
552 + * @chip: The NAND chip
553 + *
554 + * This function sends a RESET command and waits for the NAND to be ready
555 + * before returning.
556 + * This function does not select/unselect the CS line.
557 + *
558 + * Returns 0 on success, a negative error code otherwise.
559 + */
560 +int nand_reset_op(struct nand_chip *chip)
561 +{
562 +       struct mtd_info *mtd = nand_to_mtd(chip);
563 +
564 +       chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
565 +
566 +       return 0;
567 +}
568 +EXPORT_SYMBOL_GPL(nand_reset_op);
569 +
570 +/**
571 + * nand_read_data_op - Read data from the NAND
572 + * @chip: The NAND chip
573 + * @buf: buffer used to store the data
574 + * @len: length of the buffer
575 + * @force_8bit: force 8-bit bus access
576 + *
577 + * This function does a raw data read on the bus. Usually used after launching
578 + * another NAND operation like nand_read_page_op().
579 + * This function does not select/unselect the CS line.
580 + *
581 + * Returns 0 on success, a negative error code otherwise.
582 + */
583 +int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len,
584 +                     bool force_8bit)
585 +{
586 +       struct mtd_info *mtd = nand_to_mtd(chip);
587 +
588 +       if (!len || !buf)
589 +               return -EINVAL;
590 +
591 +       if (force_8bit) {
592 +               u8 *p = buf;
593 +               unsigned int i;
594 +
595 +               for (i = 0; i < len; i++)
596 +                       p[i] = chip->read_byte(mtd);
597 +       } else {
598 +               chip->read_buf(mtd, buf, len);
599 +       }
600 +
601 +       return 0;
602 +}
603 +EXPORT_SYMBOL_GPL(nand_read_data_op);
604 +
605 +/**
606 + * nand_write_data_op - Write data from the NAND
607 + * @chip: The NAND chip
608 + * @buf: buffer containing the data to send on the bus
609 + * @len: length of the buffer
610 + * @force_8bit: force 8-bit bus access
611 + *
612 + * This function does a raw data write on the bus. Usually used after launching
613 + * another NAND operation like nand_write_page_begin_op().
614 + * This function does not select/unselect the CS line.
615 + *
616 + * Returns 0 on success, a negative error code otherwise.
617 + */
618 +int nand_write_data_op(struct nand_chip *chip, const void *buf,
619 +                      unsigned int len, bool force_8bit)
620 +{
621 +       struct mtd_info *mtd = nand_to_mtd(chip);
622 +
623 +       if (!len || !buf)
624 +               return -EINVAL;
625 +
626 +       if (force_8bit) {
627 +               const u8 *p = buf;
628 +               unsigned int i;
629 +
630 +               for (i = 0; i < len; i++)
631 +                       chip->write_byte(mtd, p[i]);
632 +       } else {
633 +               chip->write_buf(mtd, buf, len);
634 +       }
635 +
636 +       return 0;
637 +}
638 +EXPORT_SYMBOL_GPL(nand_write_data_op);
639 +
640 +/**
641   * nand_reset - Reset and initialize a NAND device
642   * @chip: The NAND chip
643   * @chipnr: Internal die id
644 @@ -1235,8 +1776,10 @@ int nand_reset(struct nand_chip *chip, i
645          * interface settings, hence this weird ->select_chip() dance.
646          */
647         chip->select_chip(mtd, chipnr);
648 -       chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
649 +       ret = nand_reset_op(chip);
650         chip->select_chip(mtd, -1);
651 +       if (ret)
652 +               return ret;
653  
654         chip->select_chip(mtd, chipnr);
655         ret = nand_setup_data_interface(chip, chipnr);
656 @@ -1392,9 +1935,19 @@ EXPORT_SYMBOL(nand_check_erased_ecc_chun
657  int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
658                        uint8_t *buf, int oob_required, int page)
659  {
660 -       chip->read_buf(mtd, buf, mtd->writesize);
661 -       if (oob_required)
662 -               chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
663 +       int ret;
664 +
665 +       ret = nand_read_data_op(chip, buf, mtd->writesize, false);
666 +       if (ret)
667 +               return ret;
668 +
669 +       if (oob_required) {
670 +               ret = nand_read_data_op(chip, chip->oob_poi, mtd->oobsize,
671 +                                       false);
672 +               if (ret)
673 +                       return ret;
674 +       }
675 +
676         return 0;
677  }
678  EXPORT_SYMBOL(nand_read_page_raw);
679 @@ -1416,29 +1969,46 @@ static int nand_read_page_raw_syndrome(s
680         int eccsize = chip->ecc.size;
681         int eccbytes = chip->ecc.bytes;
682         uint8_t *oob = chip->oob_poi;
683 -       int steps, size;
684 +       int steps, size, ret;
685  
686         for (steps = chip->ecc.steps; steps > 0; steps--) {
687 -               chip->read_buf(mtd, buf, eccsize);
688 +               ret = nand_read_data_op(chip, buf, eccsize, false);
689 +               if (ret)
690 +                       return ret;
691 +
692                 buf += eccsize;
693  
694                 if (chip->ecc.prepad) {
695 -                       chip->read_buf(mtd, oob, chip->ecc.prepad);
696 +                       ret = nand_read_data_op(chip, oob, chip->ecc.prepad,
697 +                                               false);
698 +                       if (ret)
699 +                               return ret;
700 +
701                         oob += chip->ecc.prepad;
702                 }
703  
704 -               chip->read_buf(mtd, oob, eccbytes);
705 +               ret = nand_read_data_op(chip, oob, eccbytes, false);
706 +               if (ret)
707 +                       return ret;
708 +
709                 oob += eccbytes;
710  
711                 if (chip->ecc.postpad) {
712 -                       chip->read_buf(mtd, oob, chip->ecc.postpad);
713 +                       ret = nand_read_data_op(chip, oob, chip->ecc.postpad,
714 +                                               false);
715 +                       if (ret)
716 +                               return ret;
717 +
718                         oob += chip->ecc.postpad;
719                 }
720         }
721  
722         size = mtd->oobsize - (oob - chip->oob_poi);
723 -       if (size)
724 -               chip->read_buf(mtd, oob, size);
725 +       if (size) {
726 +               ret = nand_read_data_op(chip, oob, size, false);
727 +               if (ret)
728 +                       return ret;
729 +       }
730  
731         return 0;
732  }
733 @@ -1527,7 +2097,9 @@ static int nand_read_subpage(struct mtd_
734                 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1);
735  
736         p = bufpoi + data_col_addr;
737 -       chip->read_buf(mtd, p, datafrag_len);
738 +       ret = nand_read_data_op(chip, p, datafrag_len, false);
739 +       if (ret)
740 +               return ret;
741  
742         /* Calculate ECC */
743         for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size)
744 @@ -1545,8 +2117,11 @@ static int nand_read_subpage(struct mtd_
745                 gaps = 1;
746  
747         if (gaps) {
748 -               chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
749 -               chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
750 +               ret = nand_change_read_column_op(chip, mtd->writesize,
751 +                                                chip->oob_poi, mtd->oobsize,
752 +                                                false);
753 +               if (ret)
754 +                       return ret;
755         } else {
756                 /*
757                  * Send the command to read the particular ECC bytes take care
758 @@ -1560,9 +2135,12 @@ static int nand_read_subpage(struct mtd_
759                     (busw - 1))
760                         aligned_len++;
761  
762 -               chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
763 -                             mtd->writesize + aligned_pos, -1);
764 -               chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len);
765 +               ret = nand_change_read_column_op(chip,
766 +                                                mtd->writesize + aligned_pos,
767 +                                                &chip->oob_poi[aligned_pos],
768 +                                                aligned_len, false);
769 +               if (ret)
770 +                       return ret;
771         }
772  
773         ret = mtd_ooblayout_get_eccbytes(mtd, chip->buffers->ecccode,
774 @@ -1619,10 +2197,17 @@ static int nand_read_page_hwecc(struct m
775  
776         for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
777                 chip->ecc.hwctl(mtd, NAND_ECC_READ);
778 -               chip->read_buf(mtd, p, eccsize);
779 +
780 +               ret = nand_read_data_op(chip, p, eccsize, false);
781 +               if (ret)
782 +                       return ret;
783 +
784                 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
785         }
786 -       chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
787 +
788 +       ret = nand_read_data_op(chip, chip->oob_poi, mtd->oobsize, false);
789 +       if (ret)
790 +               return ret;
791  
792         ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
793                                          chip->ecc.total);
794 @@ -1681,9 +2266,13 @@ static int nand_read_page_hwecc_oob_firs
795         unsigned int max_bitflips = 0;
796  
797         /* Read the OOB area first */
798 -       chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
799 -       chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
800 -       chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
801 +       ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
802 +       if (ret)
803 +               return ret;
804 +
805 +       ret = nand_read_page_op(chip, page, 0, NULL, 0);
806 +       if (ret)
807 +               return ret;
808  
809         ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
810                                          chip->ecc.total);
811 @@ -1694,7 +2283,11 @@ static int nand_read_page_hwecc_oob_firs
812                 int stat;
813  
814                 chip->ecc.hwctl(mtd, NAND_ECC_READ);
815 -               chip->read_buf(mtd, p, eccsize);
816 +
817 +               ret = nand_read_data_op(chip, p, eccsize, false);
818 +               if (ret)
819 +                       return ret;
820 +
821                 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
822  
823                 stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL);
824 @@ -1731,7 +2324,7 @@ static int nand_read_page_hwecc_oob_firs
825  static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
826                                    uint8_t *buf, int oob_required, int page)
827  {
828 -       int i, eccsize = chip->ecc.size;
829 +       int ret, i, eccsize = chip->ecc.size;
830         int eccbytes = chip->ecc.bytes;
831         int eccsteps = chip->ecc.steps;
832         int eccpadbytes = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
833 @@ -1743,21 +2336,36 @@ static int nand_read_page_syndrome(struc
834                 int stat;
835  
836                 chip->ecc.hwctl(mtd, NAND_ECC_READ);
837 -               chip->read_buf(mtd, p, eccsize);
838 +
839 +               ret = nand_read_data_op(chip, p, eccsize, false);
840 +               if (ret)
841 +                       return ret;
842  
843                 if (chip->ecc.prepad) {
844 -                       chip->read_buf(mtd, oob, chip->ecc.prepad);
845 +                       ret = nand_read_data_op(chip, oob, chip->ecc.prepad,
846 +                                               false);
847 +                       if (ret)
848 +                               return ret;
849 +
850                         oob += chip->ecc.prepad;
851                 }
852  
853                 chip->ecc.hwctl(mtd, NAND_ECC_READSYN);
854 -               chip->read_buf(mtd, oob, eccbytes);
855 +
856 +               ret = nand_read_data_op(chip, oob, eccbytes, false);
857 +               if (ret)
858 +                       return ret;
859 +
860                 stat = chip->ecc.correct(mtd, p, oob, NULL);
861  
862                 oob += eccbytes;
863  
864                 if (chip->ecc.postpad) {
865 -                       chip->read_buf(mtd, oob, chip->ecc.postpad);
866 +                       ret = nand_read_data_op(chip, oob, chip->ecc.postpad,
867 +                                               false);
868 +                       if (ret)
869 +                               return ret;
870 +
871                         oob += chip->ecc.postpad;
872                 }
873  
874 @@ -1781,8 +2389,11 @@ static int nand_read_page_syndrome(struc
875  
876         /* Calculate remaining oob bytes */
877         i = mtd->oobsize - (oob - chip->oob_poi);
878 -       if (i)
879 -               chip->read_buf(mtd, oob, i);
880 +       if (i) {
881 +               ret = nand_read_data_op(chip, oob, i, false);
882 +               if (ret)
883 +                       return ret;
884 +       }
885  
886         return max_bitflips;
887  }
888 @@ -1903,8 +2514,11 @@ static int nand_do_read_ops(struct mtd_i
889                                                  __func__, buf);
890  
891  read_retry:
892 -                       if (nand_standard_page_accessors(&chip->ecc))
893 -                               chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
894 +                       if (nand_standard_page_accessors(&chip->ecc)) {
895 +                               ret = nand_read_page_op(chip, page, 0, NULL, 0);
896 +                               if (ret)
897 +                                       break;
898 +                       }
899  
900                         /*
901                          * Now read the page into the buffer.  Absent an error,
902 @@ -2063,9 +2677,7 @@ static int nand_read(struct mtd_info *mt
903   */
904  int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page)
905  {
906 -       chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
907 -       chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
908 -       return 0;
909 +       return nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
910  }
911  EXPORT_SYMBOL(nand_read_oob_std);
912  
913 @@ -2083,25 +2695,43 @@ int nand_read_oob_syndrome(struct mtd_in
914         int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
915         int eccsize = chip->ecc.size;
916         uint8_t *bufpoi = chip->oob_poi;
917 -       int i, toread, sndrnd = 0, pos;
918 +       int i, toread, sndrnd = 0, pos, ret;
919 +
920 +       ret = nand_read_page_op(chip, page, chip->ecc.size, NULL, 0);
921 +       if (ret)
922 +               return ret;
923  
924 -       chip->cmdfunc(mtd, NAND_CMD_READ0, chip->ecc.size, page);
925         for (i = 0; i < chip->ecc.steps; i++) {
926                 if (sndrnd) {
927 +                       int ret;
928 +
929                         pos = eccsize + i * (eccsize + chunk);
930                         if (mtd->writesize > 512)
931 -                               chip->cmdfunc(mtd, NAND_CMD_RNDOUT, pos, -1);
932 +                               ret = nand_change_read_column_op(chip, pos,
933 +                                                                NULL, 0,
934 +                                                                false);
935                         else
936 -                               chip->cmdfunc(mtd, NAND_CMD_READ0, pos, page);
937 +                               ret = nand_read_page_op(chip, page, pos, NULL,
938 +                                                       0);
939 +
940 +                       if (ret)
941 +                               return ret;
942                 } else
943                         sndrnd = 1;
944                 toread = min_t(int, length, chunk);
945 -               chip->read_buf(mtd, bufpoi, toread);
946 +
947 +               ret = nand_read_data_op(chip, bufpoi, toread, false);
948 +               if (ret)
949 +                       return ret;
950 +
951                 bufpoi += toread;
952                 length -= toread;
953         }
954 -       if (length > 0)
955 -               chip->read_buf(mtd, bufpoi, length);
956 +       if (length > 0) {
957 +               ret = nand_read_data_op(chip, bufpoi, length, false);
958 +               if (ret)
959 +                       return ret;
960 +       }
961  
962         return 0;
963  }
964 @@ -2115,18 +2745,8 @@ EXPORT_SYMBOL(nand_read_oob_syndrome);
965   */
966  int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page)
967  {
968 -       int status = 0;
969 -       const uint8_t *buf = chip->oob_poi;
970 -       int length = mtd->oobsize;
971 -
972 -       chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
973 -       chip->write_buf(mtd, buf, length);
974 -       /* Send command to program the OOB data */
975 -       chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
976 -
977 -       status = chip->waitfunc(mtd, chip);
978 -
979 -       return status & NAND_STATUS_FAIL ? -EIO : 0;
980 +       return nand_prog_page_op(chip, page, mtd->writesize, chip->oob_poi,
981 +                                mtd->oobsize);
982  }
983  EXPORT_SYMBOL(nand_write_oob_std);
984  
985 @@ -2142,7 +2762,7 @@ int nand_write_oob_syndrome(struct mtd_i
986  {
987         int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
988         int eccsize = chip->ecc.size, length = mtd->oobsize;
989 -       int i, len, pos, status = 0, sndcmd = 0, steps = chip->ecc.steps;
990 +       int ret, i, len, pos, sndcmd = 0, steps = chip->ecc.steps;
991         const uint8_t *bufpoi = chip->oob_poi;
992  
993         /*
994 @@ -2156,7 +2776,10 @@ int nand_write_oob_syndrome(struct mtd_i
995         } else
996                 pos = eccsize;
997  
998 -       chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page);
999 +       ret = nand_prog_page_begin_op(chip, page, pos, NULL, 0);
1000 +       if (ret)
1001 +               return ret;
1002 +
1003         for (i = 0; i < steps; i++) {
1004                 if (sndcmd) {
1005                         if (mtd->writesize <= 512) {
1006 @@ -2165,28 +2788,40 @@ int nand_write_oob_syndrome(struct mtd_i
1007                                 len = eccsize;
1008                                 while (len > 0) {
1009                                         int num = min_t(int, len, 4);
1010 -                                       chip->write_buf(mtd, (uint8_t *)&fill,
1011 -                                                       num);
1012 +
1013 +                                       ret = nand_write_data_op(chip, &fill,
1014 +                                                                num, false);
1015 +                                       if (ret)
1016 +                                               return ret;
1017 +
1018                                         len -= num;
1019                                 }
1020                         } else {
1021                                 pos = eccsize + i * (eccsize + chunk);
1022 -                               chip->cmdfunc(mtd, NAND_CMD_RNDIN, pos, -1);
1023 +                               ret = nand_change_write_column_op(chip, pos,
1024 +                                                                 NULL, 0,
1025 +                                                                 false);
1026 +                               if (ret)
1027 +                                       return ret;
1028                         }
1029                 } else
1030                         sndcmd = 1;
1031                 len = min_t(int, length, chunk);
1032 -               chip->write_buf(mtd, bufpoi, len);
1033 +
1034 +               ret = nand_write_data_op(chip, bufpoi, len, false);
1035 +               if (ret)
1036 +                       return ret;
1037 +
1038                 bufpoi += len;
1039                 length -= len;
1040         }
1041 -       if (length > 0)
1042 -               chip->write_buf(mtd, bufpoi, length);
1043 -
1044 -       chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
1045 -       status = chip->waitfunc(mtd, chip);
1046 +       if (length > 0) {
1047 +               ret = nand_write_data_op(chip, bufpoi, length, false);
1048 +               if (ret)
1049 +                       return ret;
1050 +       }
1051  
1052 -       return status & NAND_STATUS_FAIL ? -EIO : 0;
1053 +       return nand_prog_page_end_op(chip);
1054  }
1055  EXPORT_SYMBOL(nand_write_oob_syndrome);
1056  
1057 @@ -2341,9 +2976,18 @@ static int nand_read_oob(struct mtd_info
1058  int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
1059                         const uint8_t *buf, int oob_required, int page)
1060  {
1061 -       chip->write_buf(mtd, buf, mtd->writesize);
1062 -       if (oob_required)
1063 -               chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
1064 +       int ret;
1065 +
1066 +       ret = nand_write_data_op(chip, buf, mtd->writesize, false);
1067 +       if (ret)
1068 +               return ret;
1069 +
1070 +       if (oob_required) {
1071 +               ret = nand_write_data_op(chip, chip->oob_poi, mtd->oobsize,
1072 +                                        false);
1073 +               if (ret)
1074 +                       return ret;
1075 +       }
1076  
1077         return 0;
1078  }
1079 @@ -2367,29 +3011,46 @@ static int nand_write_page_raw_syndrome(
1080         int eccsize = chip->ecc.size;
1081         int eccbytes = chip->ecc.bytes;
1082         uint8_t *oob = chip->oob_poi;
1083 -       int steps, size;
1084 +       int steps, size, ret;
1085  
1086         for (steps = chip->ecc.steps; steps > 0; steps--) {
1087 -               chip->write_buf(mtd, buf, eccsize);
1088 +               ret = nand_write_data_op(chip, buf, eccsize, false);
1089 +               if (ret)
1090 +                       return ret;
1091 +
1092                 buf += eccsize;
1093  
1094                 if (chip->ecc.prepad) {
1095 -                       chip->write_buf(mtd, oob, chip->ecc.prepad);
1096 +                       ret = nand_write_data_op(chip, oob, chip->ecc.prepad,
1097 +                                                false);
1098 +                       if (ret)
1099 +                               return ret;
1100 +
1101                         oob += chip->ecc.prepad;
1102                 }
1103  
1104 -               chip->write_buf(mtd, oob, eccbytes);
1105 +               ret = nand_write_data_op(chip, oob, eccbytes, false);
1106 +               if (ret)
1107 +                       return ret;
1108 +
1109                 oob += eccbytes;
1110  
1111                 if (chip->ecc.postpad) {
1112 -                       chip->write_buf(mtd, oob, chip->ecc.postpad);
1113 +                       ret = nand_write_data_op(chip, oob, chip->ecc.postpad,
1114 +                                                false);
1115 +                       if (ret)
1116 +                               return ret;
1117 +
1118                         oob += chip->ecc.postpad;
1119                 }
1120         }
1121  
1122         size = mtd->oobsize - (oob - chip->oob_poi);
1123 -       if (size)
1124 -               chip->write_buf(mtd, oob, size);
1125 +       if (size) {
1126 +               ret = nand_write_data_op(chip, oob, size, false);
1127 +               if (ret)
1128 +                       return ret;
1129 +       }
1130  
1131         return 0;
1132  }
1133 @@ -2443,7 +3104,11 @@ static int nand_write_page_hwecc(struct
1134  
1135         for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
1136                 chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
1137 -               chip->write_buf(mtd, p, eccsize);
1138 +
1139 +               ret = nand_write_data_op(chip, p, eccsize, false);
1140 +               if (ret)
1141 +                       return ret;
1142 +
1143                 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
1144         }
1145  
1146 @@ -2452,7 +3117,9 @@ static int nand_write_page_hwecc(struct
1147         if (ret)
1148                 return ret;
1149  
1150 -       chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
1151 +       ret = nand_write_data_op(chip, chip->oob_poi, mtd->oobsize, false);
1152 +       if (ret)
1153 +               return ret;
1154  
1155         return 0;
1156  }
1157 @@ -2488,7 +3155,9 @@ static int nand_write_subpage_hwecc(stru
1158                 chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
1159  
1160                 /* write data (untouched subpages already masked by 0xFF) */
1161 -               chip->write_buf(mtd, buf, ecc_size);
1162 +               ret = nand_write_data_op(chip, buf, ecc_size, false);
1163 +               if (ret)
1164 +                       return ret;
1165  
1166                 /* mask ECC of un-touched subpages by padding 0xFF */
1167                 if ((step < start_step) || (step > end_step))
1168 @@ -2515,7 +3184,9 @@ static int nand_write_subpage_hwecc(stru
1169                 return ret;
1170  
1171         /* write OOB buffer to NAND device */
1172 -       chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
1173 +       ret = nand_write_data_op(chip, chip->oob_poi, mtd->oobsize, false);
1174 +       if (ret)
1175 +               return ret;
1176  
1177         return 0;
1178  }
1179 @@ -2542,31 +3213,49 @@ static int nand_write_page_syndrome(stru
1180         int eccsteps = chip->ecc.steps;
1181         const uint8_t *p = buf;
1182         uint8_t *oob = chip->oob_poi;
1183 +       int ret;
1184  
1185         for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
1186 -
1187                 chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
1188 -               chip->write_buf(mtd, p, eccsize);
1189 +
1190 +               ret = nand_write_data_op(chip, p, eccsize, false);
1191 +               if (ret)
1192 +                       return ret;
1193  
1194                 if (chip->ecc.prepad) {
1195 -                       chip->write_buf(mtd, oob, chip->ecc.prepad);
1196 +                       ret = nand_write_data_op(chip, oob, chip->ecc.prepad,
1197 +                                                false);
1198 +                       if (ret)
1199 +                               return ret;
1200 +
1201                         oob += chip->ecc.prepad;
1202                 }
1203  
1204                 chip->ecc.calculate(mtd, p, oob);
1205 -               chip->write_buf(mtd, oob, eccbytes);
1206 +
1207 +               ret = nand_write_data_op(chip, oob, eccbytes, false);
1208 +               if (ret)
1209 +                       return ret;
1210 +
1211                 oob += eccbytes;
1212  
1213                 if (chip->ecc.postpad) {
1214 -                       chip->write_buf(mtd, oob, chip->ecc.postpad);
1215 +                       ret = nand_write_data_op(chip, oob, chip->ecc.postpad,
1216 +                                                false);
1217 +                       if (ret)
1218 +                               return ret;
1219 +
1220                         oob += chip->ecc.postpad;
1221                 }
1222         }
1223  
1224         /* Calculate remaining oob bytes */
1225         i = mtd->oobsize - (oob - chip->oob_poi);
1226 -       if (i)
1227 -               chip->write_buf(mtd, oob, i);
1228 +       if (i) {
1229 +               ret = nand_write_data_op(chip, oob, i, false);
1230 +               if (ret)
1231 +                       return ret;
1232 +       }
1233  
1234         return 0;
1235  }
1236 @@ -2594,8 +3283,11 @@ static int nand_write_page(struct mtd_in
1237         else
1238                 subpage = 0;
1239  
1240 -       if (nand_standard_page_accessors(&chip->ecc))
1241 -               chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
1242 +       if (nand_standard_page_accessors(&chip->ecc)) {
1243 +               status = nand_prog_page_begin_op(chip, page, 0, NULL, 0);
1244 +               if (status)
1245 +                       return status;
1246 +       }
1247  
1248         if (unlikely(raw))
1249                 status = chip->ecc.write_page_raw(mtd, chip, buf,
1250 @@ -2610,13 +3302,8 @@ static int nand_write_page(struct mtd_in
1251         if (status < 0)
1252                 return status;
1253  
1254 -       if (nand_standard_page_accessors(&chip->ecc)) {
1255 -               chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
1256 -
1257 -               status = chip->waitfunc(mtd, chip);
1258 -               if (status & NAND_STATUS_FAIL)
1259 -                       return -EIO;
1260 -       }
1261 +       if (nand_standard_page_accessors(&chip->ecc))
1262 +               return nand_prog_page_end_op(chip);
1263  
1264         return 0;
1265  }
1266 @@ -2989,17 +3676,12 @@ out:
1267  static int single_erase(struct mtd_info *mtd, int page)
1268  {
1269         struct nand_chip *chip = mtd_to_nand(mtd);
1270 -       int status;
1271 +       unsigned int eraseblock;
1272  
1273         /* Send commands to erase a block */
1274 -       chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
1275 -       chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
1276 -
1277 -       status = chip->waitfunc(mtd, chip);
1278 -       if (status < 0)
1279 -               return status;
1280 +       eraseblock = page >> (chip->phys_erase_shift - chip->page_shift);
1281  
1282 -       return status & NAND_STATUS_FAIL ? -EIO : 0;
1283 +       return nand_erase_op(chip, eraseblock);
1284  }
1285  
1286  /**
1287 @@ -3226,22 +3908,12 @@ static int nand_max_bad_blocks(struct mt
1288  static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
1289                         int addr, uint8_t *subfeature_param)
1290  {
1291 -       int status;
1292 -       int i;
1293 -
1294         if (!chip->onfi_version ||
1295             !(le16_to_cpu(chip->onfi_params.opt_cmd)
1296               & ONFI_OPT_CMD_SET_GET_FEATURES))
1297                 return -EINVAL;
1298  
1299 -       chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1);
1300 -       for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
1301 -               chip->write_byte(mtd, subfeature_param[i]);
1302 -
1303 -       status = chip->waitfunc(mtd, chip);
1304 -       if (status & NAND_STATUS_FAIL)
1305 -               return -EIO;
1306 -       return 0;
1307 +       return nand_set_features_op(chip, addr, subfeature_param);
1308  }
1309  
1310  /**
1311 @@ -3254,17 +3926,12 @@ static int nand_onfi_set_features(struct
1312  static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
1313                         int addr, uint8_t *subfeature_param)
1314  {
1315 -       int i;
1316 -
1317         if (!chip->onfi_version ||
1318             !(le16_to_cpu(chip->onfi_params.opt_cmd)
1319               & ONFI_OPT_CMD_SET_GET_FEATURES))
1320                 return -EINVAL;
1321  
1322 -       chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1);
1323 -       for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
1324 -               *subfeature_param++ = chip->read_byte(mtd);
1325 -       return 0;
1326 +       return nand_get_features_op(chip, addr, subfeature_param);
1327  }
1328  
1329  /**
1330 @@ -3407,12 +4074,11 @@ static u16 onfi_crc16(u16 crc, u8 const
1331  static int nand_flash_detect_ext_param_page(struct nand_chip *chip,
1332                                             struct nand_onfi_params *p)
1333  {
1334 -       struct mtd_info *mtd = nand_to_mtd(chip);
1335         struct onfi_ext_param_page *ep;
1336         struct onfi_ext_section *s;
1337         struct onfi_ext_ecc_info *ecc;
1338         uint8_t *cursor;
1339 -       int ret = -EINVAL;
1340 +       int ret;
1341         int len;
1342         int i;
1343  
1344 @@ -3422,14 +4088,18 @@ static int nand_flash_detect_ext_param_p
1345                 return -ENOMEM;
1346  
1347         /* Send our own NAND_CMD_PARAM. */
1348 -       chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
1349 +       ret = nand_read_param_page_op(chip, 0, NULL, 0);
1350 +       if (ret)
1351 +               goto ext_out;
1352  
1353         /* Use the Change Read Column command to skip the ONFI param pages. */
1354 -       chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
1355 -                       sizeof(*p) * p->num_of_param_pages , -1);
1356 +       ret = nand_change_read_column_op(chip,
1357 +                                        sizeof(*p) * p->num_of_param_pages,
1358 +                                        ep, len, true);
1359 +       if (ret)
1360 +               goto ext_out;
1361  
1362 -       /* Read out the Extended Parameter Page. */
1363 -       chip->read_buf(mtd, (uint8_t *)ep, len);
1364 +       ret = -EINVAL;
1365         if ((onfi_crc16(ONFI_CRC_BASE, ((uint8_t *)ep) + 2, len - 2)
1366                 != le16_to_cpu(ep->crc))) {
1367                 pr_debug("fail in the CRC.\n");
1368 @@ -3482,19 +4152,23 @@ static int nand_flash_detect_onfi(struct
1369  {
1370         struct mtd_info *mtd = nand_to_mtd(chip);
1371         struct nand_onfi_params *p = &chip->onfi_params;
1372 -       int i, j;
1373 -       int val;
1374 +       char id[4];
1375 +       int i, ret, val;
1376  
1377         /* Try ONFI for unknown chip or LP */
1378 -       chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
1379 -       if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||
1380 -               chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
1381 +       ret = nand_readid_op(chip, 0x20, id, sizeof(id));
1382 +       if (ret || strncmp(id, "ONFI", 4))
1383 +               return 0;
1384 +
1385 +       ret = nand_read_param_page_op(chip, 0, NULL, 0);
1386 +       if (ret)
1387                 return 0;
1388  
1389 -       chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
1390         for (i = 0; i < 3; i++) {
1391 -               for (j = 0; j < sizeof(*p); j++)
1392 -                       ((uint8_t *)p)[j] = chip->read_byte(mtd);
1393 +               ret = nand_read_data_op(chip, p, sizeof(*p), true);
1394 +               if (ret)
1395 +                       return 0;
1396 +
1397                 if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
1398                                 le16_to_cpu(p->crc)) {
1399                         break;
1400 @@ -3585,20 +4259,22 @@ static int nand_flash_detect_jedec(struc
1401         struct mtd_info *mtd = nand_to_mtd(chip);
1402         struct nand_jedec_params *p = &chip->jedec_params;
1403         struct jedec_ecc_info *ecc;
1404 -       int val;
1405 -       int i, j;
1406 +       char id[5];
1407 +       int i, val, ret;
1408  
1409         /* Try JEDEC for unknown chip or LP */
1410 -       chip->cmdfunc(mtd, NAND_CMD_READID, 0x40, -1);
1411 -       if (chip->read_byte(mtd) != 'J' || chip->read_byte(mtd) != 'E' ||
1412 -               chip->read_byte(mtd) != 'D' || chip->read_byte(mtd) != 'E' ||
1413 -               chip->read_byte(mtd) != 'C')
1414 +       ret = nand_readid_op(chip, 0x40, id, sizeof(id));
1415 +       if (ret || strncmp(id, "JEDEC", sizeof(id)))
1416 +               return 0;
1417 +
1418 +       ret = nand_read_param_page_op(chip, 0x40, NULL, 0);
1419 +       if (ret)
1420                 return 0;
1421  
1422 -       chip->cmdfunc(mtd, NAND_CMD_PARAM, 0x40, -1);
1423         for (i = 0; i < 3; i++) {
1424 -               for (j = 0; j < sizeof(*p); j++)
1425 -                       ((uint8_t *)p)[j] = chip->read_byte(mtd);
1426 +               ret = nand_read_data_op(chip, p, sizeof(*p), true);
1427 +               if (ret)
1428 +                       return 0;
1429  
1430                 if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 510) ==
1431                                 le16_to_cpu(p->crc))
1432 @@ -3877,8 +4553,7 @@ static int nand_detect(struct nand_chip
1433  {
1434         const struct nand_manufacturer *manufacturer;
1435         struct mtd_info *mtd = nand_to_mtd(chip);
1436 -       int busw;
1437 -       int i;
1438 +       int busw, ret;
1439         u8 *id_data = chip->id.data;
1440         u8 maf_id, dev_id;
1441  
1442 @@ -3886,17 +4561,21 @@ static int nand_detect(struct nand_chip
1443          * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
1444          * after power-up.
1445          */
1446 -       nand_reset(chip, 0);
1447 +       ret = nand_reset(chip, 0);
1448 +       if (ret)
1449 +               return ret;
1450  
1451         /* Select the device */
1452         chip->select_chip(mtd, 0);
1453  
1454         /* Send the command for reading device ID */
1455 -       chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
1456 +       ret = nand_readid_op(chip, 0, id_data, 2);
1457 +       if (ret)
1458 +               return ret;
1459  
1460         /* Read manufacturer and device IDs */
1461 -       maf_id = chip->read_byte(mtd);
1462 -       dev_id = chip->read_byte(mtd);
1463 +       maf_id = id_data[0];
1464 +       dev_id = id_data[1];
1465  
1466         /*
1467          * Try again to make sure, as some systems the bus-hold or other
1468 @@ -3905,11 +4584,10 @@ static int nand_detect(struct nand_chip
1469          * not match, ignore the device completely.
1470          */
1471  
1472 -       chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
1473 -
1474         /* Read entire ID string */
1475 -       for (i = 0; i < ARRAY_SIZE(chip->id.data); i++)
1476 -               id_data[i] = chip->read_byte(mtd);
1477 +       ret = nand_readid_op(chip, 0, id_data, sizeof(chip->id.data));
1478 +       if (ret)
1479 +               return ret;
1480  
1481         if (id_data[0] != maf_id || id_data[1] != dev_id) {
1482                 pr_info("second ID read did not match %02x,%02x against %02x,%02x\n",
1483 @@ -4233,15 +4911,16 @@ int nand_scan_ident(struct mtd_info *mtd
1484  
1485         /* Check for a chip array */
1486         for (i = 1; i < maxchips; i++) {
1487 +               u8 id[2];
1488 +
1489                 /* See comment in nand_get_flash_type for reset */
1490                 nand_reset(chip, i);
1491  
1492                 chip->select_chip(mtd, i);
1493                 /* Send the command for reading device ID */
1494 -               chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
1495 +               nand_readid_op(chip, 0, id, sizeof(id));
1496                 /* Read manufacturer and device IDs */
1497 -               if (nand_maf_id != chip->read_byte(mtd) ||
1498 -                   nand_dev_id != chip->read_byte(mtd)) {
1499 +               if (nand_maf_id != id[0] || nand_dev_id != id[1]) {
1500                         chip->select_chip(mtd, -1);
1501                         break;
1502                 }
1503 --- a/drivers/mtd/nand/qcom_nandc.c
1504 +++ b/drivers/mtd/nand/qcom_nandc.c
1505 @@ -1990,7 +1990,7 @@ static int qcom_nandc_write_oob(struct m
1506         struct nand_ecc_ctrl *ecc = &chip->ecc;
1507         u8 *oob = chip->oob_poi;
1508         int data_size, oob_size;
1509 -       int ret, status = 0;
1510 +       int ret;
1511  
1512         host->use_ecc = true;
1513  
1514 @@ -2027,11 +2027,7 @@ static int qcom_nandc_write_oob(struct m
1515                 return -EIO;
1516         }
1517  
1518 -       chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
1519 -
1520 -       status = chip->waitfunc(mtd, chip);
1521 -
1522 -       return status & NAND_STATUS_FAIL ? -EIO : 0;
1523 +       return nand_prog_page_end_op(chip);
1524  }
1525  
1526  static int qcom_nandc_block_bad(struct mtd_info *mtd, loff_t ofs)
1527 @@ -2081,7 +2077,7 @@ static int qcom_nandc_block_markbad(stru
1528         struct qcom_nand_host *host = to_qcom_nand_host(chip);
1529         struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
1530         struct nand_ecc_ctrl *ecc = &chip->ecc;
1531 -       int page, ret, status = 0;
1532 +       int page, ret;
1533  
1534         clear_read_regs(nandc);
1535         clear_bam_transaction(nandc);
1536 @@ -2114,11 +2110,7 @@ static int qcom_nandc_block_markbad(stru
1537                 return -EIO;
1538         }
1539  
1540 -       chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
1541 -
1542 -       status = chip->waitfunc(mtd, chip);
1543 -
1544 -       return status & NAND_STATUS_FAIL ? -EIO : 0;
1545 +       return nand_prog_page_end_op(chip);
1546  }
1547  
1548  /*
1549 --- a/include/linux/mtd/rawnand.h
1550 +++ b/include/linux/mtd/rawnand.h
1551 @@ -1313,6 +1313,35 @@ int nand_write_page_raw(struct mtd_info
1552  /* Reset and initialize a NAND device */
1553  int nand_reset(struct nand_chip *chip, int chipnr);
1554  
1555 +/* NAND operation helpers */
1556 +int nand_reset_op(struct nand_chip *chip);
1557 +int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf,
1558 +                  unsigned int len);
1559 +int nand_status_op(struct nand_chip *chip, u8 *status);
1560 +int nand_exit_status_op(struct nand_chip *chip);
1561 +int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock);
1562 +int nand_read_page_op(struct nand_chip *chip, unsigned int page,
1563 +                     unsigned int offset_in_page, void *buf, unsigned int len);
1564 +int nand_change_read_column_op(struct nand_chip *chip,
1565 +                              unsigned int offset_in_page, void *buf,
1566 +                              unsigned int len, bool force_8bit);
1567 +int nand_read_oob_op(struct nand_chip *chip, unsigned int page,
1568 +                    unsigned int offset_in_page, void *buf, unsigned int len);
1569 +int nand_prog_page_begin_op(struct nand_chip *chip, unsigned int page,
1570 +                           unsigned int offset_in_page, const void *buf,
1571 +                           unsigned int len);
1572 +int nand_prog_page_end_op(struct nand_chip *chip);
1573 +int nand_prog_page_op(struct nand_chip *chip, unsigned int page,
1574 +                     unsigned int offset_in_page, const void *buf,
1575 +                     unsigned int len);
1576 +int nand_change_write_column_op(struct nand_chip *chip,
1577 +                               unsigned int offset_in_page, const void *buf,
1578 +                               unsigned int len, bool force_8bit);
1579 +int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len,
1580 +                     bool force_8bit);
1581 +int nand_write_data_op(struct nand_chip *chip, const void *buf,
1582 +                      unsigned int len, bool force_8bit);
1583 +
1584  /* Free resources held by the NAND device */
1585  void nand_cleanup(struct nand_chip *chip);
1586