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