.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright © 2004 Texas Instruments, Jian Zhang <jzhang@ti.com> |
---|
3 | 4 | * Copyright © 2004 Micron Technology Inc. |
---|
4 | 5 | * Copyright © 2004 David Brownell |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify |
---|
7 | | - * it under the terms of the GNU General Public License version 2 as |
---|
8 | | - * published by the Free Software Foundation. |
---|
9 | 6 | */ |
---|
10 | 7 | |
---|
11 | 8 | #include <linux/platform_device.h> |
---|
.. | .. |
---|
240 | 237 | |
---|
241 | 238 | /** |
---|
242 | 239 | * omap_hwcontrol - hardware specific access to control-lines |
---|
243 | | - * @mtd: MTD device structure |
---|
| 240 | + * @chip: NAND chip object |
---|
244 | 241 | * @cmd: command to device |
---|
245 | 242 | * @ctrl: |
---|
246 | 243 | * NAND_NCE: bit 0 -> don't care |
---|
.. | .. |
---|
249 | 246 | * |
---|
250 | 247 | * NOTE: boards may use different bits for these!! |
---|
251 | 248 | */ |
---|
252 | | -static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) |
---|
| 249 | +static void omap_hwcontrol(struct nand_chip *chip, int cmd, unsigned int ctrl) |
---|
253 | 250 | { |
---|
254 | | - struct omap_nand_info *info = mtd_to_omap(mtd); |
---|
| 251 | + struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip)); |
---|
255 | 252 | |
---|
256 | 253 | if (cmd != NAND_CMD_NONE) { |
---|
257 | 254 | if (ctrl & NAND_CLE) |
---|
.. | .. |
---|
275 | 272 | { |
---|
276 | 273 | struct nand_chip *nand = mtd_to_nand(mtd); |
---|
277 | 274 | |
---|
278 | | - ioread8_rep(nand->IO_ADDR_R, buf, len); |
---|
| 275 | + ioread8_rep(nand->legacy.IO_ADDR_R, buf, len); |
---|
279 | 276 | } |
---|
280 | 277 | |
---|
281 | 278 | /** |
---|
.. | .. |
---|
291 | 288 | bool status; |
---|
292 | 289 | |
---|
293 | 290 | while (len--) { |
---|
294 | | - iowrite8(*p++, info->nand.IO_ADDR_W); |
---|
| 291 | + iowrite8(*p++, info->nand.legacy.IO_ADDR_W); |
---|
295 | 292 | /* wait until buffer is available for write */ |
---|
296 | 293 | do { |
---|
297 | 294 | status = info->ops->nand_writebuffer_empty(); |
---|
.. | .. |
---|
309 | 306 | { |
---|
310 | 307 | struct nand_chip *nand = mtd_to_nand(mtd); |
---|
311 | 308 | |
---|
312 | | - ioread16_rep(nand->IO_ADDR_R, buf, len / 2); |
---|
| 309 | + ioread16_rep(nand->legacy.IO_ADDR_R, buf, len / 2); |
---|
313 | 310 | } |
---|
314 | 311 | |
---|
315 | 312 | /** |
---|
.. | .. |
---|
327 | 324 | len >>= 1; |
---|
328 | 325 | |
---|
329 | 326 | while (len--) { |
---|
330 | | - iowrite16(*p++, info->nand.IO_ADDR_W); |
---|
| 327 | + iowrite16(*p++, info->nand.legacy.IO_ADDR_W); |
---|
331 | 328 | /* wait until buffer is available for write */ |
---|
332 | 329 | do { |
---|
333 | 330 | status = info->ops->nand_writebuffer_empty(); |
---|
.. | .. |
---|
337 | 334 | |
---|
338 | 335 | /** |
---|
339 | 336 | * omap_read_buf_pref - read data from NAND controller into buffer |
---|
340 | | - * @mtd: MTD device structure |
---|
| 337 | + * @chip: NAND chip object |
---|
341 | 338 | * @buf: buffer to store date |
---|
342 | 339 | * @len: number of bytes to read |
---|
343 | 340 | */ |
---|
344 | | -static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) |
---|
| 341 | +static void omap_read_buf_pref(struct nand_chip *chip, u_char *buf, int len) |
---|
345 | 342 | { |
---|
| 343 | + struct mtd_info *mtd = nand_to_mtd(chip); |
---|
346 | 344 | struct omap_nand_info *info = mtd_to_omap(mtd); |
---|
347 | 345 | uint32_t r_count = 0; |
---|
348 | 346 | int ret = 0; |
---|
.. | .. |
---|
372 | 370 | r_count = readl(info->reg.gpmc_prefetch_status); |
---|
373 | 371 | r_count = PREFETCH_STATUS_FIFO_CNT(r_count); |
---|
374 | 372 | r_count = r_count >> 2; |
---|
375 | | - ioread32_rep(info->nand.IO_ADDR_R, p, r_count); |
---|
| 373 | + ioread32_rep(info->nand.legacy.IO_ADDR_R, p, r_count); |
---|
376 | 374 | p += r_count; |
---|
377 | 375 | len -= r_count << 2; |
---|
378 | 376 | } while (len); |
---|
.. | .. |
---|
383 | 381 | |
---|
384 | 382 | /** |
---|
385 | 383 | * omap_write_buf_pref - write buffer to NAND controller |
---|
386 | | - * @mtd: MTD device structure |
---|
| 384 | + * @chip: NAND chip object |
---|
387 | 385 | * @buf: data buffer |
---|
388 | 386 | * @len: number of bytes to write |
---|
389 | 387 | */ |
---|
390 | | -static void omap_write_buf_pref(struct mtd_info *mtd, |
---|
391 | | - const u_char *buf, int len) |
---|
| 388 | +static void omap_write_buf_pref(struct nand_chip *chip, const u_char *buf, |
---|
| 389 | + int len) |
---|
392 | 390 | { |
---|
| 391 | + struct mtd_info *mtd = nand_to_mtd(chip); |
---|
393 | 392 | struct omap_nand_info *info = mtd_to_omap(mtd); |
---|
394 | 393 | uint32_t w_count = 0; |
---|
395 | 394 | int i = 0, ret = 0; |
---|
.. | .. |
---|
399 | 398 | |
---|
400 | 399 | /* take care of subpage writes */ |
---|
401 | 400 | if (len % 2 != 0) { |
---|
402 | | - writeb(*buf, info->nand.IO_ADDR_W); |
---|
| 401 | + writeb(*buf, info->nand.legacy.IO_ADDR_W); |
---|
403 | 402 | p = (u16 *)(buf + 1); |
---|
404 | 403 | len--; |
---|
405 | 404 | } |
---|
.. | .. |
---|
419 | 418 | w_count = PREFETCH_STATUS_FIFO_CNT(w_count); |
---|
420 | 419 | w_count = w_count >> 1; |
---|
421 | 420 | for (i = 0; (i < w_count) && len; i++, len -= 2) |
---|
422 | | - iowrite16(*p++, info->nand.IO_ADDR_W); |
---|
| 421 | + iowrite16(*p++, info->nand.legacy.IO_ADDR_W); |
---|
423 | 422 | } |
---|
424 | 423 | /* wait for data to flushed-out before reset the prefetch */ |
---|
425 | 424 | tim = 0; |
---|
.. | .. |
---|
528 | 527 | |
---|
529 | 528 | /** |
---|
530 | 529 | * omap_read_buf_dma_pref - read data from NAND controller into buffer |
---|
531 | | - * @mtd: MTD device structure |
---|
| 530 | + * @chip: NAND chip object |
---|
532 | 531 | * @buf: buffer to store date |
---|
533 | 532 | * @len: number of bytes to read |
---|
534 | 533 | */ |
---|
535 | | -static void omap_read_buf_dma_pref(struct mtd_info *mtd, u_char *buf, int len) |
---|
| 534 | +static void omap_read_buf_dma_pref(struct nand_chip *chip, u_char *buf, |
---|
| 535 | + int len) |
---|
536 | 536 | { |
---|
| 537 | + struct mtd_info *mtd = nand_to_mtd(chip); |
---|
| 538 | + |
---|
537 | 539 | if (len <= mtd->oobsize) |
---|
538 | | - omap_read_buf_pref(mtd, buf, len); |
---|
| 540 | + omap_read_buf_pref(chip, buf, len); |
---|
539 | 541 | else |
---|
540 | 542 | /* start transfer in DMA mode */ |
---|
541 | 543 | omap_nand_dma_transfer(mtd, buf, len, 0x0); |
---|
.. | .. |
---|
543 | 545 | |
---|
544 | 546 | /** |
---|
545 | 547 | * omap_write_buf_dma_pref - write buffer to NAND controller |
---|
546 | | - * @mtd: MTD device structure |
---|
| 548 | + * @chip: NAND chip object |
---|
547 | 549 | * @buf: data buffer |
---|
548 | 550 | * @len: number of bytes to write |
---|
549 | 551 | */ |
---|
550 | | -static void omap_write_buf_dma_pref(struct mtd_info *mtd, |
---|
551 | | - const u_char *buf, int len) |
---|
| 552 | +static void omap_write_buf_dma_pref(struct nand_chip *chip, const u_char *buf, |
---|
| 553 | + int len) |
---|
552 | 554 | { |
---|
| 555 | + struct mtd_info *mtd = nand_to_mtd(chip); |
---|
| 556 | + |
---|
553 | 557 | if (len <= mtd->oobsize) |
---|
554 | | - omap_write_buf_pref(mtd, buf, len); |
---|
| 558 | + omap_write_buf_pref(chip, buf, len); |
---|
555 | 559 | else |
---|
556 | 560 | /* start transfer in DMA mode */ |
---|
557 | | - omap_nand_dma_transfer(mtd, (u_char *) buf, len, 0x1); |
---|
| 561 | + omap_nand_dma_transfer(mtd, (u_char *)buf, len, 0x1); |
---|
558 | 562 | } |
---|
559 | 563 | |
---|
560 | 564 | /* |
---|
.. | .. |
---|
578 | 582 | bytes = info->buf_len; |
---|
579 | 583 | else if (!info->buf_len) |
---|
580 | 584 | bytes = 0; |
---|
581 | | - iowrite32_rep(info->nand.IO_ADDR_W, |
---|
582 | | - (u32 *)info->buf, bytes >> 2); |
---|
| 585 | + iowrite32_rep(info->nand.legacy.IO_ADDR_W, (u32 *)info->buf, |
---|
| 586 | + bytes >> 2); |
---|
583 | 587 | info->buf = info->buf + bytes; |
---|
584 | 588 | info->buf_len -= bytes; |
---|
585 | 589 | |
---|
586 | 590 | } else { |
---|
587 | | - ioread32_rep(info->nand.IO_ADDR_R, |
---|
588 | | - (u32 *)info->buf, bytes >> 2); |
---|
| 591 | + ioread32_rep(info->nand.legacy.IO_ADDR_R, (u32 *)info->buf, |
---|
| 592 | + bytes >> 2); |
---|
589 | 593 | info->buf = info->buf + bytes; |
---|
590 | 594 | |
---|
591 | 595 | if (this_irq == info->gpmc_irq_count) |
---|
.. | .. |
---|
605 | 609 | |
---|
606 | 610 | /* |
---|
607 | 611 | * omap_read_buf_irq_pref - read data from NAND controller into buffer |
---|
608 | | - * @mtd: MTD device structure |
---|
| 612 | + * @chip: NAND chip object |
---|
609 | 613 | * @buf: buffer to store date |
---|
610 | 614 | * @len: number of bytes to read |
---|
611 | 615 | */ |
---|
612 | | -static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len) |
---|
| 616 | +static void omap_read_buf_irq_pref(struct nand_chip *chip, u_char *buf, |
---|
| 617 | + int len) |
---|
613 | 618 | { |
---|
| 619 | + struct mtd_info *mtd = nand_to_mtd(chip); |
---|
614 | 620 | struct omap_nand_info *info = mtd_to_omap(mtd); |
---|
615 | 621 | int ret = 0; |
---|
616 | 622 | |
---|
617 | 623 | if (len <= mtd->oobsize) { |
---|
618 | | - omap_read_buf_pref(mtd, buf, len); |
---|
| 624 | + omap_read_buf_pref(chip, buf, len); |
---|
619 | 625 | return; |
---|
620 | 626 | } |
---|
621 | 627 | |
---|
.. | .. |
---|
651 | 657 | |
---|
652 | 658 | /* |
---|
653 | 659 | * omap_write_buf_irq_pref - write buffer to NAND controller |
---|
654 | | - * @mtd: MTD device structure |
---|
| 660 | + * @chip: NAND chip object |
---|
655 | 661 | * @buf: data buffer |
---|
656 | 662 | * @len: number of bytes to write |
---|
657 | 663 | */ |
---|
658 | | -static void omap_write_buf_irq_pref(struct mtd_info *mtd, |
---|
659 | | - const u_char *buf, int len) |
---|
| 664 | +static void omap_write_buf_irq_pref(struct nand_chip *chip, const u_char *buf, |
---|
| 665 | + int len) |
---|
660 | 666 | { |
---|
| 667 | + struct mtd_info *mtd = nand_to_mtd(chip); |
---|
661 | 668 | struct omap_nand_info *info = mtd_to_omap(mtd); |
---|
662 | 669 | int ret = 0; |
---|
663 | 670 | unsigned long tim, limit; |
---|
664 | 671 | u32 val; |
---|
665 | 672 | |
---|
666 | 673 | if (len <= mtd->oobsize) { |
---|
667 | | - omap_write_buf_pref(mtd, buf, len); |
---|
| 674 | + omap_write_buf_pref(chip, buf, len); |
---|
668 | 675 | return; |
---|
669 | 676 | } |
---|
670 | 677 | |
---|
.. | .. |
---|
857 | 864 | |
---|
858 | 865 | /** |
---|
859 | 866 | * omap_correct_data - Compares the ECC read with HW generated ECC |
---|
860 | | - * @mtd: MTD device structure |
---|
| 867 | + * @chip: NAND chip object |
---|
861 | 868 | * @dat: page data |
---|
862 | 869 | * @read_ecc: ecc read from nand flash |
---|
863 | 870 | * @calc_ecc: ecc read from HW ECC registers |
---|
.. | .. |
---|
869 | 876 | * corrected errors is returned. If uncorrectable errors exist, %-1 is |
---|
870 | 877 | * returned. |
---|
871 | 878 | */ |
---|
872 | | -static int omap_correct_data(struct mtd_info *mtd, u_char *dat, |
---|
873 | | - u_char *read_ecc, u_char *calc_ecc) |
---|
| 879 | +static int omap_correct_data(struct nand_chip *chip, u_char *dat, |
---|
| 880 | + u_char *read_ecc, u_char *calc_ecc) |
---|
874 | 881 | { |
---|
875 | | - struct omap_nand_info *info = mtd_to_omap(mtd); |
---|
| 882 | + struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip)); |
---|
876 | 883 | int blockCnt = 0, i = 0, ret = 0; |
---|
877 | 884 | int stat = 0; |
---|
878 | 885 | |
---|
879 | 886 | /* Ex NAND_ECC_HW12_2048 */ |
---|
880 | | - if ((info->nand.ecc.mode == NAND_ECC_HW) && |
---|
881 | | - (info->nand.ecc.size == 2048)) |
---|
| 887 | + if (info->nand.ecc.engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST && |
---|
| 888 | + info->nand.ecc.size == 2048) |
---|
882 | 889 | blockCnt = 4; |
---|
883 | 890 | else |
---|
884 | 891 | blockCnt = 1; |
---|
.. | .. |
---|
900 | 907 | |
---|
901 | 908 | /** |
---|
902 | 909 | * omap_calcuate_ecc - Generate non-inverted ECC bytes. |
---|
903 | | - * @mtd: MTD device structure |
---|
| 910 | + * @chip: NAND chip object |
---|
904 | 911 | * @dat: The pointer to data on which ecc is computed |
---|
905 | 912 | * @ecc_code: The ecc_code buffer |
---|
906 | 913 | * |
---|
.. | .. |
---|
910 | 917 | * an erased page will produce an ECC mismatch between generated and read |
---|
911 | 918 | * ECC bytes that has to be dealt with separately. |
---|
912 | 919 | */ |
---|
913 | | -static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat, |
---|
914 | | - u_char *ecc_code) |
---|
| 920 | +static int omap_calculate_ecc(struct nand_chip *chip, const u_char *dat, |
---|
| 921 | + u_char *ecc_code) |
---|
915 | 922 | { |
---|
916 | | - struct omap_nand_info *info = mtd_to_omap(mtd); |
---|
| 923 | + struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip)); |
---|
917 | 924 | u32 val; |
---|
918 | 925 | |
---|
919 | 926 | val = readl(info->reg.gpmc_ecc_config); |
---|
.. | .. |
---|
935 | 942 | * @mtd: MTD device structure |
---|
936 | 943 | * @mode: Read/Write mode |
---|
937 | 944 | */ |
---|
938 | | -static void omap_enable_hwecc(struct mtd_info *mtd, int mode) |
---|
| 945 | +static void omap_enable_hwecc(struct nand_chip *chip, int mode) |
---|
939 | 946 | { |
---|
940 | | - struct omap_nand_info *info = mtd_to_omap(mtd); |
---|
941 | | - struct nand_chip *chip = mtd_to_nand(mtd); |
---|
| 947 | + struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip)); |
---|
942 | 948 | unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0; |
---|
943 | 949 | u32 val; |
---|
944 | 950 | |
---|
.. | .. |
---|
972 | 978 | |
---|
973 | 979 | /** |
---|
974 | 980 | * omap_wait - wait until the command is done |
---|
975 | | - * @mtd: MTD device structure |
---|
976 | | - * @chip: NAND Chip structure |
---|
| 981 | + * @this: NAND Chip structure |
---|
977 | 982 | * |
---|
978 | 983 | * Wait function is called during Program and erase operations and |
---|
979 | 984 | * the way it is called from MTD layer, we should wait till the NAND |
---|
.. | .. |
---|
982 | 987 | * Erase can take up to 400ms and program up to 20ms according to |
---|
983 | 988 | * general NAND and SmartMedia specs |
---|
984 | 989 | */ |
---|
985 | | -static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) |
---|
| 990 | +static int omap_wait(struct nand_chip *this) |
---|
986 | 991 | { |
---|
987 | | - struct nand_chip *this = mtd_to_nand(mtd); |
---|
988 | | - struct omap_nand_info *info = mtd_to_omap(mtd); |
---|
| 992 | + struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(this)); |
---|
989 | 993 | unsigned long timeo = jiffies; |
---|
990 | | - int status, state = this->state; |
---|
| 994 | + int status; |
---|
991 | 995 | |
---|
992 | | - if (state == FL_ERASING) |
---|
993 | | - timeo += msecs_to_jiffies(400); |
---|
994 | | - else |
---|
995 | | - timeo += msecs_to_jiffies(20); |
---|
| 996 | + timeo += msecs_to_jiffies(400); |
---|
996 | 997 | |
---|
997 | 998 | writeb(NAND_CMD_STATUS & 0xFF, info->reg.gpmc_nand_command); |
---|
998 | 999 | while (time_before(jiffies, timeo)) { |
---|
.. | .. |
---|
1012 | 1013 | * |
---|
1013 | 1014 | * Returns true if ready and false if busy. |
---|
1014 | 1015 | */ |
---|
1015 | | -static int omap_dev_ready(struct mtd_info *mtd) |
---|
| 1016 | +static int omap_dev_ready(struct nand_chip *chip) |
---|
1016 | 1017 | { |
---|
1017 | | - struct omap_nand_info *info = mtd_to_omap(mtd); |
---|
| 1018 | + struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip)); |
---|
1018 | 1019 | |
---|
1019 | 1020 | return gpiod_get_value(info->ready_gpiod); |
---|
1020 | 1021 | } |
---|
.. | .. |
---|
1030 | 1031 | * eccsize0 = 0 (no additional protected byte in spare area) |
---|
1031 | 1032 | * eccsize1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area) |
---|
1032 | 1033 | */ |
---|
1033 | | -static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd, int mode) |
---|
| 1034 | +static void __maybe_unused omap_enable_hwecc_bch(struct nand_chip *chip, |
---|
| 1035 | + int mode) |
---|
1034 | 1036 | { |
---|
1035 | 1037 | unsigned int bch_type; |
---|
1036 | 1038 | unsigned int dev_width, nsectors; |
---|
1037 | | - struct omap_nand_info *info = mtd_to_omap(mtd); |
---|
| 1039 | + struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip)); |
---|
1038 | 1040 | enum omap_ecc ecc_opt = info->ecc_opt; |
---|
1039 | | - struct nand_chip *chip = mtd_to_nand(mtd); |
---|
1040 | 1041 | u32 val, wr_mode; |
---|
1041 | 1042 | unsigned int ecc_size1, ecc_size0; |
---|
1042 | 1043 | |
---|
.. | .. |
---|
1256 | 1257 | |
---|
1257 | 1258 | /** |
---|
1258 | 1259 | * omap_calculate_ecc_bch_sw - ECC generator for sector for SW based correction |
---|
1259 | | - * @mtd: MTD device structure |
---|
| 1260 | + * @chip: NAND chip object |
---|
1260 | 1261 | * @dat: The pointer to data on which ecc is computed |
---|
1261 | 1262 | * @ecc_code: The ecc_code buffer |
---|
1262 | 1263 | * |
---|
.. | .. |
---|
1264 | 1265 | * when SW based correction is required as ECC is required for one sector |
---|
1265 | 1266 | * at a time. |
---|
1266 | 1267 | */ |
---|
1267 | | -static int omap_calculate_ecc_bch_sw(struct mtd_info *mtd, |
---|
| 1268 | +static int omap_calculate_ecc_bch_sw(struct nand_chip *chip, |
---|
1268 | 1269 | const u_char *dat, u_char *ecc_calc) |
---|
1269 | 1270 | { |
---|
1270 | | - return _omap_calculate_ecc_bch(mtd, dat, ecc_calc, 0); |
---|
| 1271 | + return _omap_calculate_ecc_bch(nand_to_mtd(chip), dat, ecc_calc, 0); |
---|
1271 | 1272 | } |
---|
1272 | 1273 | |
---|
1273 | 1274 | /** |
---|
.. | .. |
---|
1339 | 1340 | |
---|
1340 | 1341 | /** |
---|
1341 | 1342 | * omap_elm_correct_data - corrects page data area in case error reported |
---|
1342 | | - * @mtd: MTD device structure |
---|
| 1343 | + * @chip: NAND chip object |
---|
1343 | 1344 | * @data: page data |
---|
1344 | 1345 | * @read_ecc: ecc read from nand flash |
---|
1345 | 1346 | * @calc_ecc: ecc read from HW ECC registers |
---|
.. | .. |
---|
1348 | 1349 | * In case of non-zero ecc vector, first filter out erased-pages, and |
---|
1349 | 1350 | * then process data via ELM to detect bit-flips. |
---|
1350 | 1351 | */ |
---|
1351 | | -static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, |
---|
1352 | | - u_char *read_ecc, u_char *calc_ecc) |
---|
| 1352 | +static int omap_elm_correct_data(struct nand_chip *chip, u_char *data, |
---|
| 1353 | + u_char *read_ecc, u_char *calc_ecc) |
---|
1353 | 1354 | { |
---|
1354 | | - struct omap_nand_info *info = mtd_to_omap(mtd); |
---|
| 1355 | + struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip)); |
---|
1355 | 1356 | struct nand_ecc_ctrl *ecc = &info->nand.ecc; |
---|
1356 | 1357 | int eccsteps = info->nand.ecc.steps; |
---|
1357 | 1358 | int i , j, stat = 0; |
---|
.. | .. |
---|
1500 | 1501 | } |
---|
1501 | 1502 | |
---|
1502 | 1503 | /* Update number of correctable errors */ |
---|
1503 | | - stat += err_vec[i].error_count; |
---|
| 1504 | + stat = max_t(unsigned int, stat, err_vec[i].error_count); |
---|
1504 | 1505 | |
---|
1505 | 1506 | /* Update page data with sector size */ |
---|
1506 | 1507 | data += ecc->size; |
---|
.. | .. |
---|
1512 | 1513 | |
---|
1513 | 1514 | /** |
---|
1514 | 1515 | * omap_write_page_bch - BCH ecc based write page function for entire page |
---|
1515 | | - * @mtd: mtd info structure |
---|
1516 | 1516 | * @chip: nand chip info structure |
---|
1517 | 1517 | * @buf: data buffer |
---|
1518 | 1518 | * @oob_required: must write chip->oob_poi to OOB |
---|
.. | .. |
---|
1520 | 1520 | * |
---|
1521 | 1521 | * Custom write page method evolved to support multi sector writing in one shot |
---|
1522 | 1522 | */ |
---|
1523 | | -static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip, |
---|
1524 | | - const uint8_t *buf, int oob_required, int page) |
---|
| 1523 | +static int omap_write_page_bch(struct nand_chip *chip, const uint8_t *buf, |
---|
| 1524 | + int oob_required, int page) |
---|
1525 | 1525 | { |
---|
| 1526 | + struct mtd_info *mtd = nand_to_mtd(chip); |
---|
1526 | 1527 | int ret; |
---|
1527 | 1528 | uint8_t *ecc_calc = chip->ecc.calc_buf; |
---|
1528 | 1529 | |
---|
1529 | 1530 | nand_prog_page_begin_op(chip, page, 0, NULL, 0); |
---|
1530 | 1531 | |
---|
1531 | 1532 | /* Enable GPMC ecc engine */ |
---|
1532 | | - chip->ecc.hwctl(mtd, NAND_ECC_WRITE); |
---|
| 1533 | + chip->ecc.hwctl(chip, NAND_ECC_WRITE); |
---|
1533 | 1534 | |
---|
1534 | 1535 | /* Write data */ |
---|
1535 | | - chip->write_buf(mtd, buf, mtd->writesize); |
---|
| 1536 | + chip->legacy.write_buf(chip, buf, mtd->writesize); |
---|
1536 | 1537 | |
---|
1537 | 1538 | /* Update ecc vector from GPMC result registers */ |
---|
1538 | 1539 | omap_calculate_ecc_bch_multi(mtd, buf, &ecc_calc[0]); |
---|
.. | .. |
---|
1543 | 1544 | return ret; |
---|
1544 | 1545 | |
---|
1545 | 1546 | /* Write ecc vector to OOB area */ |
---|
1546 | | - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); |
---|
| 1547 | + chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize); |
---|
1547 | 1548 | |
---|
1548 | 1549 | return nand_prog_page_end_op(chip); |
---|
1549 | 1550 | } |
---|
1550 | 1551 | |
---|
1551 | 1552 | /** |
---|
1552 | 1553 | * omap_write_subpage_bch - BCH hardware ECC based subpage write |
---|
1553 | | - * @mtd: mtd info structure |
---|
1554 | 1554 | * @chip: nand chip info structure |
---|
1555 | 1555 | * @offset: column address of subpage within the page |
---|
1556 | 1556 | * @data_len: data length |
---|
.. | .. |
---|
1560 | 1560 | * |
---|
1561 | 1561 | * OMAP optimized subpage write method. |
---|
1562 | 1562 | */ |
---|
1563 | | -static int omap_write_subpage_bch(struct mtd_info *mtd, |
---|
1564 | | - struct nand_chip *chip, u32 offset, |
---|
| 1563 | +static int omap_write_subpage_bch(struct nand_chip *chip, u32 offset, |
---|
1565 | 1564 | u32 data_len, const u8 *buf, |
---|
1566 | 1565 | int oob_required, int page) |
---|
1567 | 1566 | { |
---|
| 1567 | + struct mtd_info *mtd = nand_to_mtd(chip); |
---|
1568 | 1568 | u8 *ecc_calc = chip->ecc.calc_buf; |
---|
1569 | 1569 | int ecc_size = chip->ecc.size; |
---|
1570 | 1570 | int ecc_bytes = chip->ecc.bytes; |
---|
.. | .. |
---|
1582 | 1582 | nand_prog_page_begin_op(chip, page, 0, NULL, 0); |
---|
1583 | 1583 | |
---|
1584 | 1584 | /* Enable GPMC ECC engine */ |
---|
1585 | | - chip->ecc.hwctl(mtd, NAND_ECC_WRITE); |
---|
| 1585 | + chip->ecc.hwctl(chip, NAND_ECC_WRITE); |
---|
1586 | 1586 | |
---|
1587 | 1587 | /* Write data */ |
---|
1588 | | - chip->write_buf(mtd, buf, mtd->writesize); |
---|
| 1588 | + chip->legacy.write_buf(chip, buf, mtd->writesize); |
---|
1589 | 1589 | |
---|
1590 | 1590 | for (step = 0; step < ecc_steps; step++) { |
---|
1591 | 1591 | /* mask ECC of un-touched subpages by padding 0xFF */ |
---|
.. | .. |
---|
1610 | 1610 | return ret; |
---|
1611 | 1611 | |
---|
1612 | 1612 | /* write OOB buffer to NAND device */ |
---|
1613 | | - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); |
---|
| 1613 | + chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize); |
---|
1614 | 1614 | |
---|
1615 | 1615 | return nand_prog_page_end_op(chip); |
---|
1616 | 1616 | } |
---|
1617 | 1617 | |
---|
1618 | 1618 | /** |
---|
1619 | 1619 | * omap_read_page_bch - BCH ecc based page read function for entire page |
---|
1620 | | - * @mtd: mtd info structure |
---|
1621 | 1620 | * @chip: nand chip info structure |
---|
1622 | 1621 | * @buf: buffer to store read data |
---|
1623 | 1622 | * @oob_required: caller requires OOB data read to chip->oob_poi |
---|
.. | .. |
---|
1630 | 1629 | * ecc engine enabled. ecc vector updated after read of OOB data. |
---|
1631 | 1630 | * For non error pages ecc vector reported as zero. |
---|
1632 | 1631 | */ |
---|
1633 | | -static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip, |
---|
1634 | | - uint8_t *buf, int oob_required, int page) |
---|
| 1632 | +static int omap_read_page_bch(struct nand_chip *chip, uint8_t *buf, |
---|
| 1633 | + int oob_required, int page) |
---|
1635 | 1634 | { |
---|
| 1635 | + struct mtd_info *mtd = nand_to_mtd(chip); |
---|
1636 | 1636 | uint8_t *ecc_calc = chip->ecc.calc_buf; |
---|
1637 | 1637 | uint8_t *ecc_code = chip->ecc.code_buf; |
---|
1638 | 1638 | int stat, ret; |
---|
.. | .. |
---|
1641 | 1641 | nand_read_page_op(chip, page, 0, NULL, 0); |
---|
1642 | 1642 | |
---|
1643 | 1643 | /* Enable GPMC ecc engine */ |
---|
1644 | | - chip->ecc.hwctl(mtd, NAND_ECC_READ); |
---|
| 1644 | + chip->ecc.hwctl(chip, NAND_ECC_READ); |
---|
1645 | 1645 | |
---|
1646 | 1646 | /* Read data */ |
---|
1647 | | - chip->read_buf(mtd, buf, mtd->writesize); |
---|
| 1647 | + chip->legacy.read_buf(chip, buf, mtd->writesize); |
---|
1648 | 1648 | |
---|
1649 | 1649 | /* Read oob bytes */ |
---|
1650 | 1650 | nand_change_read_column_op(chip, |
---|
.. | .. |
---|
1660 | 1660 | if (ret) |
---|
1661 | 1661 | return ret; |
---|
1662 | 1662 | |
---|
1663 | | - stat = chip->ecc.correct(mtd, buf, ecc_code, ecc_calc); |
---|
| 1663 | + stat = chip->ecc.correct(chip, buf, ecc_code, ecc_calc); |
---|
1664 | 1664 | |
---|
1665 | 1665 | if (stat < 0) { |
---|
1666 | 1666 | mtd->ecc_stats.failed++; |
---|
.. | .. |
---|
1722 | 1722 | break; |
---|
1723 | 1723 | } |
---|
1724 | 1724 | |
---|
1725 | | - if (ecc_needs_bch && !IS_ENABLED(CONFIG_MTD_NAND_ECC_BCH)) { |
---|
| 1725 | + if (ecc_needs_bch && !IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_BCH)) { |
---|
1726 | 1726 | dev_err(&info->pdev->dev, |
---|
1727 | | - "CONFIG_MTD_NAND_ECC_BCH not enabled\n"); |
---|
| 1727 | + "CONFIG_MTD_NAND_ECC_SW_BCH not enabled\n"); |
---|
1728 | 1728 | return false; |
---|
1729 | 1729 | } |
---|
1730 | 1730 | if (ecc_needs_omap_bch && !IS_ENABLED(CONFIG_MTD_NAND_OMAP_BCH)) { |
---|
.. | .. |
---|
1927 | 1927 | /* Re-populate low-level callbacks based on xfer modes */ |
---|
1928 | 1928 | switch (info->xfer_type) { |
---|
1929 | 1929 | case NAND_OMAP_PREFETCH_POLLED: |
---|
1930 | | - chip->read_buf = omap_read_buf_pref; |
---|
1931 | | - chip->write_buf = omap_write_buf_pref; |
---|
| 1930 | + chip->legacy.read_buf = omap_read_buf_pref; |
---|
| 1931 | + chip->legacy.write_buf = omap_write_buf_pref; |
---|
1932 | 1932 | break; |
---|
1933 | 1933 | |
---|
1934 | 1934 | case NAND_OMAP_POLLED: |
---|
.. | .. |
---|
1960 | 1960 | err); |
---|
1961 | 1961 | return err; |
---|
1962 | 1962 | } |
---|
1963 | | - chip->read_buf = omap_read_buf_dma_pref; |
---|
1964 | | - chip->write_buf = omap_write_buf_dma_pref; |
---|
| 1963 | + chip->legacy.read_buf = omap_read_buf_dma_pref; |
---|
| 1964 | + chip->legacy.write_buf = omap_write_buf_dma_pref; |
---|
1965 | 1965 | } |
---|
1966 | 1966 | break; |
---|
1967 | 1967 | |
---|
1968 | 1968 | case NAND_OMAP_PREFETCH_IRQ: |
---|
1969 | 1969 | info->gpmc_irq_fifo = platform_get_irq(info->pdev, 0); |
---|
1970 | | - if (info->gpmc_irq_fifo <= 0) { |
---|
1971 | | - dev_err(dev, "Error getting fifo IRQ\n"); |
---|
| 1970 | + if (info->gpmc_irq_fifo <= 0) |
---|
1972 | 1971 | return -ENODEV; |
---|
1973 | | - } |
---|
1974 | 1972 | err = devm_request_irq(dev, info->gpmc_irq_fifo, |
---|
1975 | 1973 | omap_nand_irq, IRQF_SHARED, |
---|
1976 | 1974 | "gpmc-nand-fifo", info); |
---|
.. | .. |
---|
1982 | 1980 | } |
---|
1983 | 1981 | |
---|
1984 | 1982 | info->gpmc_irq_count = platform_get_irq(info->pdev, 1); |
---|
1985 | | - if (info->gpmc_irq_count <= 0) { |
---|
1986 | | - dev_err(dev, "Error getting IRQ count\n"); |
---|
| 1983 | + if (info->gpmc_irq_count <= 0) |
---|
1987 | 1984 | return -ENODEV; |
---|
1988 | | - } |
---|
1989 | 1985 | err = devm_request_irq(dev, info->gpmc_irq_count, |
---|
1990 | 1986 | omap_nand_irq, IRQF_SHARED, |
---|
1991 | 1987 | "gpmc-nand-count", info); |
---|
.. | .. |
---|
1996 | 1992 | return err; |
---|
1997 | 1993 | } |
---|
1998 | 1994 | |
---|
1999 | | - chip->read_buf = omap_read_buf_irq_pref; |
---|
2000 | | - chip->write_buf = omap_write_buf_irq_pref; |
---|
| 1995 | + chip->legacy.read_buf = omap_read_buf_irq_pref; |
---|
| 1996 | + chip->legacy.write_buf = omap_write_buf_irq_pref; |
---|
2001 | 1997 | |
---|
2002 | 1998 | break; |
---|
2003 | 1999 | |
---|
.. | .. |
---|
2010 | 2006 | return -EINVAL; |
---|
2011 | 2007 | |
---|
2012 | 2008 | /* |
---|
2013 | | - * Bail out earlier to let NAND_ECC_SOFT code create its own |
---|
| 2009 | + * Bail out earlier to let NAND_ECC_ENGINE_TYPE_SOFT code create its own |
---|
2014 | 2010 | * ooblayout instead of using ours. |
---|
2015 | 2011 | */ |
---|
2016 | 2012 | if (info->ecc_opt == OMAP_ECC_HAM1_CODE_SW) { |
---|
2017 | | - chip->ecc.mode = NAND_ECC_SOFT; |
---|
2018 | | - chip->ecc.algo = NAND_ECC_HAMMING; |
---|
| 2013 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; |
---|
| 2014 | + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; |
---|
2019 | 2015 | return 0; |
---|
2020 | 2016 | } |
---|
2021 | 2017 | |
---|
.. | .. |
---|
2023 | 2019 | switch (info->ecc_opt) { |
---|
2024 | 2020 | case OMAP_ECC_HAM1_CODE_HW: |
---|
2025 | 2021 | dev_info(dev, "nand: using OMAP_ECC_HAM1_CODE_HW\n"); |
---|
2026 | | - chip->ecc.mode = NAND_ECC_HW; |
---|
| 2022 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; |
---|
2027 | 2023 | chip->ecc.bytes = 3; |
---|
2028 | 2024 | chip->ecc.size = 512; |
---|
2029 | 2025 | chip->ecc.strength = 1; |
---|
.. | .. |
---|
2040 | 2036 | |
---|
2041 | 2037 | case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: |
---|
2042 | 2038 | pr_info("nand: using OMAP_ECC_BCH4_CODE_HW_DETECTION_SW\n"); |
---|
2043 | | - chip->ecc.mode = NAND_ECC_HW; |
---|
| 2039 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; |
---|
2044 | 2040 | chip->ecc.size = 512; |
---|
2045 | 2041 | chip->ecc.bytes = 7; |
---|
2046 | 2042 | chip->ecc.strength = 4; |
---|
.. | .. |
---|
2060 | 2056 | |
---|
2061 | 2057 | case OMAP_ECC_BCH4_CODE_HW: |
---|
2062 | 2058 | pr_info("nand: using OMAP_ECC_BCH4_CODE_HW ECC scheme\n"); |
---|
2063 | | - chip->ecc.mode = NAND_ECC_HW; |
---|
| 2059 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; |
---|
2064 | 2060 | chip->ecc.size = 512; |
---|
2065 | 2061 | /* 14th bit is kept reserved for ROM-code compatibility */ |
---|
2066 | 2062 | chip->ecc.bytes = 7 + 1; |
---|
.. | .. |
---|
2082 | 2078 | |
---|
2083 | 2079 | case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: |
---|
2084 | 2080 | pr_info("nand: using OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n"); |
---|
2085 | | - chip->ecc.mode = NAND_ECC_HW; |
---|
| 2081 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; |
---|
2086 | 2082 | chip->ecc.size = 512; |
---|
2087 | 2083 | chip->ecc.bytes = 13; |
---|
2088 | 2084 | chip->ecc.strength = 8; |
---|
.. | .. |
---|
2102 | 2098 | |
---|
2103 | 2099 | case OMAP_ECC_BCH8_CODE_HW: |
---|
2104 | 2100 | pr_info("nand: using OMAP_ECC_BCH8_CODE_HW ECC scheme\n"); |
---|
2105 | | - chip->ecc.mode = NAND_ECC_HW; |
---|
| 2101 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; |
---|
2106 | 2102 | chip->ecc.size = 512; |
---|
2107 | 2103 | /* 14th bit is kept reserved for ROM-code compatibility */ |
---|
2108 | 2104 | chip->ecc.bytes = 13 + 1; |
---|
.. | .. |
---|
2125 | 2121 | |
---|
2126 | 2122 | case OMAP_ECC_BCH16_CODE_HW: |
---|
2127 | 2123 | pr_info("Using OMAP_ECC_BCH16_CODE_HW ECC scheme\n"); |
---|
2128 | | - chip->ecc.mode = NAND_ECC_HW; |
---|
| 2124 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; |
---|
2129 | 2125 | chip->ecc.size = 512; |
---|
2130 | 2126 | chip->ecc.bytes = 26; |
---|
2131 | 2127 | chip->ecc.strength = 16; |
---|
.. | .. |
---|
2167 | 2163 | }; |
---|
2168 | 2164 | |
---|
2169 | 2165 | /* Shared among all NAND instances to synchronize access to the ECC Engine */ |
---|
2170 | | -static struct nand_controller omap_gpmc_controller = { |
---|
2171 | | - .lock = __SPIN_LOCK_UNLOCKED(omap_gpmc_controller.lock), |
---|
2172 | | - .wq = __WAIT_QUEUE_HEAD_INITIALIZER(omap_gpmc_controller.wq), |
---|
2173 | | - .ops = &omap_nand_controller_ops, |
---|
2174 | | -}; |
---|
| 2166 | +static struct nand_controller omap_gpmc_controller; |
---|
| 2167 | +static bool omap_gpmc_controller_initialized; |
---|
2175 | 2168 | |
---|
2176 | 2169 | static int omap_nand_probe(struct platform_device *pdev) |
---|
2177 | 2170 | { |
---|
.. | .. |
---|
2215 | 2208 | } |
---|
2216 | 2209 | |
---|
2217 | 2210 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
2218 | | - nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res); |
---|
2219 | | - if (IS_ERR(nand_chip->IO_ADDR_R)) |
---|
2220 | | - return PTR_ERR(nand_chip->IO_ADDR_R); |
---|
| 2211 | + nand_chip->legacy.IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res); |
---|
| 2212 | + if (IS_ERR(nand_chip->legacy.IO_ADDR_R)) |
---|
| 2213 | + return PTR_ERR(nand_chip->legacy.IO_ADDR_R); |
---|
2221 | 2214 | |
---|
2222 | 2215 | info->phys_base = res->start; |
---|
2223 | 2216 | |
---|
| 2217 | + if (!omap_gpmc_controller_initialized) { |
---|
| 2218 | + omap_gpmc_controller.ops = &omap_nand_controller_ops; |
---|
| 2219 | + nand_controller_init(&omap_gpmc_controller); |
---|
| 2220 | + omap_gpmc_controller_initialized = true; |
---|
| 2221 | + } |
---|
| 2222 | + |
---|
2224 | 2223 | nand_chip->controller = &omap_gpmc_controller; |
---|
2225 | 2224 | |
---|
2226 | | - nand_chip->IO_ADDR_W = nand_chip->IO_ADDR_R; |
---|
2227 | | - nand_chip->cmd_ctrl = omap_hwcontrol; |
---|
| 2225 | + nand_chip->legacy.IO_ADDR_W = nand_chip->legacy.IO_ADDR_R; |
---|
| 2226 | + nand_chip->legacy.cmd_ctrl = omap_hwcontrol; |
---|
2228 | 2227 | |
---|
2229 | 2228 | info->ready_gpiod = devm_gpiod_get_optional(&pdev->dev, "rb", |
---|
2230 | 2229 | GPIOD_IN); |
---|
.. | .. |
---|
2241 | 2240 | * device and read status register until you get a failure or success |
---|
2242 | 2241 | */ |
---|
2243 | 2242 | if (info->ready_gpiod) { |
---|
2244 | | - nand_chip->dev_ready = omap_dev_ready; |
---|
2245 | | - nand_chip->chip_delay = 0; |
---|
| 2243 | + nand_chip->legacy.dev_ready = omap_dev_ready; |
---|
| 2244 | + nand_chip->legacy.chip_delay = 0; |
---|
2246 | 2245 | } else { |
---|
2247 | | - nand_chip->waitfunc = omap_wait; |
---|
2248 | | - nand_chip->chip_delay = 50; |
---|
| 2246 | + nand_chip->legacy.waitfunc = omap_wait; |
---|
| 2247 | + nand_chip->legacy.chip_delay = 50; |
---|
2249 | 2248 | } |
---|
2250 | 2249 | |
---|
2251 | 2250 | if (info->flash_bbt) |
---|
.. | .. |
---|
2284 | 2283 | struct mtd_info *mtd = platform_get_drvdata(pdev); |
---|
2285 | 2284 | struct nand_chip *nand_chip = mtd_to_nand(mtd); |
---|
2286 | 2285 | struct omap_nand_info *info = mtd_to_omap(mtd); |
---|
| 2286 | + int ret; |
---|
| 2287 | + |
---|
2287 | 2288 | if (nand_chip->ecc.priv) { |
---|
2288 | 2289 | nand_bch_free(nand_chip->ecc.priv); |
---|
2289 | 2290 | nand_chip->ecc.priv = NULL; |
---|
2290 | 2291 | } |
---|
2291 | 2292 | if (info->dma) |
---|
2292 | 2293 | dma_release_channel(info->dma); |
---|
2293 | | - nand_release(nand_chip); |
---|
2294 | | - return 0; |
---|
| 2294 | + ret = mtd_device_unregister(mtd); |
---|
| 2295 | + WARN_ON(ret); |
---|
| 2296 | + nand_cleanup(nand_chip); |
---|
| 2297 | + return ret; |
---|
2295 | 2298 | } |
---|
2296 | 2299 | |
---|
2297 | 2300 | static const struct of_device_id omap_nand_ids[] = { |
---|