]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/nand/nand.c
MFV r337029:
[FreeBSD/FreeBSD.git] / sys / dev / nand / nand.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (C) 2009-2012 Semihalf
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/socket.h>
36 #include <sys/malloc.h>
37 #include <sys/module.h>
38 #include <sys/bus.h>
39 #include <sys/lock.h>
40 #include <sys/mutex.h>
41 #include <sys/callout.h>
42 #include <sys/sysctl.h>
43
44 #include <dev/nand/nand.h>
45 #include <dev/nand/nandbus.h>
46 #include <dev/nand/nand_ecc_pos.h>
47 #include "nfc_if.h"
48 #include "nand_if.h"
49 #include "nandbus_if.h"
50 #include <machine/stdarg.h>
51
52 #define NAND_RESET_DELAY        1000    /* tRST */
53 #define NAND_ERASE_DELAY        3000    /* tBERS */
54 #define NAND_PROG_DELAY         700     /* tPROG */
55 #define NAND_READ_DELAY         50      /* tR */
56
57 #define BIT0(x) ((x) & 0x1)
58 #define BIT1(x) (BIT0(x >> 1))
59 #define BIT2(x) (BIT0(x >> 2))
60 #define BIT3(x) (BIT0(x >> 3))
61 #define BIT4(x) (BIT0(x >> 4))
62 #define BIT5(x) (BIT0(x >> 5))
63 #define BIT6(x) (BIT0(x >> 6))
64 #define BIT7(x) (BIT0(x >> 7))
65
66 #define SOFTECC_SIZE            256
67 #define SOFTECC_BYTES           3
68
69 int nand_debug_flag = 0;
70 SYSCTL_INT(_debug, OID_AUTO, nand_debug, CTLFLAG_RWTUN, &nand_debug_flag, 0,
71     "NAND subsystem debug flag");
72
73 MALLOC_DEFINE(M_NAND, "NAND", "NAND dynamic data");
74
75 static void calculate_ecc(const uint8_t *, uint8_t *);
76 static int correct_ecc(uint8_t *, uint8_t *, uint8_t *);
77
78 void
79 nand_debug(int level, const char *fmt, ...)
80 {
81         va_list ap;
82
83         if (!(nand_debug_flag & level))
84                 return;
85         va_start(ap, fmt);
86         vprintf(fmt, ap);
87         va_end(ap);
88         printf("\n");
89 }
90
91 void
92 nand_init(struct nand_softc *nand, device_t dev, int ecc_mode,
93     int ecc_bytes, int ecc_size, uint16_t *eccposition, char *cdev_name)
94 {
95
96         nand->ecc.eccmode = ecc_mode;
97         nand->chip_cdev_name = cdev_name;
98
99         if (ecc_mode == NAND_ECC_SOFT) {
100                 nand->ecc.eccbytes = SOFTECC_BYTES;
101                 nand->ecc.eccsize = SOFTECC_SIZE;
102         } else if (ecc_mode != NAND_ECC_NONE) {
103                 nand->ecc.eccbytes = ecc_bytes;
104                 nand->ecc.eccsize = ecc_size;
105                 if (eccposition)
106                         nand->ecc.eccpositions = eccposition;
107         }
108 }
109
110 void
111 nand_onfi_set_params(struct nand_chip *chip, struct onfi_chip_params *params)
112 {
113         struct chip_geom *cg;
114
115         cg = &chip->chip_geom;
116
117         init_chip_geom(cg, params->luns, params->blocks_per_lun,
118             params->pages_per_block, params->bytes_per_page,
119             params->spare_bytes_per_page);
120         chip->t_bers = params->t_bers;
121         chip->t_prog = params->t_prog;
122         chip->t_r = params->t_r;
123         chip->t_ccs = params->t_ccs;
124
125         if (params->features & ONFI_FEAT_16BIT)
126                 chip->flags |= NAND_16_BIT;
127 }
128
129 void
130 nand_set_params(struct nand_chip *chip, struct nand_params *params)
131 {
132         struct chip_geom *cg;
133         uint32_t blocks_per_chip;
134
135         cg = &chip->chip_geom;
136         blocks_per_chip = (params->chip_size << 20) /
137             (params->page_size * params->pages_per_block);
138
139         init_chip_geom(cg, 1, blocks_per_chip,
140             params->pages_per_block, params->page_size,
141             params->oob_size);
142
143         chip->t_bers = NAND_ERASE_DELAY;
144         chip->t_prog = NAND_PROG_DELAY;
145         chip->t_r = NAND_READ_DELAY;
146         chip->t_ccs = 0;
147
148         if (params->flags & NAND_16_BIT)
149                 chip->flags |= NAND_16_BIT;
150 }
151
152 int
153 nand_init_stat(struct nand_chip *chip)
154 {
155         struct block_stat *blk_stat;
156         struct page_stat *pg_stat;
157         struct chip_geom *cg;
158         uint32_t blks, pgs;
159
160         cg = &chip->chip_geom;
161         blks = cg->blks_per_lun * cg->luns;
162         blk_stat = malloc(sizeof(struct block_stat) * blks, M_NAND,
163             M_WAITOK | M_ZERO);
164         if (!blk_stat)
165                 return (ENOMEM);
166
167         pgs = blks * cg->pgs_per_blk;
168         pg_stat = malloc(sizeof(struct page_stat) * pgs, M_NAND,
169             M_WAITOK | M_ZERO);
170         if (!pg_stat) {
171                 free(blk_stat, M_NAND);
172                 return (ENOMEM);
173         }
174
175         chip->blk_stat = blk_stat;
176         chip->pg_stat = pg_stat;
177
178         return (0);
179 }
180
181 void
182 nand_destroy_stat(struct nand_chip *chip)
183 {
184
185         free(chip->pg_stat, M_NAND);
186         free(chip->blk_stat, M_NAND);
187 }
188
189 int
190 init_chip_geom(struct chip_geom *cg, uint32_t luns, uint32_t blks_per_lun,
191     uint32_t pgs_per_blk, uint32_t pg_size, uint32_t oob_size)
192 {
193         int shift;
194
195         if (!cg)
196                 return (-1);
197
198         cg->luns = luns;
199         cg->blks_per_lun = blks_per_lun;
200         cg->blks_per_chip = blks_per_lun * luns;
201         cg->pgs_per_blk = pgs_per_blk;
202
203         cg->page_size = pg_size;
204         cg->oob_size = oob_size;
205         cg->block_size = cg->page_size * cg->pgs_per_blk;
206         cg->chip_size = cg->block_size * cg->blks_per_chip;
207
208         shift = fls(cg->pgs_per_blk - 1);
209         cg->pg_mask = (1 << shift) - 1;
210         cg->blk_shift = shift;
211
212         if (cg->blks_per_lun > 0) {
213                 shift = fls(cg->blks_per_lun - 1);
214                 cg->blk_mask = ((1 << shift) - 1) << cg->blk_shift;
215         } else {
216                 shift = 0;
217                 cg->blk_mask = 0;
218         }
219
220         cg->lun_shift = shift + cg->blk_shift;
221         shift = fls(cg->luns - 1);
222         cg->lun_mask = ((1 << shift) - 1) << cg->lun_shift;
223
224         nand_debug(NDBG_NAND, "Masks: lun 0x%x blk 0x%x page 0x%x\n"
225             "Shifts: lun %d blk %d",
226             cg->lun_mask, cg->blk_mask, cg->pg_mask,
227             cg->lun_shift, cg->blk_shift);
228
229         return (0);
230 }
231
232 int
233 nand_row_to_blkpg(struct chip_geom *cg, uint32_t row, uint32_t *lun,
234     uint32_t *blk, uint32_t *pg)
235 {
236
237         if (!cg || !lun || !blk || !pg)
238                 return (-1);
239
240         if (row & ~(cg->lun_mask | cg->blk_mask | cg->pg_mask)) {
241                 nand_debug(NDBG_NAND,"Address out of bounds\n");
242                 return (-1);
243         }
244
245         *lun = (row & cg->lun_mask) >> cg->lun_shift;
246         *blk = (row & cg->blk_mask) >> cg->blk_shift;
247         *pg = (row & cg->pg_mask);
248
249         nand_debug(NDBG_NAND,"address %x-%x-%x\n", *lun, *blk, *pg);
250
251         return (0);
252 }
253
254 int page_to_row(struct chip_geom *cg, uint32_t page, uint32_t *row)
255 {
256         uint32_t lun, block, pg_in_blk;
257
258         if (!cg || !row)
259                 return (-1);
260
261         block = page / cg->pgs_per_blk;
262         pg_in_blk = page % cg->pgs_per_blk;
263
264         lun = block / cg->blks_per_lun;
265         block = block % cg->blks_per_lun;
266
267         *row = (lun << cg->lun_shift) & cg->lun_mask;
268         *row |= ((block << cg->blk_shift) & cg->blk_mask);
269         *row |= (pg_in_blk & cg->pg_mask);
270
271         return (0);
272 }
273
274 int
275 nand_check_page_boundary(struct nand_chip *chip, uint32_t page)
276 {
277         struct chip_geom* cg;
278
279         cg = &chip->chip_geom;
280         if (page >= (cg->pgs_per_blk * cg->blks_per_lun * cg->luns)) {
281                 nand_debug(NDBG_GEN,"%s: page number too big %#x\n",
282                     __func__, page);
283                 return (1);
284         }
285
286         return (0);
287 }
288
289 void
290 nand_get_chip_param(struct nand_chip *chip, struct chip_param_io *param)
291 {
292         struct chip_geom *cg;
293
294         cg = &chip->chip_geom;
295         param->page_size = cg->page_size;
296         param->oob_size = cg->oob_size;
297
298         param->blocks = cg->blks_per_lun * cg->luns;
299         param->pages_per_block = cg->pgs_per_blk;
300 }
301
302 static uint16_t *
303 default_software_ecc_positions(struct nand_chip *chip)
304 {
305         /* If positions have been set already, use them. */
306         if (chip->nand->ecc.eccpositions)
307                 return (chip->nand->ecc.eccpositions);
308
309         /*
310          * XXX Note that the following logic isn't really sufficient, especially
311          * in the ONFI case where the number of ECC bytes can be dictated by
312          * values in the parameters page, and that could lead to needing more
313          * byte positions than exist within the tables of software-ecc defaults.
314          */
315         if (chip->chip_geom.oob_size >= 128)
316                 return (default_software_ecc_positions_128);
317         if (chip->chip_geom.oob_size >= 64)
318                 return (default_software_ecc_positions_64);
319         else if (chip->chip_geom.oob_size >= 16)
320                 return (default_software_ecc_positions_16);
321
322         return (NULL);
323 }
324
325 static void
326 calculate_ecc(const uint8_t *buf, uint8_t *ecc)
327 {
328         uint8_t p8, byte;
329         int i;
330
331         memset(ecc, 0, 3);
332
333         for (i = 0; i < 256; i++) {
334                 byte = buf[i];
335                 ecc[0] ^= (BIT0(byte) ^ BIT2(byte) ^ BIT4(byte) ^
336                     BIT6(byte)) << 2;
337                 ecc[0] ^= (BIT1(byte) ^ BIT3(byte) ^ BIT5(byte) ^
338                     BIT7(byte)) << 3;
339                 ecc[0] ^= (BIT0(byte) ^ BIT1(byte) ^ BIT4(byte) ^
340                     BIT5(byte)) << 4;
341                 ecc[0] ^= (BIT2(byte) ^ BIT3(byte) ^ BIT6(byte) ^
342                     BIT7(byte)) << 5;
343                 ecc[0] ^= (BIT0(byte) ^ BIT1(byte) ^ BIT2(byte) ^
344                     BIT3(byte)) << 6;
345                 ecc[0] ^= (BIT4(byte) ^ BIT5(byte) ^ BIT6(byte) ^
346                     BIT7(byte)) << 7;
347
348                 p8 = BIT0(byte) ^ BIT1(byte) ^ BIT2(byte) ^
349                     BIT3(byte) ^ BIT4(byte) ^ BIT5(byte) ^ BIT6(byte) ^
350                     BIT7(byte);
351
352                 if (p8) {
353                         ecc[2] ^= (0x1 << BIT0(i));
354                         ecc[2] ^= (0x4 << BIT1(i));
355                         ecc[2] ^= (0x10 << BIT2(i));
356                         ecc[2] ^= (0x40 << BIT3(i));
357
358                         ecc[1] ^= (0x1 << BIT4(i));
359                         ecc[1] ^= (0x4 << BIT5(i));
360                         ecc[1] ^= (0x10 << BIT6(i));
361                         ecc[1] ^= (0x40 << BIT7(i));
362                 }
363         }
364         ecc[0] = ~ecc[0];
365         ecc[1] = ~ecc[1];
366         ecc[2] = ~ecc[2];
367         ecc[0] |= 3;
368 }
369
370 static int
371 correct_ecc(uint8_t *buf, uint8_t *calc_ecc, uint8_t *read_ecc)
372 {
373         uint8_t ecc0, ecc1, ecc2, onesnum, bit, byte;
374         uint16_t addr = 0;
375
376         ecc0 = calc_ecc[0] ^ read_ecc[0];
377         ecc1 = calc_ecc[1] ^ read_ecc[1];
378         ecc2 = calc_ecc[2] ^ read_ecc[2];
379
380         if (!ecc0 && !ecc1 && !ecc2)
381                 return (ECC_OK);
382
383         addr = BIT3(ecc0) | (BIT5(ecc0) << 1) | (BIT7(ecc0) << 2);
384         addr |= (BIT1(ecc2) << 3) | (BIT3(ecc2) << 4) |
385             (BIT5(ecc2) << 5) |  (BIT7(ecc2) << 6);
386         addr |= (BIT1(ecc1) << 7) | (BIT3(ecc1) << 8) |
387             (BIT5(ecc1) << 9) |  (BIT7(ecc1) << 10);
388
389         onesnum = 0;
390         while (ecc0 || ecc1 || ecc2) {
391                 if (ecc0 & 1)
392                         onesnum++;
393                 if (ecc1 & 1)
394                         onesnum++;
395                 if (ecc2 & 1)
396                         onesnum++;
397
398                 ecc0 >>= 1;
399                 ecc1 >>= 1;
400                 ecc2 >>= 1;
401         }
402
403         if (onesnum == 11) {
404                 /* Correctable error */
405                 bit = addr & 7;
406                 byte = addr >> 3;
407                 buf[byte] ^= (1 << bit);
408                 return (ECC_CORRECTABLE);
409         } else if (onesnum == 1) {
410                 /* ECC error */
411                 return (ECC_ERROR_ECC);
412         } else {
413                 /* Uncorrectable error */
414                 return (ECC_UNCORRECTABLE);
415         }
416
417         return (0);
418 }
419
420 int
421 nand_softecc_get(device_t dev, uint8_t *buf, int pagesize, uint8_t *ecc)
422 {
423         int steps = pagesize / SOFTECC_SIZE;
424         int i = 0, j = 0;
425
426         for (; i < (steps * SOFTECC_BYTES);
427             i += SOFTECC_BYTES, j += SOFTECC_SIZE) {
428                 calculate_ecc(&buf[j], &ecc[i]);
429         }
430
431         return (0);
432 }
433
434 int
435 nand_softecc_correct(device_t dev, uint8_t *buf, int pagesize,
436     uint8_t *readecc, uint8_t *calcecc)
437 {
438         int steps = pagesize / SOFTECC_SIZE;
439         int i = 0, j = 0, ret = 0;
440
441         for (i = 0; i < (steps * SOFTECC_BYTES);
442             i += SOFTECC_BYTES, j += SOFTECC_SIZE) {
443                 ret += correct_ecc(&buf[j], &calcecc[i], &readecc[i]);
444                 if (ret < 0)
445                         return (ret);
446         }
447
448         return (ret);
449 }
450
451 static int
452 offset_to_page(struct chip_geom *cg, uint32_t offset)
453 {
454
455         return (offset / cg->page_size);
456 }
457
458 int
459 nand_read_pages(struct nand_chip *chip, uint32_t offset, void *buf,
460     uint32_t len)
461 {
462         struct chip_geom *cg;
463         struct nand_ecc_data *eccd;
464         struct page_stat *pg_stat;
465         device_t nandbus;
466         void *oob = NULL;
467         uint8_t *ptr;
468         uint16_t *eccpos = NULL;
469         uint32_t page, num, steps = 0;
470         int i, retval = 0, needwrite;
471
472         nand_debug(NDBG_NAND,"%p read page %x[%x]", chip, offset, len);
473         cg = &chip->chip_geom;
474         eccd = &chip->nand->ecc;
475         page = offset_to_page(cg, offset);
476         num = len / cg->page_size;
477
478         if (eccd->eccmode != NAND_ECC_NONE) {
479                 steps = cg->page_size / eccd->eccsize;
480                 eccpos = default_software_ecc_positions(chip);
481                 oob = malloc(cg->oob_size, M_NAND, M_WAITOK);
482         }
483
484         nandbus = device_get_parent(chip->dev);
485         NANDBUS_LOCK(nandbus);
486         NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
487
488         ptr = (uint8_t *)buf;
489         while (num--) {
490                 pg_stat = &(chip->pg_stat[page]);
491
492                 if (NAND_READ_PAGE(chip->dev, page, ptr, cg->page_size, 0)) {
493                         retval = ENXIO;
494                         break;
495                 }
496
497                 if (eccd->eccmode != NAND_ECC_NONE) {
498                         if (NAND_GET_ECC(chip->dev, ptr, eccd->ecccalculated,
499                             &needwrite)) {
500                                 retval = ENXIO;
501                                 break;
502                         }
503                         nand_debug(NDBG_ECC,"%s: ECC calculated:",
504                             __func__);
505                         if (nand_debug_flag & NDBG_ECC)
506                                 for (i = 0; i < (eccd->eccbytes * steps); i++)
507                                         printf("%x ", eccd->ecccalculated[i]);
508
509                         nand_debug(NDBG_ECC,"\n");
510
511                         if (NAND_READ_OOB(chip->dev, page, oob, cg->oob_size,
512                             0)) {
513                                 retval = ENXIO;
514                                 break;
515                         }
516                         for (i = 0; i < (eccd->eccbytes * steps); i++)
517                                 eccd->eccread[i] = ((uint8_t *)oob)[eccpos[i]];
518
519                         nand_debug(NDBG_ECC,"%s: ECC read:", __func__);
520                         if (nand_debug_flag & NDBG_ECC)
521                                 for (i = 0; i < (eccd->eccbytes * steps); i++)
522                                         printf("%x ", eccd->eccread[i]);
523                         nand_debug(NDBG_ECC,"\n");
524
525                         retval = NAND_CORRECT_ECC(chip->dev, ptr, eccd->eccread,
526                             eccd->ecccalculated);
527
528                         nand_debug(NDBG_ECC, "NAND_CORRECT_ECC() returned %d",
529                             retval);
530
531                         if (retval == 0)
532                                 pg_stat->ecc_stat.ecc_succeded++;
533                         else if (retval > 0) {
534                                 pg_stat->ecc_stat.ecc_corrected += retval;
535                                 retval = ECC_CORRECTABLE;
536                         } else {
537                                 pg_stat->ecc_stat.ecc_failed++;
538                                 break;
539                         }
540                 }
541
542                 pg_stat->page_read++;
543                 page++;
544                 ptr += cg->page_size;
545         }
546
547         NANDBUS_UNLOCK(nandbus);
548
549         if (oob)
550                 free(oob, M_NAND);
551
552         return (retval);
553 }
554
555 int
556 nand_read_pages_raw(struct nand_chip *chip, uint32_t offset, void *buf,
557     uint32_t len)
558 {
559         struct chip_geom *cg;
560         device_t nandbus;
561         uint8_t *ptr;
562         uint32_t page, num, end, begin = 0, begin_off;
563         int retval = 0;
564
565         cg = &chip->chip_geom;
566         page = offset_to_page(cg, offset);
567         begin_off = offset - page * cg->page_size;
568         if (begin_off) {
569                 begin = cg->page_size - begin_off;
570                 len -= begin;
571         }
572         num = len / cg->page_size;
573         end = len % cg->page_size;
574
575         nandbus = device_get_parent(chip->dev);
576         NANDBUS_LOCK(nandbus);
577         NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
578
579         ptr = (uint8_t *)buf;
580         if (begin_off) {
581                 if (NAND_READ_PAGE(chip->dev, page, ptr, begin, begin_off)) {
582                         NANDBUS_UNLOCK(nandbus);
583                         return (ENXIO);
584                 }
585
586                 page++;
587                 ptr += begin;
588         }
589
590         while (num--) {
591                 if (NAND_READ_PAGE(chip->dev, page, ptr, cg->page_size, 0)) {
592                         NANDBUS_UNLOCK(nandbus);
593                         return (ENXIO);
594                 }
595
596                 page++;
597                 ptr += cg->page_size;
598         }
599
600         if (end)
601                 if (NAND_READ_PAGE(chip->dev, page, ptr, end, 0)) {
602                         NANDBUS_UNLOCK(nandbus);
603                         return (ENXIO);
604                 }
605
606         NANDBUS_UNLOCK(nandbus);
607
608         return (retval);
609 }
610
611
612 int
613 nand_prog_pages(struct nand_chip *chip, uint32_t offset, uint8_t *buf,
614     uint32_t len)
615 {
616         struct chip_geom *cg;
617         struct page_stat *pg_stat;
618         struct nand_ecc_data *eccd;
619         device_t nandbus;
620         uint32_t page, num;
621         uint8_t *oob = NULL;
622         uint16_t *eccpos = NULL;
623         int steps = 0, i, needwrite, err = 0;
624
625         nand_debug(NDBG_NAND,"%p prog page %x[%x]", chip, offset, len);
626
627         eccd = &chip->nand->ecc;
628         cg = &chip->chip_geom;
629         page = offset_to_page(cg, offset);
630         num = len / cg->page_size;
631
632         if (eccd->eccmode != NAND_ECC_NONE) {
633                 steps = cg->page_size / eccd->eccsize;
634                 oob = malloc(cg->oob_size, M_NAND, M_WAITOK);
635                 eccpos = default_software_ecc_positions(chip);
636         }
637
638         nandbus = device_get_parent(chip->dev);
639         NANDBUS_LOCK(nandbus);
640         NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
641
642         while (num--) {
643                 if (NAND_PROGRAM_PAGE(chip->dev, page, buf, cg->page_size, 0)) {
644                         err = ENXIO;
645                         break;
646                 }
647
648                 if (eccd->eccmode != NAND_ECC_NONE) {
649                         if (NAND_GET_ECC(chip->dev, buf, &eccd->ecccalculated,
650                             &needwrite)) {
651                                 err = ENXIO;
652                                 break;
653                         }
654                         nand_debug(NDBG_ECC,"ECC calculated:");
655                         if (nand_debug_flag & NDBG_ECC)
656                                 for (i = 0; i < (eccd->eccbytes * steps); i++)
657                                         printf("%x ", eccd->ecccalculated[i]);
658
659                         nand_debug(NDBG_ECC,"\n");
660
661                         if (needwrite) {
662                                 if (NAND_READ_OOB(chip->dev, page, oob, cg->oob_size,
663                                     0)) {
664                                         err = ENXIO;
665                                         break;
666                                 }
667
668                                 for (i = 0; i < (eccd->eccbytes * steps); i++)
669                                         oob[eccpos[i]] = eccd->ecccalculated[i];
670
671                                 if (NAND_PROGRAM_OOB(chip->dev, page, oob,
672                                     cg->oob_size, 0)) {
673                                         err = ENXIO;
674                                         break;
675                                 }
676                         }
677                 }
678
679                 pg_stat = &(chip->pg_stat[page]);
680                 pg_stat->page_written++;
681
682                 page++;
683                 buf += cg->page_size;
684         }
685
686         NANDBUS_UNLOCK(nandbus);
687
688         if (oob)
689                 free(oob, M_NAND);
690
691         return (err);
692 }
693
694 int
695 nand_prog_pages_raw(struct nand_chip *chip, uint32_t offset, void *buf,
696     uint32_t len)
697 {
698         struct chip_geom *cg;
699         device_t nandbus;
700         uint8_t *ptr;
701         uint32_t page, num, end, begin = 0, begin_off;
702         int retval = 0;
703
704         cg = &chip->chip_geom;
705         page = offset_to_page(cg, offset);
706         begin_off = offset - page * cg->page_size;
707         if (begin_off) {
708                 begin = cg->page_size - begin_off;
709                 len -= begin;
710         }
711         num = len / cg->page_size;
712         end = len % cg->page_size;
713
714         nandbus = device_get_parent(chip->dev);
715         NANDBUS_LOCK(nandbus);
716         NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
717
718         ptr = (uint8_t *)buf;
719         if (begin_off) {
720                 if (NAND_PROGRAM_PAGE(chip->dev, page, ptr, begin, begin_off)) {
721                         NANDBUS_UNLOCK(nandbus);
722                         return (ENXIO);
723                 }
724
725                 page++;
726                 ptr += begin;
727         }
728
729         while (num--) {
730                 if (NAND_PROGRAM_PAGE(chip->dev, page, ptr, cg->page_size, 0)) {
731                         NANDBUS_UNLOCK(nandbus);
732                         return (ENXIO);
733                 }
734
735                 page++;
736                 ptr += cg->page_size;
737         }
738
739         if (end)
740                 retval = NAND_PROGRAM_PAGE(chip->dev, page, ptr, end, 0);
741
742         NANDBUS_UNLOCK(nandbus);
743
744         return (retval);
745 }
746
747 int
748 nand_read_oob(struct nand_chip *chip, uint32_t page, void *buf,
749     uint32_t len)
750 {
751         device_t nandbus;
752         int retval = 0;
753
754         nandbus = device_get_parent(chip->dev);
755         NANDBUS_LOCK(nandbus);
756         NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
757
758         retval = NAND_READ_OOB(chip->dev, page, buf, len, 0);
759
760         NANDBUS_UNLOCK(nandbus);
761
762         return (retval);
763 }
764
765
766 int
767 nand_prog_oob(struct nand_chip *chip, uint32_t page, void *buf,
768     uint32_t len)
769 {
770         device_t nandbus;
771         int retval = 0;
772
773         nandbus = device_get_parent(chip->dev);
774         NANDBUS_LOCK(nandbus);
775         NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
776
777         retval = NAND_PROGRAM_OOB(chip->dev, page, buf, len, 0);
778
779         NANDBUS_UNLOCK(nandbus);
780
781         return (retval);
782 }
783
784 int
785 nand_erase_blocks(struct nand_chip *chip, off_t offset, size_t len)
786 {
787         device_t nandbus;
788         struct chip_geom *cg;
789         uint32_t block, num_blocks;
790         int err = 0;
791
792         cg = &chip->chip_geom;
793         if ((offset % cg->block_size) || (len % cg->block_size))
794                 return (EINVAL);
795
796         block = offset / cg->block_size;
797         num_blocks = len / cg->block_size;
798         nand_debug(NDBG_NAND,"%p erase blocks %d[%d]", chip, block, num_blocks);
799
800         nandbus = device_get_parent(chip->dev);
801         NANDBUS_LOCK(nandbus);
802         NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
803
804         while (num_blocks--) {
805                 if (!nand_check_bad_block(chip, block)) {
806                         if (NAND_ERASE_BLOCK(chip->dev, block)) {
807                                 nand_debug(NDBG_NAND,"%p erase blocks %d error",
808                                     chip, block);
809                                 nand_mark_bad_block(chip, block);
810                                 err = ENXIO;
811                         }
812                 } else
813                         err = ENXIO;
814
815                 block++;
816         }
817
818         NANDBUS_UNLOCK(nandbus);
819
820         if (err)
821                 nand_update_bbt(chip);
822
823         return (err);
824 }
825
826 MODULE_VERSION(nand, 1);