Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mtd: nand: Support controllers with custom page

If your controller already sends the required NAND commands when
reading or writing a page, then the framework is not supposed to
send READ0 and SEQIN/PAGEPROG respectively.

Signed-off-by: Marc Gonzalez <marc_gonzalez@sigmadesigns.com>
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>

authored by

Marc Gonzalez and committed by
Boris Brezillon
3371d663 fc80f21a

+43 -3
+31 -3
drivers/mtd/nand/nand_base.c
··· 1961 1961 __func__, buf); 1962 1962 1963 1963 read_retry: 1964 - chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); 1964 + if (nand_standard_page_accessors(&chip->ecc)) 1965 + chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); 1965 1966 1966 1967 /* 1967 1968 * Now read the page into the buffer. Absent an error, ··· 2650 2649 else 2651 2650 subpage = 0; 2652 2651 2653 - chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); 2652 + if (nand_standard_page_accessors(&chip->ecc)) 2653 + chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); 2654 2654 2655 2655 if (unlikely(raw)) 2656 2656 status = chip->ecc.write_page_raw(mtd, chip, buf, ··· 2674 2672 2675 2673 if (!cached || !NAND_HAS_CACHEPROG(chip)) { 2676 2674 2677 - chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); 2675 + if (nand_standard_page_accessors(&chip->ecc)) 2676 + chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); 2678 2677 status = chip->waitfunc(mtd, chip); 2679 2678 /* 2680 2679 * See if operation failed and additional status checks are ··· 4514 4511 return corr >= ds_corr && ecc->strength >= chip->ecc_strength_ds; 4515 4512 } 4516 4513 4514 + static bool invalid_ecc_page_accessors(struct nand_chip *chip) 4515 + { 4516 + struct nand_ecc_ctrl *ecc = &chip->ecc; 4517 + 4518 + if (nand_standard_page_accessors(ecc)) 4519 + return false; 4520 + 4521 + /* 4522 + * NAND_ECC_CUSTOM_PAGE_ACCESS flag is set, make sure the NAND 4523 + * controller driver implements all the page accessors because 4524 + * default helpers are not suitable when the core does not 4525 + * send the READ0/PAGEPROG commands. 4526 + */ 4527 + return (!ecc->read_page || !ecc->write_page || 4528 + !ecc->read_page_raw || !ecc->write_page_raw || 4529 + (NAND_HAS_SUBPAGE_READ(chip) && !ecc->read_subpage) || 4530 + (NAND_HAS_SUBPAGE_WRITE(chip) && !ecc->write_subpage && 4531 + ecc->hwctl && ecc->calculate)); 4532 + } 4533 + 4517 4534 /** 4518 4535 * nand_scan_tail - [NAND Interface] Scan for the NAND device 4519 4536 * @mtd: MTD device structure ··· 4553 4530 if (WARN_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && 4554 4531 !(chip->bbt_options & NAND_BBT_USE_FLASH))) 4555 4532 return -EINVAL; 4533 + 4534 + if (invalid_ecc_page_accessors(chip)) { 4535 + pr_err("Invalid ECC page accessors setup\n"); 4536 + return -EINVAL; 4537 + } 4556 4538 4557 4539 if (!(chip->options & NAND_OWN_BUFFERS)) { 4558 4540 nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize
+12
include/linux/mtd/nand.h
··· 142 142 */ 143 143 #define NAND_ECC_GENERIC_ERASED_CHECK BIT(0) 144 144 #define NAND_ECC_MAXIMIZE BIT(1) 145 + /* 146 + * If your controller already sends the required NAND commands when 147 + * reading or writing a page, then the framework is not supposed to 148 + * send READ0 and SEQIN/PAGEPROG respectively. 149 + */ 150 + #define NAND_ECC_CUSTOM_PAGE_ACCESS BIT(2) 145 151 146 152 /* Bit mask for flags passed to do_nand_read_ecc */ 147 153 #define NAND_GET_DEVICE 0x80 ··· 192 186 /* Macros to identify the above */ 193 187 #define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG)) 194 188 #define NAND_HAS_SUBPAGE_READ(chip) ((chip->options & NAND_SUBPAGE_READ)) 189 + #define NAND_HAS_SUBPAGE_WRITE(chip) !((chip)->options & NAND_NO_SUBPAGE_WRITE) 195 190 196 191 /* Non chip related options */ 197 192 /* This option skips the bbt scan during initialization. */ ··· 574 567 int (*write_oob)(struct mtd_info *mtd, struct nand_chip *chip, 575 568 int page); 576 569 }; 570 + 571 + static inline int nand_standard_page_accessors(struct nand_ecc_ctrl *ecc) 572 + { 573 + return !(ecc->options & NAND_ECC_CUSTOM_PAGE_ACCESS); 574 + } 577 575 578 576 /** 579 577 * struct nand_buffers - buffer structure for read/write