| .. | .. |
|---|
| 5 | 5 | * Copyright (C) 2017 Marvell |
|---|
| 6 | 6 | * Author: Miquel RAYNAL <miquel.raynal@free-electrons.com> |
|---|
| 7 | 7 | * |
|---|
| 8 | + * |
|---|
| 9 | + * This NAND controller driver handles two versions of the hardware, |
|---|
| 10 | + * one is called NFCv1 and is available on PXA SoCs and the other is |
|---|
| 11 | + * called NFCv2 and is available on Armada SoCs. |
|---|
| 12 | + * |
|---|
| 13 | + * The main visible difference is that NFCv1 only has Hamming ECC |
|---|
| 14 | + * capabilities, while NFCv2 also embeds a BCH ECC engine. Also, DMA |
|---|
| 15 | + * is not used with NFCv2. |
|---|
| 16 | + * |
|---|
| 17 | + * The ECC layouts are depicted in details in Marvell AN-379, but here |
|---|
| 18 | + * is a brief description. |
|---|
| 19 | + * |
|---|
| 20 | + * When using Hamming, the data is split in 512B chunks (either 1, 2 |
|---|
| 21 | + * or 4) and each chunk will have its own ECC "digest" of 6B at the |
|---|
| 22 | + * beginning of the OOB area and eventually the remaining free OOB |
|---|
| 23 | + * bytes (also called "spare" bytes in the driver). This engine |
|---|
| 24 | + * corrects up to 1 bit per chunk and detects reliably an error if |
|---|
| 25 | + * there are at most 2 bitflips. Here is the page layout used by the |
|---|
| 26 | + * controller when Hamming is chosen: |
|---|
| 27 | + * |
|---|
| 28 | + * +-------------------------------------------------------------+ |
|---|
| 29 | + * | Data 1 | ... | Data N | ECC 1 | ... | ECCN | Free OOB bytes | |
|---|
| 30 | + * +-------------------------------------------------------------+ |
|---|
| 31 | + * |
|---|
| 32 | + * When using the BCH engine, there are N identical (data + free OOB + |
|---|
| 33 | + * ECC) sections and potentially an extra one to deal with |
|---|
| 34 | + * configurations where the chosen (data + free OOB + ECC) sizes do |
|---|
| 35 | + * not align with the page (data + OOB) size. ECC bytes are always |
|---|
| 36 | + * 30B per ECC chunk. Here is the page layout used by the controller |
|---|
| 37 | + * when BCH is chosen: |
|---|
| 38 | + * |
|---|
| 39 | + * +----------------------------------------- |
|---|
| 40 | + * | Data 1 | Free OOB bytes 1 | ECC 1 | ... |
|---|
| 41 | + * +----------------------------------------- |
|---|
| 42 | + * |
|---|
| 43 | + * ------------------------------------------- |
|---|
| 44 | + * ... | Data N | Free OOB bytes N | ECC N | |
|---|
| 45 | + * ------------------------------------------- |
|---|
| 46 | + * |
|---|
| 47 | + * --------------------------------------------+ |
|---|
| 48 | + * Last Data | Last Free OOB bytes | Last ECC | |
|---|
| 49 | + * --------------------------------------------+ |
|---|
| 50 | + * |
|---|
| 51 | + * In both cases, the layout seen by the user is always: all data |
|---|
| 52 | + * first, then all free OOB bytes and finally all ECC bytes. With BCH, |
|---|
| 53 | + * ECC bytes are 30B long and are padded with 0xFF to align on 32 |
|---|
| 54 | + * bytes. |
|---|
| 55 | + * |
|---|
| 56 | + * The controller has certain limitations that are handled by the |
|---|
| 57 | + * driver: |
|---|
| 58 | + * - It can only read 2k at a time. To overcome this limitation, the |
|---|
| 59 | + * driver issues data cycles on the bus, without issuing new |
|---|
| 60 | + * CMD + ADDR cycles. The Marvell term is "naked" operations. |
|---|
| 61 | + * - The ECC strength in BCH mode cannot be tuned. It is fixed 16 |
|---|
| 62 | + * bits. What can be tuned is the ECC block size as long as it |
|---|
| 63 | + * stays between 512B and 2kiB. It's usually chosen based on the |
|---|
| 64 | + * chip ECC requirements. For instance, using 2kiB ECC chunks |
|---|
| 65 | + * provides 4b/512B correctability. |
|---|
| 66 | + * - The controller will always treat data bytes, free OOB bytes |
|---|
| 67 | + * and ECC bytes in that order, no matter what the real layout is |
|---|
| 68 | + * (which is usually all data then all OOB bytes). The |
|---|
| 69 | + * marvell_nfc_layouts array below contains the currently |
|---|
| 70 | + * supported layouts. |
|---|
| 71 | + * - Because of these weird layouts, the Bad Block Markers can be |
|---|
| 72 | + * located in data section. In this case, the NAND_BBT_NO_OOB_BBM |
|---|
| 73 | + * option must be set to prevent scanning/writing bad block |
|---|
| 74 | + * markers. |
|---|
| 8 | 75 | */ |
|---|
| 9 | 76 | |
|---|
| 10 | 77 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 160 | 227 | #define XTYPE_MASK 7 |
|---|
| 161 | 228 | |
|---|
| 162 | 229 | /** |
|---|
| 230 | + * struct marvell_hw_ecc_layout - layout of Marvell ECC |
|---|
| 231 | + * |
|---|
| 163 | 232 | * Marvell ECC engine works differently than the others, in order to limit the |
|---|
| 164 | 233 | * size of the IP, hardware engineers chose to set a fixed strength at 16 bits |
|---|
| 165 | 234 | * per subpage, and depending on a the desired strength needed by the NAND chip, |
|---|
| .. | .. |
|---|
| 217 | 286 | MARVELL_LAYOUT( 512, 512, 1, 1, 1, 512, 8, 8, 0, 0, 0), |
|---|
| 218 | 287 | MARVELL_LAYOUT( 2048, 512, 1, 1, 1, 2048, 40, 24, 0, 0, 0), |
|---|
| 219 | 288 | MARVELL_LAYOUT( 2048, 512, 4, 1, 1, 2048, 32, 30, 0, 0, 0), |
|---|
| 289 | + MARVELL_LAYOUT( 2048, 512, 8, 2, 1, 1024, 0, 30,1024,32, 30), |
|---|
| 220 | 290 | MARVELL_LAYOUT( 4096, 512, 4, 2, 2, 2048, 32, 30, 0, 0, 0), |
|---|
| 221 | 291 | MARVELL_LAYOUT( 4096, 512, 8, 5, 4, 1024, 0, 30, 0, 64, 30), |
|---|
| 292 | + MARVELL_LAYOUT( 8192, 512, 4, 4, 4, 2048, 0, 30, 0, 0, 0), |
|---|
| 293 | + MARVELL_LAYOUT( 8192, 512, 8, 9, 8, 1024, 0, 30, 0, 160, 30), |
|---|
| 222 | 294 | }; |
|---|
| 223 | 295 | |
|---|
| 224 | 296 | /** |
|---|
| 297 | + * struct marvell_nand_chip_sel - CS line description |
|---|
| 298 | + * |
|---|
| 225 | 299 | * The Nand Flash Controller has up to 4 CE and 2 RB pins. The CE selection |
|---|
| 226 | 300 | * is made by a field in NDCB0 register, and in another field in NDCB2 register. |
|---|
| 227 | 301 | * The datasheet describes the logic with an error: ADDR5 field is once |
|---|
| .. | .. |
|---|
| 242 | 316 | }; |
|---|
| 243 | 317 | |
|---|
| 244 | 318 | /** |
|---|
| 245 | | - * NAND chip structure: stores NAND chip device related information |
|---|
| 319 | + * struct marvell_nand_chip - stores NAND chip device related information |
|---|
| 246 | 320 | * |
|---|
| 247 | 321 | * @chip: Base NAND chip structure |
|---|
| 248 | 322 | * @node: Used to store NAND chips into a list |
|---|
| 249 | | - * @layout NAND layout when using hardware ECC |
|---|
| 323 | + * @layout: NAND layout when using hardware ECC |
|---|
| 250 | 324 | * @ndcr: Controller register value for this NAND chip |
|---|
| 251 | 325 | * @ndtr0: Timing registers 0 value for this NAND chip |
|---|
| 252 | 326 | * @ndtr1: Timing registers 1 value for this NAND chip |
|---|
| 327 | + * @addr_cyc: Amount of cycles needed to pass column address |
|---|
| 253 | 328 | * @selected_die: Current active CS |
|---|
| 254 | 329 | * @nsels: Number of CS lines required by the NAND chip |
|---|
| 255 | 330 | * @sels: Array of CS lines descriptions |
|---|
| .. | .. |
|---|
| 264 | 339 | int addr_cyc; |
|---|
| 265 | 340 | int selected_die; |
|---|
| 266 | 341 | unsigned int nsels; |
|---|
| 267 | | - struct marvell_nand_chip_sel sels[0]; |
|---|
| 342 | + struct marvell_nand_chip_sel sels[]; |
|---|
| 268 | 343 | }; |
|---|
| 269 | 344 | |
|---|
| 270 | 345 | static inline struct marvell_nand_chip *to_marvell_nand(struct nand_chip *chip) |
|---|
| .. | .. |
|---|
| 279 | 354 | } |
|---|
| 280 | 355 | |
|---|
| 281 | 356 | /** |
|---|
| 282 | | - * NAND controller capabilities for distinction between compatible strings |
|---|
| 357 | + * struct marvell_nfc_caps - NAND controller capabilities for distinction |
|---|
| 358 | + * between compatible strings |
|---|
| 283 | 359 | * |
|---|
| 284 | 360 | * @max_cs_nb: Number of Chip Select lines available |
|---|
| 285 | 361 | * @max_rb_nb: Number of Ready/Busy lines available |
|---|
| .. | .. |
|---|
| 302 | 378 | }; |
|---|
| 303 | 379 | |
|---|
| 304 | 380 | /** |
|---|
| 305 | | - * NAND controller structure: stores Marvell NAND controller information |
|---|
| 381 | + * struct marvell_nfc - stores Marvell NAND controller information |
|---|
| 306 | 382 | * |
|---|
| 307 | 383 | * @controller: Base controller structure |
|---|
| 308 | 384 | * @dev: Parent device (used to print error messages) |
|---|
| 309 | 385 | * @regs: NAND controller registers |
|---|
| 310 | 386 | * @core_clk: Core clock |
|---|
| 311 | | - * @reg_clk: Regiters clock |
|---|
| 387 | + * @reg_clk: Registers clock |
|---|
| 312 | 388 | * @complete: Completion object to wait for NAND controller events |
|---|
| 313 | 389 | * @assigned_cs: Bitmask describing already assigned CS lines |
|---|
| 314 | 390 | * @chips: List containing all the NAND chips attached to |
|---|
| 315 | 391 | * this NAND controller |
|---|
| 392 | + * @selected_chip: Currently selected target chip |
|---|
| 316 | 393 | * @caps: NAND controller capabilities for each compatible string |
|---|
| 394 | + * @use_dma: Whetner DMA is used |
|---|
| 317 | 395 | * @dma_chan: DMA channel (NFCv1 only) |
|---|
| 318 | 396 | * @dma_buf: 32-bit aligned buffer for DMA transfers (NFCv1 only) |
|---|
| 319 | 397 | */ |
|---|
| .. | .. |
|---|
| 341 | 419 | } |
|---|
| 342 | 420 | |
|---|
| 343 | 421 | /** |
|---|
| 344 | | - * NAND controller timings expressed in NAND Controller clock cycles |
|---|
| 422 | + * struct marvell_nfc_timings - NAND controller timings expressed in NAND |
|---|
| 423 | + * Controller clock cycles |
|---|
| 345 | 424 | * |
|---|
| 346 | 425 | * @tRP: ND_nRE pulse width |
|---|
| 347 | 426 | * @tRH: ND_nRE high duration |
|---|
| .. | .. |
|---|
| 385 | 464 | period_ns)) |
|---|
| 386 | 465 | |
|---|
| 387 | 466 | /** |
|---|
| 388 | | - * NAND driver structure filled during the parsing of the ->exec_op() subop |
|---|
| 389 | | - * subset of instructions. |
|---|
| 467 | + * struct marvell_nfc_op - filled during the parsing of the ->exec_op() |
|---|
| 468 | + * subop subset of instructions. |
|---|
| 390 | 469 | * |
|---|
| 391 | 470 | * @ndcb: Array of values written to NDCBx registers |
|---|
| 392 | 471 | * @cle_ale_delay_ns: Optional delay after the last CMD or ADDR cycle |
|---|
| .. | .. |
|---|
| 615 | 694 | return marvell_nfc_end_cmd(chip, cs_flag, "CMDD"); |
|---|
| 616 | 695 | } |
|---|
| 617 | 696 | |
|---|
| 697 | +static int marvell_nfc_poll_status(struct marvell_nfc *nfc, u32 mask, |
|---|
| 698 | + u32 expected_val, unsigned long timeout_ms) |
|---|
| 699 | +{ |
|---|
| 700 | + unsigned long limit; |
|---|
| 701 | + u32 st; |
|---|
| 702 | + |
|---|
| 703 | + limit = jiffies + msecs_to_jiffies(timeout_ms); |
|---|
| 704 | + do { |
|---|
| 705 | + st = readl_relaxed(nfc->regs + NDSR); |
|---|
| 706 | + if (st & NDSR_RDY(1)) |
|---|
| 707 | + st |= NDSR_RDY(0); |
|---|
| 708 | + |
|---|
| 709 | + if ((st & mask) == expected_val) |
|---|
| 710 | + return 0; |
|---|
| 711 | + |
|---|
| 712 | + cpu_relax(); |
|---|
| 713 | + } while (time_after(limit, jiffies)); |
|---|
| 714 | + |
|---|
| 715 | + return -ETIMEDOUT; |
|---|
| 716 | +} |
|---|
| 717 | + |
|---|
| 618 | 718 | static int marvell_nfc_wait_op(struct nand_chip *chip, unsigned int timeout_ms) |
|---|
| 619 | 719 | { |
|---|
| 620 | 720 | struct marvell_nfc *nfc = to_marvell_nfc(chip->controller); |
|---|
| 721 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 621 | 722 | u32 pending; |
|---|
| 622 | 723 | int ret; |
|---|
| 623 | 724 | |
|---|
| .. | .. |
|---|
| 625 | 726 | if (!timeout_ms) |
|---|
| 626 | 727 | timeout_ms = IRQ_TIMEOUT; |
|---|
| 627 | 728 | |
|---|
| 628 | | - init_completion(&nfc->complete); |
|---|
| 729 | + if (mtd->oops_panic_write) { |
|---|
| 730 | + ret = marvell_nfc_poll_status(nfc, NDSR_RDY(0), |
|---|
| 731 | + NDSR_RDY(0), |
|---|
| 732 | + timeout_ms); |
|---|
| 733 | + } else { |
|---|
| 734 | + init_completion(&nfc->complete); |
|---|
| 629 | 735 | |
|---|
| 630 | | - marvell_nfc_enable_int(nfc, NDCR_RDYM); |
|---|
| 631 | | - ret = wait_for_completion_timeout(&nfc->complete, |
|---|
| 632 | | - msecs_to_jiffies(timeout_ms)); |
|---|
| 633 | | - marvell_nfc_disable_int(nfc, NDCR_RDYM); |
|---|
| 736 | + marvell_nfc_enable_int(nfc, NDCR_RDYM); |
|---|
| 737 | + ret = wait_for_completion_timeout(&nfc->complete, |
|---|
| 738 | + msecs_to_jiffies(timeout_ms)); |
|---|
| 739 | + marvell_nfc_disable_int(nfc, NDCR_RDYM); |
|---|
| 740 | + } |
|---|
| 634 | 741 | pending = marvell_nfc_clear_int(nfc, NDSR_RDY(0) | NDSR_RDY(1)); |
|---|
| 635 | 742 | |
|---|
| 636 | 743 | /* |
|---|
| .. | .. |
|---|
| 645 | 752 | return 0; |
|---|
| 646 | 753 | } |
|---|
| 647 | 754 | |
|---|
| 648 | | -static void marvell_nfc_select_chip(struct mtd_info *mtd, int die_nr) |
|---|
| 755 | +static void marvell_nfc_select_target(struct nand_chip *chip, |
|---|
| 756 | + unsigned int die_nr) |
|---|
| 649 | 757 | { |
|---|
| 650 | | - struct nand_chip *chip = mtd_to_nand(mtd); |
|---|
| 651 | 758 | struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip); |
|---|
| 652 | 759 | struct marvell_nfc *nfc = to_marvell_nfc(chip->controller); |
|---|
| 653 | 760 | u32 ndcr_generic; |
|---|
| 654 | | - |
|---|
| 655 | | - if (chip == nfc->selected_chip && die_nr == marvell_nand->selected_die) |
|---|
| 656 | | - return; |
|---|
| 657 | | - |
|---|
| 658 | | - if (die_nr < 0 || die_nr >= marvell_nand->nsels) { |
|---|
| 659 | | - nfc->selected_chip = NULL; |
|---|
| 660 | | - marvell_nand->selected_die = -1; |
|---|
| 661 | | - return; |
|---|
| 662 | | - } |
|---|
| 663 | | - |
|---|
| 664 | | - writel_relaxed(marvell_nand->ndtr0, nfc->regs + NDTR0); |
|---|
| 665 | | - writel_relaxed(marvell_nand->ndtr1, nfc->regs + NDTR1); |
|---|
| 666 | 761 | |
|---|
| 667 | 762 | /* |
|---|
| 668 | 763 | * Reset the NDCR register to a clean state for this particular chip, |
|---|
| .. | .. |
|---|
| 674 | 769 | |
|---|
| 675 | 770 | /* Also reset the interrupt status register */ |
|---|
| 676 | 771 | marvell_nfc_clear_int(nfc, NDCR_ALL_INT); |
|---|
| 772 | + |
|---|
| 773 | + if (chip == nfc->selected_chip && die_nr == marvell_nand->selected_die) |
|---|
| 774 | + return; |
|---|
| 775 | + |
|---|
| 776 | + writel_relaxed(marvell_nand->ndtr0, nfc->regs + NDTR0); |
|---|
| 777 | + writel_relaxed(marvell_nand->ndtr1, nfc->regs + NDTR1); |
|---|
| 677 | 778 | |
|---|
| 678 | 779 | nfc->selected_chip = chip; |
|---|
| 679 | 780 | marvell_nand->selected_die = die_nr; |
|---|
| .. | .. |
|---|
| 716 | 817 | * When enabling BCH, set threshold to 0 to always know the |
|---|
| 717 | 818 | * number of corrected bitflips. |
|---|
| 718 | 819 | */ |
|---|
| 719 | | - if (chip->ecc.algo == NAND_ECC_BCH) |
|---|
| 820 | + if (chip->ecc.algo == NAND_ECC_ALGO_BCH) |
|---|
| 720 | 821 | writel_relaxed(NDECCCTRL_BCH_EN, nfc->regs + NDECCCTRL); |
|---|
| 721 | 822 | } |
|---|
| 722 | 823 | } |
|---|
| .. | .. |
|---|
| 728 | 829 | |
|---|
| 729 | 830 | if (ndcr & NDCR_ECC_EN) { |
|---|
| 730 | 831 | writel_relaxed(ndcr & ~NDCR_ECC_EN, nfc->regs + NDCR); |
|---|
| 731 | | - if (chip->ecc.algo == NAND_ECC_BCH) |
|---|
| 832 | + if (chip->ecc.algo == NAND_ECC_ALGO_BCH) |
|---|
| 732 | 833 | writel_relaxed(0, nfc->regs + NDECCCTRL); |
|---|
| 733 | 834 | } |
|---|
| 734 | 835 | } |
|---|
| .. | .. |
|---|
| 868 | 969 | } |
|---|
| 869 | 970 | |
|---|
| 870 | 971 | /* |
|---|
| 871 | | - * Check a chunk is correct or not according to hardware ECC engine. |
|---|
| 972 | + * Check if a chunk is correct or not according to the hardware ECC engine. |
|---|
| 872 | 973 | * mtd->ecc_stats.corrected is updated, as well as max_bitflips, however |
|---|
| 873 | 974 | * mtd->ecc_stats.failure is not, the function will instead return a non-zero |
|---|
| 874 | 975 | * value indicating that a check on the emptyness of the subpage must be |
|---|
| 875 | | - * performed before declaring the subpage corrupted. |
|---|
| 976 | + * performed before actually declaring the subpage as "corrupted". |
|---|
| 876 | 977 | */ |
|---|
| 877 | | -static int marvell_nfc_hw_ecc_correct(struct nand_chip *chip, |
|---|
| 878 | | - unsigned int *max_bitflips) |
|---|
| 978 | +static int marvell_nfc_hw_ecc_check_bitflips(struct nand_chip *chip, |
|---|
| 979 | + unsigned int *max_bitflips) |
|---|
| 879 | 980 | { |
|---|
| 880 | 981 | struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 881 | 982 | struct marvell_nfc *nfc = to_marvell_nfc(chip->controller); |
|---|
| .. | .. |
|---|
| 902 | 1003 | if (ndsr & NDSR_CORERR) { |
|---|
| 903 | 1004 | writel_relaxed(ndsr, nfc->regs + NDSR); |
|---|
| 904 | 1005 | |
|---|
| 905 | | - if (chip->ecc.algo == NAND_ECC_BCH) |
|---|
| 1006 | + if (chip->ecc.algo == NAND_ECC_ALGO_BCH) |
|---|
| 906 | 1007 | bf = NDSR_ERRCNT(ndsr); |
|---|
| 907 | 1008 | else |
|---|
| 908 | 1009 | bf = 1; |
|---|
| .. | .. |
|---|
| 966 | 1067 | } |
|---|
| 967 | 1068 | |
|---|
| 968 | 1069 | ret = marvell_nfc_wait_cmdd(chip); |
|---|
| 969 | | - |
|---|
| 970 | 1070 | return ret; |
|---|
| 971 | 1071 | } |
|---|
| 972 | 1072 | |
|---|
| 973 | | -static int marvell_nfc_hw_ecc_hmg_read_page_raw(struct mtd_info *mtd, |
|---|
| 974 | | - struct nand_chip *chip, u8 *buf, |
|---|
| 1073 | +static int marvell_nfc_hw_ecc_hmg_read_page_raw(struct nand_chip *chip, u8 *buf, |
|---|
| 975 | 1074 | int oob_required, int page) |
|---|
| 976 | 1075 | { |
|---|
| 1076 | + marvell_nfc_select_target(chip, chip->cur_cs); |
|---|
| 977 | 1077 | return marvell_nfc_hw_ecc_hmg_do_read_page(chip, buf, chip->oob_poi, |
|---|
| 978 | 1078 | true, page); |
|---|
| 979 | 1079 | } |
|---|
| 980 | 1080 | |
|---|
| 981 | | -static int marvell_nfc_hw_ecc_hmg_read_page(struct mtd_info *mtd, |
|---|
| 982 | | - struct nand_chip *chip, |
|---|
| 983 | | - u8 *buf, int oob_required, |
|---|
| 984 | | - int page) |
|---|
| 1081 | +static int marvell_nfc_hw_ecc_hmg_read_page(struct nand_chip *chip, u8 *buf, |
|---|
| 1082 | + int oob_required, int page) |
|---|
| 985 | 1083 | { |
|---|
| 986 | 1084 | const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout; |
|---|
| 987 | 1085 | unsigned int full_sz = lt->data_bytes + lt->spare_bytes + lt->ecc_bytes; |
|---|
| 988 | 1086 | int max_bitflips = 0, ret; |
|---|
| 989 | 1087 | u8 *raw_buf; |
|---|
| 990 | 1088 | |
|---|
| 1089 | + marvell_nfc_select_target(chip, chip->cur_cs); |
|---|
| 991 | 1090 | marvell_nfc_enable_hw_ecc(chip); |
|---|
| 992 | 1091 | marvell_nfc_hw_ecc_hmg_do_read_page(chip, buf, chip->oob_poi, false, |
|---|
| 993 | 1092 | page); |
|---|
| 994 | | - ret = marvell_nfc_hw_ecc_correct(chip, &max_bitflips); |
|---|
| 1093 | + ret = marvell_nfc_hw_ecc_check_bitflips(chip, &max_bitflips); |
|---|
| 995 | 1094 | marvell_nfc_disable_hw_ecc(chip); |
|---|
| 996 | 1095 | |
|---|
| 997 | 1096 | if (!ret) |
|---|
| .. | .. |
|---|
| 1019 | 1118 | * it appears before the ECC bytes when reading), the ->read_oob_raw() function |
|---|
| 1020 | 1119 | * also stands for ->read_oob(). |
|---|
| 1021 | 1120 | */ |
|---|
| 1022 | | -static int marvell_nfc_hw_ecc_hmg_read_oob_raw(struct mtd_info *mtd, |
|---|
| 1023 | | - struct nand_chip *chip, int page) |
|---|
| 1121 | +static int marvell_nfc_hw_ecc_hmg_read_oob_raw(struct nand_chip *chip, int page) |
|---|
| 1024 | 1122 | { |
|---|
| 1025 | | - /* Invalidate page cache */ |
|---|
| 1026 | | - chip->pagebuf = -1; |
|---|
| 1123 | + u8 *buf = nand_get_data_buf(chip); |
|---|
| 1027 | 1124 | |
|---|
| 1028 | | - return marvell_nfc_hw_ecc_hmg_do_read_page(chip, chip->data_buf, |
|---|
| 1029 | | - chip->oob_poi, true, page); |
|---|
| 1125 | + marvell_nfc_select_target(chip, chip->cur_cs); |
|---|
| 1126 | + return marvell_nfc_hw_ecc_hmg_do_read_page(chip, buf, chip->oob_poi, |
|---|
| 1127 | + true, page); |
|---|
| 1030 | 1128 | } |
|---|
| 1031 | 1129 | |
|---|
| 1032 | 1130 | /* Hamming write helpers */ |
|---|
| .. | .. |
|---|
| 1035 | 1133 | const u8 *oob_buf, bool raw, |
|---|
| 1036 | 1134 | int page) |
|---|
| 1037 | 1135 | { |
|---|
| 1136 | + const struct nand_sdr_timings *sdr = |
|---|
| 1137 | + nand_get_sdr_timings(nand_get_interface_config(chip)); |
|---|
| 1038 | 1138 | struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip); |
|---|
| 1039 | 1139 | struct marvell_nfc *nfc = to_marvell_nfc(chip->controller); |
|---|
| 1040 | 1140 | const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout; |
|---|
| .. | .. |
|---|
| 1080 | 1180 | return ret; |
|---|
| 1081 | 1181 | |
|---|
| 1082 | 1182 | ret = marvell_nfc_wait_op(chip, |
|---|
| 1083 | | - PSEC_TO_MSEC(chip->data_interface.timings.sdr.tPROG_max)); |
|---|
| 1183 | + PSEC_TO_MSEC(sdr->tPROG_max)); |
|---|
| 1084 | 1184 | return ret; |
|---|
| 1085 | 1185 | } |
|---|
| 1086 | 1186 | |
|---|
| 1087 | | -static int marvell_nfc_hw_ecc_hmg_write_page_raw(struct mtd_info *mtd, |
|---|
| 1088 | | - struct nand_chip *chip, |
|---|
| 1187 | +static int marvell_nfc_hw_ecc_hmg_write_page_raw(struct nand_chip *chip, |
|---|
| 1089 | 1188 | const u8 *buf, |
|---|
| 1090 | 1189 | int oob_required, int page) |
|---|
| 1091 | 1190 | { |
|---|
| 1191 | + marvell_nfc_select_target(chip, chip->cur_cs); |
|---|
| 1092 | 1192 | return marvell_nfc_hw_ecc_hmg_do_write_page(chip, buf, chip->oob_poi, |
|---|
| 1093 | 1193 | true, page); |
|---|
| 1094 | 1194 | } |
|---|
| 1095 | 1195 | |
|---|
| 1096 | | -static int marvell_nfc_hw_ecc_hmg_write_page(struct mtd_info *mtd, |
|---|
| 1097 | | - struct nand_chip *chip, |
|---|
| 1196 | +static int marvell_nfc_hw_ecc_hmg_write_page(struct nand_chip *chip, |
|---|
| 1098 | 1197 | const u8 *buf, |
|---|
| 1099 | 1198 | int oob_required, int page) |
|---|
| 1100 | 1199 | { |
|---|
| 1101 | 1200 | int ret; |
|---|
| 1102 | 1201 | |
|---|
| 1202 | + marvell_nfc_select_target(chip, chip->cur_cs); |
|---|
| 1103 | 1203 | marvell_nfc_enable_hw_ecc(chip); |
|---|
| 1104 | 1204 | ret = marvell_nfc_hw_ecc_hmg_do_write_page(chip, buf, chip->oob_poi, |
|---|
| 1105 | 1205 | false, page); |
|---|
| .. | .. |
|---|
| 1113 | 1213 | * it appears before the ECC bytes when reading), the ->write_oob_raw() function |
|---|
| 1114 | 1214 | * also stands for ->write_oob(). |
|---|
| 1115 | 1215 | */ |
|---|
| 1116 | | -static int marvell_nfc_hw_ecc_hmg_write_oob_raw(struct mtd_info *mtd, |
|---|
| 1117 | | - struct nand_chip *chip, |
|---|
| 1216 | +static int marvell_nfc_hw_ecc_hmg_write_oob_raw(struct nand_chip *chip, |
|---|
| 1118 | 1217 | int page) |
|---|
| 1119 | 1218 | { |
|---|
| 1120 | | - /* Invalidate page cache */ |
|---|
| 1121 | | - chip->pagebuf = -1; |
|---|
| 1219 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 1220 | + u8 *buf = nand_get_data_buf(chip); |
|---|
| 1122 | 1221 | |
|---|
| 1123 | | - memset(chip->data_buf, 0xFF, mtd->writesize); |
|---|
| 1222 | + memset(buf, 0xFF, mtd->writesize); |
|---|
| 1124 | 1223 | |
|---|
| 1125 | | - return marvell_nfc_hw_ecc_hmg_do_write_page(chip, chip->data_buf, |
|---|
| 1126 | | - chip->oob_poi, true, page); |
|---|
| 1224 | + marvell_nfc_select_target(chip, chip->cur_cs); |
|---|
| 1225 | + return marvell_nfc_hw_ecc_hmg_do_write_page(chip, buf, chip->oob_poi, |
|---|
| 1226 | + true, page); |
|---|
| 1127 | 1227 | } |
|---|
| 1128 | 1228 | |
|---|
| 1129 | 1229 | /* BCH read helpers */ |
|---|
| 1130 | | -static int marvell_nfc_hw_ecc_bch_read_page_raw(struct mtd_info *mtd, |
|---|
| 1131 | | - struct nand_chip *chip, u8 *buf, |
|---|
| 1230 | +static int marvell_nfc_hw_ecc_bch_read_page_raw(struct nand_chip *chip, u8 *buf, |
|---|
| 1132 | 1231 | int oob_required, int page) |
|---|
| 1133 | 1232 | { |
|---|
| 1233 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 1134 | 1234 | const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout; |
|---|
| 1135 | 1235 | u8 *oob = chip->oob_poi; |
|---|
| 1136 | 1236 | int chunk_size = lt->data_bytes + lt->spare_bytes + lt->ecc_bytes; |
|---|
| .. | .. |
|---|
| 1140 | 1240 | int spare_len = lt->spare_bytes; |
|---|
| 1141 | 1241 | int ecc_len = lt->ecc_bytes; |
|---|
| 1142 | 1242 | int chunk; |
|---|
| 1243 | + |
|---|
| 1244 | + marvell_nfc_select_target(chip, chip->cur_cs); |
|---|
| 1143 | 1245 | |
|---|
| 1144 | 1246 | if (oob_required) |
|---|
| 1145 | 1247 | memset(chip->oob_poi, 0xFF, mtd->oobsize); |
|---|
| .. | .. |
|---|
| 1161 | 1263 | |
|---|
| 1162 | 1264 | /* Read spare bytes */ |
|---|
| 1163 | 1265 | nand_read_data_op(chip, oob + (lt->spare_bytes * chunk), |
|---|
| 1164 | | - spare_len, false); |
|---|
| 1266 | + spare_len, false, false); |
|---|
| 1165 | 1267 | |
|---|
| 1166 | 1268 | /* Read ECC bytes */ |
|---|
| 1167 | 1269 | nand_read_data_op(chip, oob + ecc_offset + |
|---|
| 1168 | 1270 | (ALIGN(lt->ecc_bytes, 32) * chunk), |
|---|
| 1169 | | - ecc_len, false); |
|---|
| 1271 | + ecc_len, false, false); |
|---|
| 1170 | 1272 | } |
|---|
| 1171 | 1273 | |
|---|
| 1172 | 1274 | return 0; |
|---|
| .. | .. |
|---|
| 1239 | 1341 | } |
|---|
| 1240 | 1342 | } |
|---|
| 1241 | 1343 | |
|---|
| 1242 | | -static int marvell_nfc_hw_ecc_bch_read_page(struct mtd_info *mtd, |
|---|
| 1243 | | - struct nand_chip *chip, |
|---|
| 1344 | +static int marvell_nfc_hw_ecc_bch_read_page(struct nand_chip *chip, |
|---|
| 1244 | 1345 | u8 *buf, int oob_required, |
|---|
| 1245 | 1346 | int page) |
|---|
| 1246 | 1347 | { |
|---|
| 1348 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 1247 | 1349 | const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout; |
|---|
| 1248 | | - int data_len = lt->data_bytes, spare_len = lt->spare_bytes, ecc_len; |
|---|
| 1249 | | - u8 *data = buf, *spare = chip->oob_poi, *ecc; |
|---|
| 1350 | + int data_len = lt->data_bytes, spare_len = lt->spare_bytes; |
|---|
| 1351 | + u8 *data = buf, *spare = chip->oob_poi; |
|---|
| 1250 | 1352 | int max_bitflips = 0; |
|---|
| 1251 | 1353 | u32 failure_mask = 0; |
|---|
| 1252 | | - int chunk, ecc_offset_in_page, ret; |
|---|
| 1354 | + int chunk, ret; |
|---|
| 1355 | + |
|---|
| 1356 | + marvell_nfc_select_target(chip, chip->cur_cs); |
|---|
| 1253 | 1357 | |
|---|
| 1254 | 1358 | /* |
|---|
| 1255 | 1359 | * With BCH, OOB is not fully used (and thus not read entirely), not |
|---|
| .. | .. |
|---|
| 1271 | 1375 | /* Read the chunk and detect number of bitflips */ |
|---|
| 1272 | 1376 | marvell_nfc_hw_ecc_bch_read_chunk(chip, chunk, data, data_len, |
|---|
| 1273 | 1377 | spare, spare_len, page); |
|---|
| 1274 | | - ret = marvell_nfc_hw_ecc_correct(chip, &max_bitflips); |
|---|
| 1378 | + ret = marvell_nfc_hw_ecc_check_bitflips(chip, &max_bitflips); |
|---|
| 1275 | 1379 | if (ret) |
|---|
| 1276 | 1380 | failure_mask |= BIT(chunk); |
|---|
| 1277 | 1381 | |
|---|
| .. | .. |
|---|
| 1290 | 1394 | * the controller in normal mode and must be re-read in raw mode. To |
|---|
| 1291 | 1395 | * avoid dropping the performances, we prefer not to include them. The |
|---|
| 1292 | 1396 | * user should re-read the page in raw mode if ECC bytes are required. |
|---|
| 1397 | + */ |
|---|
| 1398 | + |
|---|
| 1399 | + /* |
|---|
| 1400 | + * In case there is any subpage read error, we usually re-read only ECC |
|---|
| 1401 | + * bytes in raw mode and check if the whole page is empty. In this case, |
|---|
| 1402 | + * it is normal that the ECC check failed and we just ignore the error. |
|---|
| 1293 | 1403 | * |
|---|
| 1294 | | - * However, for any subpage read error reported by ->correct(), the ECC |
|---|
| 1295 | | - * bytes must be read in raw mode and the full subpage must be checked |
|---|
| 1296 | | - * to see if it is entirely empty of if there was an actual error. |
|---|
| 1404 | + * However, it has been empirically observed that for some layouts (e.g |
|---|
| 1405 | + * 2k page, 8b strength per 512B chunk), the controller tries to correct |
|---|
| 1406 | + * bits and may create itself bitflips in the erased area. To overcome |
|---|
| 1407 | + * this strange behavior, the whole page is re-read in raw mode, not |
|---|
| 1408 | + * only the ECC bytes. |
|---|
| 1297 | 1409 | */ |
|---|
| 1298 | 1410 | for (chunk = 0; chunk < lt->nchunks; chunk++) { |
|---|
| 1411 | + int data_off_in_page, spare_off_in_page, ecc_off_in_page; |
|---|
| 1412 | + int data_off, spare_off, ecc_off; |
|---|
| 1413 | + int data_len, spare_len, ecc_len; |
|---|
| 1414 | + |
|---|
| 1299 | 1415 | /* No failure reported for this chunk, move to the next one */ |
|---|
| 1300 | 1416 | if (!(failure_mask & BIT(chunk))) |
|---|
| 1301 | 1417 | continue; |
|---|
| 1302 | 1418 | |
|---|
| 1303 | | - /* Derive ECC bytes positions (in page/buffer) and length */ |
|---|
| 1304 | | - ecc = chip->oob_poi + |
|---|
| 1305 | | - (lt->full_chunk_cnt * lt->spare_bytes) + |
|---|
| 1306 | | - lt->last_spare_bytes + |
|---|
| 1307 | | - (chunk * ALIGN(lt->ecc_bytes, 32)); |
|---|
| 1308 | | - ecc_offset_in_page = |
|---|
| 1309 | | - (chunk * (lt->data_bytes + lt->spare_bytes + |
|---|
| 1310 | | - lt->ecc_bytes)) + |
|---|
| 1311 | | - (chunk < lt->full_chunk_cnt ? |
|---|
| 1312 | | - lt->data_bytes + lt->spare_bytes : |
|---|
| 1313 | | - lt->last_data_bytes + lt->last_spare_bytes); |
|---|
| 1314 | | - ecc_len = chunk < lt->full_chunk_cnt ? |
|---|
| 1315 | | - lt->ecc_bytes : lt->last_ecc_bytes; |
|---|
| 1419 | + data_off_in_page = chunk * (lt->data_bytes + lt->spare_bytes + |
|---|
| 1420 | + lt->ecc_bytes); |
|---|
| 1421 | + spare_off_in_page = data_off_in_page + |
|---|
| 1422 | + (chunk < lt->full_chunk_cnt ? lt->data_bytes : |
|---|
| 1423 | + lt->last_data_bytes); |
|---|
| 1424 | + ecc_off_in_page = spare_off_in_page + |
|---|
| 1425 | + (chunk < lt->full_chunk_cnt ? lt->spare_bytes : |
|---|
| 1426 | + lt->last_spare_bytes); |
|---|
| 1316 | 1427 | |
|---|
| 1317 | | - /* Do the actual raw read of the ECC bytes */ |
|---|
| 1318 | | - nand_change_read_column_op(chip, ecc_offset_in_page, |
|---|
| 1319 | | - ecc, ecc_len, false); |
|---|
| 1428 | + data_off = chunk * lt->data_bytes; |
|---|
| 1429 | + spare_off = chunk * lt->spare_bytes; |
|---|
| 1430 | + ecc_off = (lt->full_chunk_cnt * lt->spare_bytes) + |
|---|
| 1431 | + lt->last_spare_bytes + |
|---|
| 1432 | + (chunk * (lt->ecc_bytes + 2)); |
|---|
| 1320 | 1433 | |
|---|
| 1321 | | - /* Derive data/spare bytes positions (in buffer) and length */ |
|---|
| 1322 | | - data = buf + (chunk * lt->data_bytes); |
|---|
| 1323 | | - data_len = chunk < lt->full_chunk_cnt ? |
|---|
| 1324 | | - lt->data_bytes : lt->last_data_bytes; |
|---|
| 1325 | | - spare = chip->oob_poi + (chunk * (lt->spare_bytes + |
|---|
| 1326 | | - lt->ecc_bytes)); |
|---|
| 1327 | | - spare_len = chunk < lt->full_chunk_cnt ? |
|---|
| 1328 | | - lt->spare_bytes : lt->last_spare_bytes; |
|---|
| 1434 | + data_len = chunk < lt->full_chunk_cnt ? lt->data_bytes : |
|---|
| 1435 | + lt->last_data_bytes; |
|---|
| 1436 | + spare_len = chunk < lt->full_chunk_cnt ? lt->spare_bytes : |
|---|
| 1437 | + lt->last_spare_bytes; |
|---|
| 1438 | + ecc_len = chunk < lt->full_chunk_cnt ? lt->ecc_bytes : |
|---|
| 1439 | + lt->last_ecc_bytes; |
|---|
| 1440 | + |
|---|
| 1441 | + /* |
|---|
| 1442 | + * Only re-read the ECC bytes, unless we are using the 2k/8b |
|---|
| 1443 | + * layout which is buggy in the sense that the ECC engine will |
|---|
| 1444 | + * try to correct data bytes anyway, creating bitflips. In this |
|---|
| 1445 | + * case, re-read the entire page. |
|---|
| 1446 | + */ |
|---|
| 1447 | + if (lt->writesize == 2048 && lt->strength == 8) { |
|---|
| 1448 | + nand_change_read_column_op(chip, data_off_in_page, |
|---|
| 1449 | + buf + data_off, data_len, |
|---|
| 1450 | + false); |
|---|
| 1451 | + nand_change_read_column_op(chip, spare_off_in_page, |
|---|
| 1452 | + chip->oob_poi + spare_off, spare_len, |
|---|
| 1453 | + false); |
|---|
| 1454 | + } |
|---|
| 1455 | + |
|---|
| 1456 | + nand_change_read_column_op(chip, ecc_off_in_page, |
|---|
| 1457 | + chip->oob_poi + ecc_off, ecc_len, |
|---|
| 1458 | + false); |
|---|
| 1329 | 1459 | |
|---|
| 1330 | 1460 | /* Check the entire chunk (data + spare + ecc) for emptyness */ |
|---|
| 1331 | | - marvell_nfc_check_empty_chunk(chip, data, data_len, spare, |
|---|
| 1332 | | - spare_len, ecc, ecc_len, |
|---|
| 1461 | + marvell_nfc_check_empty_chunk(chip, buf + data_off, data_len, |
|---|
| 1462 | + chip->oob_poi + spare_off, spare_len, |
|---|
| 1463 | + chip->oob_poi + ecc_off, ecc_len, |
|---|
| 1333 | 1464 | &max_bitflips); |
|---|
| 1334 | 1465 | } |
|---|
| 1335 | 1466 | |
|---|
| 1336 | 1467 | return max_bitflips; |
|---|
| 1337 | 1468 | } |
|---|
| 1338 | 1469 | |
|---|
| 1339 | | -static int marvell_nfc_hw_ecc_bch_read_oob_raw(struct mtd_info *mtd, |
|---|
| 1340 | | - struct nand_chip *chip, int page) |
|---|
| 1470 | +static int marvell_nfc_hw_ecc_bch_read_oob_raw(struct nand_chip *chip, int page) |
|---|
| 1341 | 1471 | { |
|---|
| 1342 | | - /* Invalidate page cache */ |
|---|
| 1343 | | - chip->pagebuf = -1; |
|---|
| 1472 | + u8 *buf = nand_get_data_buf(chip); |
|---|
| 1344 | 1473 | |
|---|
| 1345 | | - return chip->ecc.read_page_raw(mtd, chip, chip->data_buf, true, page); |
|---|
| 1474 | + return chip->ecc.read_page_raw(chip, buf, true, page); |
|---|
| 1346 | 1475 | } |
|---|
| 1347 | 1476 | |
|---|
| 1348 | | -static int marvell_nfc_hw_ecc_bch_read_oob(struct mtd_info *mtd, |
|---|
| 1349 | | - struct nand_chip *chip, int page) |
|---|
| 1477 | +static int marvell_nfc_hw_ecc_bch_read_oob(struct nand_chip *chip, int page) |
|---|
| 1350 | 1478 | { |
|---|
| 1351 | | - /* Invalidate page cache */ |
|---|
| 1352 | | - chip->pagebuf = -1; |
|---|
| 1479 | + u8 *buf = nand_get_data_buf(chip); |
|---|
| 1353 | 1480 | |
|---|
| 1354 | | - return chip->ecc.read_page(mtd, chip, chip->data_buf, true, page); |
|---|
| 1481 | + return chip->ecc.read_page(chip, buf, true, page); |
|---|
| 1355 | 1482 | } |
|---|
| 1356 | 1483 | |
|---|
| 1357 | 1484 | /* BCH write helpers */ |
|---|
| 1358 | | -static int marvell_nfc_hw_ecc_bch_write_page_raw(struct mtd_info *mtd, |
|---|
| 1359 | | - struct nand_chip *chip, |
|---|
| 1485 | +static int marvell_nfc_hw_ecc_bch_write_page_raw(struct nand_chip *chip, |
|---|
| 1360 | 1486 | const u8 *buf, |
|---|
| 1361 | 1487 | int oob_required, int page) |
|---|
| 1362 | 1488 | { |
|---|
| .. | .. |
|---|
| 1369 | 1495 | int ecc_offset = (lt->full_chunk_cnt * lt->spare_bytes) + |
|---|
| 1370 | 1496 | lt->last_spare_bytes; |
|---|
| 1371 | 1497 | int chunk; |
|---|
| 1498 | + |
|---|
| 1499 | + marvell_nfc_select_target(chip, chip->cur_cs); |
|---|
| 1372 | 1500 | |
|---|
| 1373 | 1501 | nand_prog_page_begin_op(chip, page, 0, NULL, 0); |
|---|
| 1374 | 1502 | |
|---|
| .. | .. |
|---|
| 1469 | 1597 | return 0; |
|---|
| 1470 | 1598 | } |
|---|
| 1471 | 1599 | |
|---|
| 1472 | | -static int marvell_nfc_hw_ecc_bch_write_page(struct mtd_info *mtd, |
|---|
| 1473 | | - struct nand_chip *chip, |
|---|
| 1600 | +static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip, |
|---|
| 1474 | 1601 | const u8 *buf, |
|---|
| 1475 | 1602 | int oob_required, int page) |
|---|
| 1476 | 1603 | { |
|---|
| 1604 | + const struct nand_sdr_timings *sdr = |
|---|
| 1605 | + nand_get_sdr_timings(nand_get_interface_config(chip)); |
|---|
| 1606 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 1477 | 1607 | const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout; |
|---|
| 1478 | 1608 | const u8 *data = buf; |
|---|
| 1479 | 1609 | const u8 *spare = chip->oob_poi; |
|---|
| 1480 | 1610 | int data_len = lt->data_bytes; |
|---|
| 1481 | 1611 | int spare_len = lt->spare_bytes; |
|---|
| 1482 | 1612 | int chunk, ret; |
|---|
| 1613 | + |
|---|
| 1614 | + marvell_nfc_select_target(chip, chip->cur_cs); |
|---|
| 1483 | 1615 | |
|---|
| 1484 | 1616 | /* Spare data will be written anyway, so clear it to avoid garbage */ |
|---|
| 1485 | 1617 | if (!oob_required) |
|---|
| .. | .. |
|---|
| 1507 | 1639 | marvell_nfc_wait_ndrun(chip); |
|---|
| 1508 | 1640 | } |
|---|
| 1509 | 1641 | |
|---|
| 1510 | | - ret = marvell_nfc_wait_op(chip, |
|---|
| 1511 | | - PSEC_TO_MSEC(chip->data_interface.timings.sdr.tPROG_max)); |
|---|
| 1642 | + ret = marvell_nfc_wait_op(chip, PSEC_TO_MSEC(sdr->tPROG_max)); |
|---|
| 1512 | 1643 | |
|---|
| 1513 | 1644 | marvell_nfc_disable_hw_ecc(chip); |
|---|
| 1514 | 1645 | |
|---|
| .. | .. |
|---|
| 1518 | 1649 | return 0; |
|---|
| 1519 | 1650 | } |
|---|
| 1520 | 1651 | |
|---|
| 1521 | | -static int marvell_nfc_hw_ecc_bch_write_oob_raw(struct mtd_info *mtd, |
|---|
| 1522 | | - struct nand_chip *chip, |
|---|
| 1652 | +static int marvell_nfc_hw_ecc_bch_write_oob_raw(struct nand_chip *chip, |
|---|
| 1523 | 1653 | int page) |
|---|
| 1524 | 1654 | { |
|---|
| 1525 | | - /* Invalidate page cache */ |
|---|
| 1526 | | - chip->pagebuf = -1; |
|---|
| 1655 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 1656 | + u8 *buf = nand_get_data_buf(chip); |
|---|
| 1527 | 1657 | |
|---|
| 1528 | | - memset(chip->data_buf, 0xFF, mtd->writesize); |
|---|
| 1658 | + memset(buf, 0xFF, mtd->writesize); |
|---|
| 1529 | 1659 | |
|---|
| 1530 | | - return chip->ecc.write_page_raw(mtd, chip, chip->data_buf, true, page); |
|---|
| 1660 | + return chip->ecc.write_page_raw(chip, buf, true, page); |
|---|
| 1531 | 1661 | } |
|---|
| 1532 | 1662 | |
|---|
| 1533 | | -static int marvell_nfc_hw_ecc_bch_write_oob(struct mtd_info *mtd, |
|---|
| 1534 | | - struct nand_chip *chip, int page) |
|---|
| 1663 | +static int marvell_nfc_hw_ecc_bch_write_oob(struct nand_chip *chip, int page) |
|---|
| 1535 | 1664 | { |
|---|
| 1536 | | - /* Invalidate page cache */ |
|---|
| 1537 | | - chip->pagebuf = -1; |
|---|
| 1665 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 1666 | + u8 *buf = nand_get_data_buf(chip); |
|---|
| 1538 | 1667 | |
|---|
| 1539 | | - memset(chip->data_buf, 0xFF, mtd->writesize); |
|---|
| 1668 | + memset(buf, 0xFF, mtd->writesize); |
|---|
| 1540 | 1669 | |
|---|
| 1541 | | - return chip->ecc.write_page(mtd, chip, chip->data_buf, true, page); |
|---|
| 1670 | + return chip->ecc.write_page(chip, buf, true, page); |
|---|
| 1542 | 1671 | } |
|---|
| 1543 | 1672 | |
|---|
| 1544 | 1673 | /* NAND framework ->exec_op() hooks and related helpers */ |
|---|
| .. | .. |
|---|
| 2017 | 2146 | { |
|---|
| 2018 | 2147 | struct marvell_nfc *nfc = to_marvell_nfc(chip->controller); |
|---|
| 2019 | 2148 | |
|---|
| 2149 | + if (!check_only) |
|---|
| 2150 | + marvell_nfc_select_target(chip, op->cs); |
|---|
| 2151 | + |
|---|
| 2020 | 2152 | if (nfc->caps->is_nfcv2) |
|---|
| 2021 | 2153 | return nand_op_parser_exec_op(chip, &marvell_nfcv2_op_parser, |
|---|
| 2022 | 2154 | op, check_only); |
|---|
| .. | .. |
|---|
| 2074 | 2206 | .free = marvell_nand_ooblayout_free, |
|---|
| 2075 | 2207 | }; |
|---|
| 2076 | 2208 | |
|---|
| 2077 | | -static int marvell_nand_hw_ecc_ctrl_init(struct mtd_info *mtd, |
|---|
| 2078 | | - struct nand_ecc_ctrl *ecc) |
|---|
| 2209 | +static int marvell_nand_hw_ecc_controller_init(struct mtd_info *mtd, |
|---|
| 2210 | + struct nand_ecc_ctrl *ecc) |
|---|
| 2079 | 2211 | { |
|---|
| 2080 | 2212 | struct nand_chip *chip = mtd_to_nand(mtd); |
|---|
| 2081 | 2213 | struct marvell_nfc *nfc = to_marvell_nfc(chip->controller); |
|---|
| .. | .. |
|---|
| 2108 | 2240 | return -ENOTSUPP; |
|---|
| 2109 | 2241 | } |
|---|
| 2110 | 2242 | |
|---|
| 2243 | + /* Special care for the layout 2k/8-bit/512B */ |
|---|
| 2244 | + if (l->writesize == 2048 && l->strength == 8) { |
|---|
| 2245 | + if (mtd->oobsize < 128) { |
|---|
| 2246 | + dev_err(nfc->dev, "Requested layout needs at least 128 OOB bytes\n"); |
|---|
| 2247 | + return -ENOTSUPP; |
|---|
| 2248 | + } else { |
|---|
| 2249 | + chip->bbt_options |= NAND_BBT_NO_OOB_BBM; |
|---|
| 2250 | + } |
|---|
| 2251 | + } |
|---|
| 2252 | + |
|---|
| 2111 | 2253 | mtd_set_ooblayout(mtd, &marvell_nand_ooblayout_ops); |
|---|
| 2112 | 2254 | ecc->steps = l->nchunks; |
|---|
| 2113 | 2255 | ecc->size = l->data_bytes; |
|---|
| 2114 | 2256 | |
|---|
| 2115 | 2257 | if (ecc->strength == 1) { |
|---|
| 2116 | | - chip->ecc.algo = NAND_ECC_HAMMING; |
|---|
| 2258 | + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; |
|---|
| 2117 | 2259 | ecc->read_page_raw = marvell_nfc_hw_ecc_hmg_read_page_raw; |
|---|
| 2118 | 2260 | ecc->read_page = marvell_nfc_hw_ecc_hmg_read_page; |
|---|
| 2119 | 2261 | ecc->read_oob_raw = marvell_nfc_hw_ecc_hmg_read_oob_raw; |
|---|
| .. | .. |
|---|
| 2123 | 2265 | ecc->write_oob_raw = marvell_nfc_hw_ecc_hmg_write_oob_raw; |
|---|
| 2124 | 2266 | ecc->write_oob = ecc->write_oob_raw; |
|---|
| 2125 | 2267 | } else { |
|---|
| 2126 | | - chip->ecc.algo = NAND_ECC_BCH; |
|---|
| 2268 | + chip->ecc.algo = NAND_ECC_ALGO_BCH; |
|---|
| 2127 | 2269 | ecc->strength = 16; |
|---|
| 2128 | 2270 | ecc->read_page_raw = marvell_nfc_hw_ecc_bch_read_page_raw; |
|---|
| 2129 | 2271 | ecc->read_page = marvell_nfc_hw_ecc_bch_read_page; |
|---|
| .. | .. |
|---|
| 2142 | 2284 | struct nand_ecc_ctrl *ecc) |
|---|
| 2143 | 2285 | { |
|---|
| 2144 | 2286 | struct nand_chip *chip = mtd_to_nand(mtd); |
|---|
| 2287 | + const struct nand_ecc_props *requirements = |
|---|
| 2288 | + nanddev_get_ecc_requirements(&chip->base); |
|---|
| 2145 | 2289 | struct marvell_nfc *nfc = to_marvell_nfc(chip->controller); |
|---|
| 2146 | 2290 | int ret; |
|---|
| 2147 | 2291 | |
|---|
| 2148 | | - if (ecc->mode != NAND_ECC_NONE && (!ecc->size || !ecc->strength)) { |
|---|
| 2149 | | - if (chip->ecc_step_ds && chip->ecc_strength_ds) { |
|---|
| 2150 | | - ecc->size = chip->ecc_step_ds; |
|---|
| 2151 | | - ecc->strength = chip->ecc_strength_ds; |
|---|
| 2292 | + if (ecc->engine_type != NAND_ECC_ENGINE_TYPE_NONE && |
|---|
| 2293 | + (!ecc->size || !ecc->strength)) { |
|---|
| 2294 | + if (requirements->step_size && requirements->strength) { |
|---|
| 2295 | + ecc->size = requirements->step_size; |
|---|
| 2296 | + ecc->strength = requirements->strength; |
|---|
| 2152 | 2297 | } else { |
|---|
| 2153 | 2298 | dev_info(nfc->dev, |
|---|
| 2154 | 2299 | "No minimum ECC strength, using 1b/512B\n"); |
|---|
| .. | .. |
|---|
| 2157 | 2302 | } |
|---|
| 2158 | 2303 | } |
|---|
| 2159 | 2304 | |
|---|
| 2160 | | - switch (ecc->mode) { |
|---|
| 2161 | | - case NAND_ECC_HW: |
|---|
| 2162 | | - ret = marvell_nand_hw_ecc_ctrl_init(mtd, ecc); |
|---|
| 2305 | + switch (ecc->engine_type) { |
|---|
| 2306 | + case NAND_ECC_ENGINE_TYPE_ON_HOST: |
|---|
| 2307 | + ret = marvell_nand_hw_ecc_controller_init(mtd, ecc); |
|---|
| 2163 | 2308 | if (ret) |
|---|
| 2164 | 2309 | return ret; |
|---|
| 2165 | 2310 | break; |
|---|
| 2166 | | - case NAND_ECC_NONE: |
|---|
| 2167 | | - case NAND_ECC_SOFT: |
|---|
| 2168 | | - case NAND_ECC_ON_DIE: |
|---|
| 2311 | + case NAND_ECC_ENGINE_TYPE_NONE: |
|---|
| 2312 | + case NAND_ECC_ENGINE_TYPE_SOFT: |
|---|
| 2313 | + case NAND_ECC_ENGINE_TYPE_ON_DIE: |
|---|
| 2169 | 2314 | if (!nfc->caps->is_nfcv2 && mtd->writesize != SZ_512 && |
|---|
| 2170 | 2315 | mtd->writesize != SZ_2K) { |
|---|
| 2171 | 2316 | dev_err(nfc->dev, "NFCv1 cannot write %d bytes pages\n", |
|---|
| .. | .. |
|---|
| 2203 | 2348 | .pattern = bbt_mirror_pattern |
|---|
| 2204 | 2349 | }; |
|---|
| 2205 | 2350 | |
|---|
| 2206 | | -static int marvell_nfc_setup_data_interface(struct mtd_info *mtd, int chipnr, |
|---|
| 2207 | | - const struct nand_data_interface |
|---|
| 2208 | | - *conf) |
|---|
| 2351 | +static int marvell_nfc_setup_interface(struct nand_chip *chip, int chipnr, |
|---|
| 2352 | + const struct nand_interface_config *conf) |
|---|
| 2209 | 2353 | { |
|---|
| 2210 | | - struct nand_chip *chip = mtd_to_nand(mtd); |
|---|
| 2211 | 2354 | struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip); |
|---|
| 2212 | 2355 | struct marvell_nfc *nfc = to_marvell_nfc(chip->controller); |
|---|
| 2213 | 2356 | unsigned int period_ns = 1000000000 / clk_get_rate(nfc->core_clk) * 2; |
|---|
| .. | .. |
|---|
| 2364 | 2507 | return ret; |
|---|
| 2365 | 2508 | } |
|---|
| 2366 | 2509 | |
|---|
| 2367 | | - if (chip->ecc.mode == NAND_ECC_HW) { |
|---|
| 2510 | + if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST) { |
|---|
| 2368 | 2511 | /* |
|---|
| 2369 | 2512 | * Subpage write not available with hardware ECC, prohibit also |
|---|
| 2370 | 2513 | * subpage read as in userspace subpage access would still be |
|---|
| .. | .. |
|---|
| 2406 | 2549 | |
|---|
| 2407 | 2550 | static const struct nand_controller_ops marvell_nand_controller_ops = { |
|---|
| 2408 | 2551 | .attach_chip = marvell_nand_attach_chip, |
|---|
| 2552 | + .exec_op = marvell_nfc_exec_op, |
|---|
| 2553 | + .setup_interface = marvell_nfc_setup_interface, |
|---|
| 2409 | 2554 | }; |
|---|
| 2410 | 2555 | |
|---|
| 2411 | 2556 | static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc, |
|---|
| .. | .. |
|---|
| 2438 | 2583 | } |
|---|
| 2439 | 2584 | |
|---|
| 2440 | 2585 | /* Alloc the nand chip structure */ |
|---|
| 2441 | | - marvell_nand = devm_kzalloc(dev, sizeof(*marvell_nand) + |
|---|
| 2442 | | - (nsels * |
|---|
| 2443 | | - sizeof(struct marvell_nand_chip_sel)), |
|---|
| 2586 | + marvell_nand = devm_kzalloc(dev, |
|---|
| 2587 | + struct_size(marvell_nand, sels, nsels), |
|---|
| 2444 | 2588 | GFP_KERNEL); |
|---|
| 2445 | 2589 | if (!marvell_nand) { |
|---|
| 2446 | 2590 | dev_err(dev, "could not allocate chip structure\n"); |
|---|
| .. | .. |
|---|
| 2528 | 2672 | chip->controller = &nfc->controller; |
|---|
| 2529 | 2673 | nand_set_flash_node(chip, np); |
|---|
| 2530 | 2674 | |
|---|
| 2531 | | - chip->exec_op = marvell_nfc_exec_op; |
|---|
| 2532 | | - chip->select_chip = marvell_nfc_select_chip; |
|---|
| 2533 | | - if (!of_property_read_bool(np, "marvell,nand-keep-config")) |
|---|
| 2534 | | - chip->setup_data_interface = marvell_nfc_setup_data_interface; |
|---|
| 2675 | + if (of_property_read_bool(np, "marvell,nand-keep-config")) |
|---|
| 2676 | + chip->options |= NAND_KEEP_TIMINGS; |
|---|
| 2535 | 2677 | |
|---|
| 2536 | 2678 | mtd = nand_to_mtd(chip); |
|---|
| 2537 | 2679 | mtd->dev.parent = dev; |
|---|
| .. | .. |
|---|
| 2540 | 2682 | * Default to HW ECC engine mode. If the nand-ecc-mode property is given |
|---|
| 2541 | 2683 | * in the DT node, this entry will be overwritten in nand_scan_ident(). |
|---|
| 2542 | 2684 | */ |
|---|
| 2543 | | - chip->ecc.mode = NAND_ECC_HW; |
|---|
| 2685 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; |
|---|
| 2544 | 2686 | |
|---|
| 2545 | 2687 | /* |
|---|
| 2546 | 2688 | * Save a reference value for timing registers before |
|---|
| 2547 | | - * ->setup_data_interface() is called. |
|---|
| 2689 | + * ->setup_interface() is called. |
|---|
| 2548 | 2690 | */ |
|---|
| 2549 | 2691 | marvell_nand->ndtr0 = readl_relaxed(nfc->regs + NDTR0); |
|---|
| 2550 | 2692 | marvell_nand->ndtr1 = readl_relaxed(nfc->regs + NDTR1); |
|---|
| .. | .. |
|---|
| 2576 | 2718 | static void marvell_nand_chips_cleanup(struct marvell_nfc *nfc) |
|---|
| 2577 | 2719 | { |
|---|
| 2578 | 2720 | struct marvell_nand_chip *entry, *temp; |
|---|
| 2721 | + struct nand_chip *chip; |
|---|
| 2722 | + int ret; |
|---|
| 2579 | 2723 | |
|---|
| 2580 | 2724 | list_for_each_entry_safe(entry, temp, &nfc->chips, node) { |
|---|
| 2581 | | - nand_release(&entry->chip); |
|---|
| 2725 | + chip = &entry->chip; |
|---|
| 2726 | + ret = mtd_device_unregister(nand_to_mtd(chip)); |
|---|
| 2727 | + WARN_ON(ret); |
|---|
| 2728 | + nand_cleanup(chip); |
|---|
| 2582 | 2729 | list_del(&entry->node); |
|---|
| 2583 | 2730 | } |
|---|
| 2584 | 2731 | } |
|---|
| .. | .. |
|---|
| 2648 | 2795 | if (ret) |
|---|
| 2649 | 2796 | return ret; |
|---|
| 2650 | 2797 | |
|---|
| 2651 | | - nfc->dma_chan = dma_request_slave_channel(nfc->dev, "data"); |
|---|
| 2652 | | - if (!nfc->dma_chan) { |
|---|
| 2653 | | - dev_err(nfc->dev, |
|---|
| 2654 | | - "Unable to request data DMA channel\n"); |
|---|
| 2655 | | - return -ENODEV; |
|---|
| 2798 | + nfc->dma_chan = dma_request_chan(nfc->dev, "data"); |
|---|
| 2799 | + if (IS_ERR(nfc->dma_chan)) { |
|---|
| 2800 | + ret = PTR_ERR(nfc->dma_chan); |
|---|
| 2801 | + nfc->dma_chan = NULL; |
|---|
| 2802 | + return dev_err_probe(nfc->dev, ret, "DMA channel request failed\n"); |
|---|
| 2656 | 2803 | } |
|---|
| 2657 | 2804 | |
|---|
| 2658 | 2805 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 2659 | | - if (!r) |
|---|
| 2660 | | - return -ENXIO; |
|---|
| 2806 | + if (!r) { |
|---|
| 2807 | + ret = -ENXIO; |
|---|
| 2808 | + goto release_channel; |
|---|
| 2809 | + } |
|---|
| 2661 | 2810 | |
|---|
| 2662 | 2811 | config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
|---|
| 2663 | 2812 | config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
|---|
| .. | .. |
|---|
| 2668 | 2817 | ret = dmaengine_slave_config(nfc->dma_chan, &config); |
|---|
| 2669 | 2818 | if (ret < 0) { |
|---|
| 2670 | 2819 | dev_err(nfc->dev, "Failed to configure DMA channel\n"); |
|---|
| 2671 | | - return ret; |
|---|
| 2820 | + goto release_channel; |
|---|
| 2672 | 2821 | } |
|---|
| 2673 | 2822 | |
|---|
| 2674 | 2823 | /* |
|---|
| .. | .. |
|---|
| 2678 | 2827 | * the provided buffer. |
|---|
| 2679 | 2828 | */ |
|---|
| 2680 | 2829 | nfc->dma_buf = kmalloc(MAX_CHUNK_SIZE, GFP_KERNEL | GFP_DMA); |
|---|
| 2681 | | - if (!nfc->dma_buf) |
|---|
| 2682 | | - return -ENOMEM; |
|---|
| 2830 | + if (!nfc->dma_buf) { |
|---|
| 2831 | + ret = -ENOMEM; |
|---|
| 2832 | + goto release_channel; |
|---|
| 2833 | + } |
|---|
| 2683 | 2834 | |
|---|
| 2684 | 2835 | nfc->use_dma = true; |
|---|
| 2685 | 2836 | |
|---|
| 2686 | 2837 | return 0; |
|---|
| 2838 | + |
|---|
| 2839 | +release_channel: |
|---|
| 2840 | + dma_release_channel(nfc->dma_chan); |
|---|
| 2841 | + nfc->dma_chan = NULL; |
|---|
| 2842 | + |
|---|
| 2843 | + return ret; |
|---|
| 2687 | 2844 | } |
|---|
| 2688 | 2845 | |
|---|
| 2689 | 2846 | static void marvell_nfc_reset(struct marvell_nfc *nfc) |
|---|
| .. | .. |
|---|
| 2746 | 2903 | static int marvell_nfc_probe(struct platform_device *pdev) |
|---|
| 2747 | 2904 | { |
|---|
| 2748 | 2905 | struct device *dev = &pdev->dev; |
|---|
| 2749 | | - struct resource *r; |
|---|
| 2750 | 2906 | struct marvell_nfc *nfc; |
|---|
| 2751 | 2907 | int ret; |
|---|
| 2752 | 2908 | int irq; |
|---|
| .. | .. |
|---|
| 2761 | 2917 | nfc->controller.ops = &marvell_nand_controller_ops; |
|---|
| 2762 | 2918 | INIT_LIST_HEAD(&nfc->chips); |
|---|
| 2763 | 2919 | |
|---|
| 2764 | | - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 2765 | | - nfc->regs = devm_ioremap_resource(dev, r); |
|---|
| 2920 | + nfc->regs = devm_platform_ioremap_resource(pdev, 0); |
|---|
| 2766 | 2921 | if (IS_ERR(nfc->regs)) |
|---|
| 2767 | 2922 | return PTR_ERR(nfc->regs); |
|---|
| 2768 | 2923 | |
|---|
| 2769 | 2924 | irq = platform_get_irq(pdev, 0); |
|---|
| 2770 | | - if (irq < 0) { |
|---|
| 2771 | | - dev_err(dev, "failed to retrieve irq\n"); |
|---|
| 2925 | + if (irq < 0) |
|---|
| 2772 | 2926 | return irq; |
|---|
| 2773 | | - } |
|---|
| 2774 | 2927 | |
|---|
| 2775 | 2928 | nfc->core_clk = devm_clk_get(&pdev->dev, "core"); |
|---|
| 2776 | 2929 | |
|---|
| .. | .. |
|---|
| 2827 | 2980 | |
|---|
| 2828 | 2981 | ret = marvell_nand_chips_init(dev, nfc); |
|---|
| 2829 | 2982 | if (ret) |
|---|
| 2830 | | - goto unprepare_reg_clk; |
|---|
| 2983 | + goto release_dma; |
|---|
| 2831 | 2984 | |
|---|
| 2832 | 2985 | return 0; |
|---|
| 2833 | 2986 | |
|---|
| 2987 | +release_dma: |
|---|
| 2988 | + if (nfc->use_dma) |
|---|
| 2989 | + dma_release_channel(nfc->dma_chan); |
|---|
| 2834 | 2990 | unprepare_reg_clk: |
|---|
| 2835 | 2991 | clk_disable_unprepare(nfc->reg_clk); |
|---|
| 2836 | 2992 | unprepare_core_clk: |
|---|
| .. | .. |
|---|
| 2887 | 3043 | |
|---|
| 2888 | 3044 | /* |
|---|
| 2889 | 3045 | * Reset nfc->selected_chip so the next command will cause the timing |
|---|
| 2890 | | - * registers to be restored in marvell_nfc_select_chip(). |
|---|
| 3046 | + * registers to be restored in marvell_nfc_select_target(). |
|---|
| 2891 | 3047 | */ |
|---|
| 2892 | 3048 | nfc->selected_chip = NULL; |
|---|
| 2893 | 3049 | |
|---|