| .. | .. |
|---|
| 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[] = { |
|---|