Loading src/drivers/mtd/nand/pl35x_nand.c +202 −69 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/rawnand.h> #include <linux/mtd/nand_ecc.h> #include <linux/mtd/partitions.h> #include <linux/of_address.h> Loading Loading @@ -171,7 +171,7 @@ static int pl35x_ecc_ooblayout64_ecc(struct mtd_info *mtd, int section, if (section >= chip->ecc.steps) return -ERANGE; oobregion->offset = (section * 16) + 52; oobregion->offset = (section * chip->ecc.bytes) + 52; oobregion->length = chip->ecc.bytes; return 0; Loading @@ -182,10 +182,12 @@ static int pl35x_ecc_ooblayout64_free(struct mtd_info *mtd, int section, { struct nand_chip *chip = mtd_to_nand(mtd); if (section) return -ERANGE; if (section >= chip->ecc.steps) return -ERANGE; oobregion->offset = (section * 16) + 2; oobregion->offset = (section * chip->ecc.bytes) + 2; oobregion->length = 50; Loading Loading @@ -296,7 +298,7 @@ static int pl35x_nand_calculate_hwecc(struct mtd_info *mtd, if (ecc_status & 0x40) { for (ecc_byte = 0; ecc_byte < 3; ecc_byte++) { /* Copy ECC bytes to MTD buffer */ *ecc_code = ecc_value & 0xFF; *ecc_code = ~ecc_value & 0xFF; ecc_value = ecc_value >> 8; ecc_code++; } Loading Loading @@ -386,6 +388,10 @@ static int pl35x_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, unsigned long data_phase_addr; uint8_t *p; struct pl35x_nand_info *xnand = container_of(chip, struct pl35x_nand_info, chip); unsigned long nand_offset = (unsigned long __force)xnand->nand_base; chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); p = chip->oob_poi; Loading @@ -394,7 +400,9 @@ static int pl35x_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, p += (mtd->oobsize - PL35X_NAND_LAST_TRANSFER_LENGTH); data_phase_addr = (unsigned long __force)chip->IO_ADDR_R; data_phase_addr -= nand_offset; data_phase_addr |= PL35X_NAND_CLEAR_CS; data_phase_addr += nand_offset; chip->IO_ADDR_R = (void __iomem * __force)data_phase_addr; chip->read_buf(mtd, p, PL35X_NAND_LAST_TRANSFER_LENGTH); Loading @@ -415,6 +423,9 @@ static int pl35x_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int status = 0; const uint8_t *buf = chip->oob_poi; unsigned long data_phase_addr; struct pl35x_nand_info *xnand = container_of(chip, struct pl35x_nand_info, chip); unsigned long nand_offset = (unsigned long __force)xnand->nand_base; chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page); Loading @@ -423,8 +434,10 @@ static int pl35x_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, buf += (mtd->oobsize - PL35X_NAND_LAST_TRANSFER_LENGTH); data_phase_addr = (unsigned long __force)chip->IO_ADDR_W; data_phase_addr -= nand_offset; data_phase_addr |= PL35X_NAND_CLEAR_CS; data_phase_addr |= (1 << END_CMD_VALID_SHIFT); data_phase_addr += nand_offset; chip->IO_ADDR_W = (void __iomem * __force)data_phase_addr; chip->write_buf(mtd, buf, PL35X_NAND_LAST_TRANSFER_LENGTH); Loading @@ -435,6 +448,79 @@ static int pl35x_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, return (status & NAND_STATUS_FAIL) ? -EIO : 0; } /** * pl35x_nand_read_page_ondie - [Intern] read page data with ondie ecc * @mtd: Pointer to the mtd info structure * @chip: Pointer to the NAND chip info structure * @buf: Pointer to the data buffer * @oob_required: Caller requires OOB data read to chip->oob_poi * @page: Page number to read * * Return: Always return zero */ static int pl35x_nand_read_page_ondie(struct mtd_info *mtd, struct nand_chip *chip, u8 *buf, int oob_required, int page) { unsigned long data_phase_addr; u8 *p; struct pl35x_nand_info *xnand = container_of(chip, struct pl35x_nand_info, chip); unsigned long nand_offset = (unsigned long __force)xnand->nand_base; int status; chip->read_buf(mtd, buf, mtd->writesize); p = chip->oob_poi; chip->read_buf(mtd, p, (mtd->oobsize - PL35X_NAND_LAST_TRANSFER_LENGTH)); p += (mtd->oobsize - PL35X_NAND_LAST_TRANSFER_LENGTH); data_phase_addr = (unsigned long __force)chip->IO_ADDR_R; data_phase_addr -= nand_offset; data_phase_addr |= PL35X_NAND_CLEAR_CS; data_phase_addr += nand_offset; chip->IO_ADDR_R = (void __iomem * __force)data_phase_addr; chip->read_buf(mtd, p, PL35X_NAND_LAST_TRANSFER_LENGTH); /* Check ECC info */ chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); status = (int)chip->read_byte(mtd); if (!(status & NAND_STATUS_READY)) { pr_err("%s: page %d status=%#x - transfer not finished!\n", __func__, page, status); ndelay(100); if (!(status & NAND_STATUS_READY)) return -EIO; } /* UnCorrectable Error bitflips. 5+ on our chip */ #define NAND_UCE_BITS 5 if (status & NAND_STATUS_FAIL) { pr_warn("%s: page %d status=%#x - ECC Uncorrectable Error\n", __func__, page, status); /* * Note: don't return -EIO which means no data and is fatal * during a filesystem mount. * Instead return NAND_UCE_BITS bitflips and increment * the uncorrectable error count. This allows the layer above * (such as UBI) to know data is present but corrupt and to * be safely manage if its only a EC or VI page. */ mtd->ecc_stats.failed++; return NAND_UCE_BITS; } #define NAND_STATUS_ECC_COR BIT(3) /* Correctable error */ if (status & NAND_STATUS_ECC_COR) { pr_info("%s: page %d status=%#x - ECC Correctable error\n", __func__, page, status); mtd->ecc_stats.corrected++; return 1; } return 0; } /** * pl35x_nand_read_page_raw - [Intern] read raw page data without ecc * @mtd: Pointer to the mtd info structure Loading @@ -451,6 +537,9 @@ static int pl35x_nand_read_page_raw(struct mtd_info *mtd, { unsigned long data_phase_addr; uint8_t *p; struct pl35x_nand_info *xnand = container_of(chip, struct pl35x_nand_info, chip); unsigned long nand_offset = (unsigned long __force)xnand->nand_base; chip->read_buf(mtd, buf, mtd->writesize); Loading @@ -460,7 +549,9 @@ static int pl35x_nand_read_page_raw(struct mtd_info *mtd, p += (mtd->oobsize - PL35X_NAND_LAST_TRANSFER_LENGTH); data_phase_addr = (unsigned long __force)chip->IO_ADDR_R; data_phase_addr -= nand_offset; data_phase_addr |= PL35X_NAND_CLEAR_CS; data_phase_addr += nand_offset; chip->IO_ADDR_R = (void __iomem * __force)data_phase_addr; chip->read_buf(mtd, p, PL35X_NAND_LAST_TRANSFER_LENGTH); Loading @@ -473,6 +564,7 @@ static int pl35x_nand_read_page_raw(struct mtd_info *mtd, * @chip: Pointer to the NAND chip info structure * @buf: Pointer to the data buffer * @oob_required: Caller requires OOB data read to chip->oob_poi * @page: Page number to write * * Return: Always return zero */ Loading @@ -483,6 +575,9 @@ static int pl35x_nand_write_page_raw(struct mtd_info *mtd, { unsigned long data_phase_addr; uint8_t *p; struct pl35x_nand_info *xnand = container_of(chip, struct pl35x_nand_info, chip); unsigned long nand_offset = (unsigned long __force)xnand->nand_base; chip->write_buf(mtd, buf, mtd->writesize); Loading @@ -492,8 +587,10 @@ static int pl35x_nand_write_page_raw(struct mtd_info *mtd, p += (mtd->oobsize - PL35X_NAND_LAST_TRANSFER_LENGTH); data_phase_addr = (unsigned long __force)chip->IO_ADDR_W; data_phase_addr -= nand_offset; data_phase_addr |= PL35X_NAND_CLEAR_CS; data_phase_addr |= (1 << END_CMD_VALID_SHIFT); data_phase_addr += nand_offset; chip->IO_ADDR_W = (void __iomem * __force)data_phase_addr; chip->write_buf(mtd, p, PL35X_NAND_LAST_TRANSFER_LENGTH); Loading @@ -507,6 +604,7 @@ static int pl35x_nand_write_page_raw(struct mtd_info *mtd, * @chip: Pointer to the NAND chip info structure * @buf: Pointer to the data buffer * @oob_required: Caller requires OOB data read to chip->oob_poi * @page: Page number to write * * This functions writes data and hardware generated ECC values in to the page. * Loading @@ -523,6 +621,9 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd, unsigned long data_phase_addr; uint8_t *oob_ptr; u32 ret; struct pl35x_nand_info *xnand = container_of(chip, struct pl35x_nand_info, chip); unsigned long nand_offset = (unsigned long __force)xnand->nand_base; for ( ; (eccsteps - 1); eccsteps--) { chip->write_buf(mtd, p, eccsize); Loading @@ -533,7 +634,9 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd, /* Set ECC Last bit to 1 */ data_phase_addr = (unsigned long __force)chip->IO_ADDR_W; data_phase_addr -= nand_offset; data_phase_addr |= PL35X_NAND_ECC_LAST; data_phase_addr += nand_offset; chip->IO_ADDR_W = (void __iomem * __force)data_phase_addr; chip->write_buf(mtd, p, PL35X_NAND_LAST_TRANSFER_LENGTH); Loading @@ -547,7 +650,9 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd, return ret; /* Clear ECC last bit */ data_phase_addr = (unsigned long __force)chip->IO_ADDR_W; data_phase_addr -= nand_offset; data_phase_addr &= ~PL35X_NAND_ECC_LAST; data_phase_addr += nand_offset; chip->IO_ADDR_W = (void __iomem * __force)data_phase_addr; /* Write the spare area with ECC bytes */ Loading @@ -556,8 +661,10 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd, (mtd->oobsize - PL35X_NAND_LAST_TRANSFER_LENGTH)); data_phase_addr = (unsigned long __force)chip->IO_ADDR_W; data_phase_addr -= nand_offset; data_phase_addr |= PL35X_NAND_CLEAR_CS; data_phase_addr |= (1 << END_CMD_VALID_SHIFT); data_phase_addr += nand_offset; chip->IO_ADDR_W = (void __iomem * __force)data_phase_addr; oob_ptr += (mtd->oobsize - PL35X_NAND_LAST_TRANSFER_LENGTH); chip->write_buf(mtd, oob_ptr, PL35X_NAND_LAST_TRANSFER_LENGTH); Loading @@ -571,6 +678,7 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd, * @chip: Pointer to the NAND chip info structure * @buf: Pointer to the data buffer * @oob_required: Caller requires OOB data read to chip->oob_poi * @page: Page number to write * * Return: Always return zero */ Loading Loading @@ -623,6 +731,9 @@ static int pl35x_nand_read_page_hwecc(struct mtd_info *mtd, unsigned long data_phase_addr; uint8_t *oob_ptr; u32 ret; struct pl35x_nand_info *xnand = container_of(chip, struct pl35x_nand_info, chip); unsigned long nand_offset = (unsigned long __force)xnand->nand_base; for ( ; (eccsteps - 1); eccsteps--) { chip->read_buf(mtd, p, eccsize); Loading @@ -633,7 +744,9 @@ static int pl35x_nand_read_page_hwecc(struct mtd_info *mtd, /* Set ECC Last bit to 1 */ data_phase_addr = (unsigned long __force)chip->IO_ADDR_R; data_phase_addr -= nand_offset; data_phase_addr |= PL35X_NAND_ECC_LAST; data_phase_addr += nand_offset; chip->IO_ADDR_R = (void __iomem * __force)data_phase_addr; chip->read_buf(mtd, p, PL35X_NAND_LAST_TRANSFER_LENGTH); Loading @@ -643,7 +756,9 @@ static int pl35x_nand_read_page_hwecc(struct mtd_info *mtd, /* Clear ECC last bit */ data_phase_addr = (unsigned long __force)chip->IO_ADDR_R; data_phase_addr -= nand_offset; data_phase_addr &= ~PL35X_NAND_ECC_LAST; data_phase_addr += nand_offset; chip->IO_ADDR_R = (void __iomem * __force)data_phase_addr; /* Read the stored ECC value */ Loading @@ -653,7 +768,9 @@ static int pl35x_nand_read_page_hwecc(struct mtd_info *mtd, /* de-assert chip select */ data_phase_addr = (unsigned long __force)chip->IO_ADDR_R; data_phase_addr -= nand_offset; data_phase_addr |= PL35X_NAND_CLEAR_CS; data_phase_addr += nand_offset; chip->IO_ADDR_R = (void __iomem * __force)data_phase_addr; oob_ptr += (mtd->oobsize - PL35X_NAND_LAST_TRANSFER_LENGTH); Loading Loading @@ -707,6 +824,8 @@ static int pl35x_nand_read_page_swecc(struct mtd_info *mtd, ret = mtd_ooblayout_get_eccbytes(mtd, ecc_calc, chip->oob_poi, 0, chip->ecc.total); if (ret) return ret; eccsteps = chip->ecc.steps; p = buf; Loading @@ -726,14 +845,34 @@ static int pl35x_nand_read_page_swecc(struct mtd_info *mtd, /** * pl35x_nand_select_chip - Select the flash device * @mtd: Pointer to the mtd info structure * @chip: Pointer to the NAND chip info structure * @chipnr: chipnumber to select, -1 for deselect * * This function is empty as the NAND controller handles chip select line * internally based on the chip address passed in command and data phase. */ static void pl35x_nand_select_chip(struct mtd_info *mtd, int chip) static void pl35x_nand_select_chip(struct mtd_info *mtd, int chipnr) { unsigned long data_phase_addr; struct pl35x_nand_info *xnand; unsigned long nand_offset; struct nand_chip *chip; /* * Chip selection will happen in command/data operation */ if (chipnr >= 0) return; /* de-assert chip select */ chip = mtd_to_nand(mtd); data_phase_addr = (unsigned long __force)chip->IO_ADDR_R; xnand = container_of(chip, struct pl35x_nand_info, chip); nand_offset = (unsigned long __force)xnand->nand_base; data_phase_addr -= nand_offset; data_phase_addr |= PL35X_NAND_CLEAR_CS; data_phase_addr += nand_offset; chip->IO_ADDR_R = (void __iomem * __force)data_phase_addr; chip->read_byte(mtd); } /** Loading @@ -746,11 +885,6 @@ static void pl35x_nand_select_chip(struct mtd_info *mtd, int chip) static void pl35x_nand_cmd_function(struct mtd_info *mtd, unsigned int command, int column, int page_addr) { if (command == NAND_CMD_READ0) pr_debug("NAND READ\n"); if (command == NAND_CMD_UNLOCK1) pr_debug("NAND UNLOCK1\n"); if (command == NAND_CMD_SET_FEATURES) pr_debug("NAND NAND_CMD_SET_FEATURES\n"); struct nand_chip *chip = mtd_to_nand(mtd); const struct pl35x_nand_command_format *curr_cmd = NULL; struct pl35x_nand_info *xnand = Loading Loading @@ -808,24 +942,24 @@ static void pl35x_nand_cmd_function(struct mtd_info *mtd, unsigned int command, else addrcycles = curr_cmd->addr_cycles; cmd_phase_addr = (unsigned long __force)xnand->nand_base | cmd_phase_addr = (unsigned long __force)xnand->nand_base + ( (addrcycles << ADDR_CYCLES_SHIFT) | (end_cmd_valid << END_CMD_VALID_SHIFT) | (COMMAND_PHASE) | (end_cmd << END_CMD_SHIFT) | (curr_cmd->start_cmd << START_CMD_SHIFT); (curr_cmd->start_cmd << START_CMD_SHIFT)); cmd_addr = (void __iomem * __force)cmd_phase_addr; /* Get the data phase address */ end_cmd_valid = 0; data_phase_addr = (unsigned long __force)xnand->nand_base | data_phase_addr = (unsigned long __force)xnand->nand_base + ( (0x0 << CLEAR_CS_SHIFT) | (end_cmd_valid << END_CMD_VALID_SHIFT) | (DATA_PHASE) | (end_cmd << END_CMD_SHIFT) | (0x0 << ECC_LAST_SHIFT); (0x0 << ECC_LAST_SHIFT)); chip->IO_ADDR_R = (void __iomem * __force)data_phase_addr; chip->IO_ADDR_W = chip->IO_ADDR_R; Loading Loading @@ -922,8 +1056,6 @@ static void pl35x_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, struct nand_chip *chip = mtd_to_nand(mtd); unsigned long *ptr = (unsigned long *)buf; pr_debug("pl35x_nand_write_buf: datasize=%d len=%d len>>2=%d\n",sizeof(ptr[0]),len,len>>2); len >>= 2; for (i = 0; i < len; i++) Loading Loading @@ -1072,6 +1204,7 @@ static int pl35x_nand_detect_ondie_ecc(struct mtd_info *mtd) /** * pl35x_nand_ecc_init - Initialize the ecc information as per the ecc mode * @mtd: Pointer to the mtd_info structure * @ecc: Pointer to ECC control structure * @ondie_ecc_state: ondie ecc status * * This function initializes the ecc block and functional pointers as per the Loading Loading @@ -1099,7 +1232,7 @@ static void pl35x_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc, */ ecc->bytes = 0; mtd_set_ooblayout(mtd, &fsmc_ecc_ooblayout_ondie64_ops); ecc->read_page = pl35x_nand_read_page_raw; ecc->read_page = pl35x_nand_read_page_ondie; ecc->write_page = pl35x_nand_write_page_raw; ecc->size = mtd->writesize; /* Loading Loading @@ -1188,9 +1321,10 @@ static int pl35x_nand_probe(struct platform_device *pdev) nand_chip->cmdfunc = pl35x_nand_cmd_function; nand_chip->dev_ready = pl35x_nand_device_ready; nand_chip->select_chip = pl35x_nand_select_chip; nand_chip->onfi_set_features = pl35x_nand_onfi_set_features; nand_chip->onfi_get_features = pl35x_nand_onfi_get_features; //nand_chip->onfi_set_features = nand_onfi_get_set_features_notsupp; //nand_chip->onfi_get_features = nand_onfi_get_set_features_notsupp; /* If we don't set this delay driver sets 20us by default */ nand_chip->chip_delay = 30; Loading Loading @@ -1273,7 +1407,6 @@ static struct platform_driver pl35x_nand_driver = { .remove = pl35x_nand_remove, .driver = { .name = PL35X_NAND_DRIVER_NAME, .owner = THIS_MODULE, .of_match_table = pl35x_nand_of_match, }, }; Loading Loading
src/drivers/mtd/nand/pl35x_nand.c +202 −69 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/rawnand.h> #include <linux/mtd/nand_ecc.h> #include <linux/mtd/partitions.h> #include <linux/of_address.h> Loading Loading @@ -171,7 +171,7 @@ static int pl35x_ecc_ooblayout64_ecc(struct mtd_info *mtd, int section, if (section >= chip->ecc.steps) return -ERANGE; oobregion->offset = (section * 16) + 52; oobregion->offset = (section * chip->ecc.bytes) + 52; oobregion->length = chip->ecc.bytes; return 0; Loading @@ -182,10 +182,12 @@ static int pl35x_ecc_ooblayout64_free(struct mtd_info *mtd, int section, { struct nand_chip *chip = mtd_to_nand(mtd); if (section) return -ERANGE; if (section >= chip->ecc.steps) return -ERANGE; oobregion->offset = (section * 16) + 2; oobregion->offset = (section * chip->ecc.bytes) + 2; oobregion->length = 50; Loading Loading @@ -296,7 +298,7 @@ static int pl35x_nand_calculate_hwecc(struct mtd_info *mtd, if (ecc_status & 0x40) { for (ecc_byte = 0; ecc_byte < 3; ecc_byte++) { /* Copy ECC bytes to MTD buffer */ *ecc_code = ecc_value & 0xFF; *ecc_code = ~ecc_value & 0xFF; ecc_value = ecc_value >> 8; ecc_code++; } Loading Loading @@ -386,6 +388,10 @@ static int pl35x_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, unsigned long data_phase_addr; uint8_t *p; struct pl35x_nand_info *xnand = container_of(chip, struct pl35x_nand_info, chip); unsigned long nand_offset = (unsigned long __force)xnand->nand_base; chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); p = chip->oob_poi; Loading @@ -394,7 +400,9 @@ static int pl35x_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, p += (mtd->oobsize - PL35X_NAND_LAST_TRANSFER_LENGTH); data_phase_addr = (unsigned long __force)chip->IO_ADDR_R; data_phase_addr -= nand_offset; data_phase_addr |= PL35X_NAND_CLEAR_CS; data_phase_addr += nand_offset; chip->IO_ADDR_R = (void __iomem * __force)data_phase_addr; chip->read_buf(mtd, p, PL35X_NAND_LAST_TRANSFER_LENGTH); Loading @@ -415,6 +423,9 @@ static int pl35x_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int status = 0; const uint8_t *buf = chip->oob_poi; unsigned long data_phase_addr; struct pl35x_nand_info *xnand = container_of(chip, struct pl35x_nand_info, chip); unsigned long nand_offset = (unsigned long __force)xnand->nand_base; chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page); Loading @@ -423,8 +434,10 @@ static int pl35x_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, buf += (mtd->oobsize - PL35X_NAND_LAST_TRANSFER_LENGTH); data_phase_addr = (unsigned long __force)chip->IO_ADDR_W; data_phase_addr -= nand_offset; data_phase_addr |= PL35X_NAND_CLEAR_CS; data_phase_addr |= (1 << END_CMD_VALID_SHIFT); data_phase_addr += nand_offset; chip->IO_ADDR_W = (void __iomem * __force)data_phase_addr; chip->write_buf(mtd, buf, PL35X_NAND_LAST_TRANSFER_LENGTH); Loading @@ -435,6 +448,79 @@ static int pl35x_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, return (status & NAND_STATUS_FAIL) ? -EIO : 0; } /** * pl35x_nand_read_page_ondie - [Intern] read page data with ondie ecc * @mtd: Pointer to the mtd info structure * @chip: Pointer to the NAND chip info structure * @buf: Pointer to the data buffer * @oob_required: Caller requires OOB data read to chip->oob_poi * @page: Page number to read * * Return: Always return zero */ static int pl35x_nand_read_page_ondie(struct mtd_info *mtd, struct nand_chip *chip, u8 *buf, int oob_required, int page) { unsigned long data_phase_addr; u8 *p; struct pl35x_nand_info *xnand = container_of(chip, struct pl35x_nand_info, chip); unsigned long nand_offset = (unsigned long __force)xnand->nand_base; int status; chip->read_buf(mtd, buf, mtd->writesize); p = chip->oob_poi; chip->read_buf(mtd, p, (mtd->oobsize - PL35X_NAND_LAST_TRANSFER_LENGTH)); p += (mtd->oobsize - PL35X_NAND_LAST_TRANSFER_LENGTH); data_phase_addr = (unsigned long __force)chip->IO_ADDR_R; data_phase_addr -= nand_offset; data_phase_addr |= PL35X_NAND_CLEAR_CS; data_phase_addr += nand_offset; chip->IO_ADDR_R = (void __iomem * __force)data_phase_addr; chip->read_buf(mtd, p, PL35X_NAND_LAST_TRANSFER_LENGTH); /* Check ECC info */ chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); status = (int)chip->read_byte(mtd); if (!(status & NAND_STATUS_READY)) { pr_err("%s: page %d status=%#x - transfer not finished!\n", __func__, page, status); ndelay(100); if (!(status & NAND_STATUS_READY)) return -EIO; } /* UnCorrectable Error bitflips. 5+ on our chip */ #define NAND_UCE_BITS 5 if (status & NAND_STATUS_FAIL) { pr_warn("%s: page %d status=%#x - ECC Uncorrectable Error\n", __func__, page, status); /* * Note: don't return -EIO which means no data and is fatal * during a filesystem mount. * Instead return NAND_UCE_BITS bitflips and increment * the uncorrectable error count. This allows the layer above * (such as UBI) to know data is present but corrupt and to * be safely manage if its only a EC or VI page. */ mtd->ecc_stats.failed++; return NAND_UCE_BITS; } #define NAND_STATUS_ECC_COR BIT(3) /* Correctable error */ if (status & NAND_STATUS_ECC_COR) { pr_info("%s: page %d status=%#x - ECC Correctable error\n", __func__, page, status); mtd->ecc_stats.corrected++; return 1; } return 0; } /** * pl35x_nand_read_page_raw - [Intern] read raw page data without ecc * @mtd: Pointer to the mtd info structure Loading @@ -451,6 +537,9 @@ static int pl35x_nand_read_page_raw(struct mtd_info *mtd, { unsigned long data_phase_addr; uint8_t *p; struct pl35x_nand_info *xnand = container_of(chip, struct pl35x_nand_info, chip); unsigned long nand_offset = (unsigned long __force)xnand->nand_base; chip->read_buf(mtd, buf, mtd->writesize); Loading @@ -460,7 +549,9 @@ static int pl35x_nand_read_page_raw(struct mtd_info *mtd, p += (mtd->oobsize - PL35X_NAND_LAST_TRANSFER_LENGTH); data_phase_addr = (unsigned long __force)chip->IO_ADDR_R; data_phase_addr -= nand_offset; data_phase_addr |= PL35X_NAND_CLEAR_CS; data_phase_addr += nand_offset; chip->IO_ADDR_R = (void __iomem * __force)data_phase_addr; chip->read_buf(mtd, p, PL35X_NAND_LAST_TRANSFER_LENGTH); Loading @@ -473,6 +564,7 @@ static int pl35x_nand_read_page_raw(struct mtd_info *mtd, * @chip: Pointer to the NAND chip info structure * @buf: Pointer to the data buffer * @oob_required: Caller requires OOB data read to chip->oob_poi * @page: Page number to write * * Return: Always return zero */ Loading @@ -483,6 +575,9 @@ static int pl35x_nand_write_page_raw(struct mtd_info *mtd, { unsigned long data_phase_addr; uint8_t *p; struct pl35x_nand_info *xnand = container_of(chip, struct pl35x_nand_info, chip); unsigned long nand_offset = (unsigned long __force)xnand->nand_base; chip->write_buf(mtd, buf, mtd->writesize); Loading @@ -492,8 +587,10 @@ static int pl35x_nand_write_page_raw(struct mtd_info *mtd, p += (mtd->oobsize - PL35X_NAND_LAST_TRANSFER_LENGTH); data_phase_addr = (unsigned long __force)chip->IO_ADDR_W; data_phase_addr -= nand_offset; data_phase_addr |= PL35X_NAND_CLEAR_CS; data_phase_addr |= (1 << END_CMD_VALID_SHIFT); data_phase_addr += nand_offset; chip->IO_ADDR_W = (void __iomem * __force)data_phase_addr; chip->write_buf(mtd, p, PL35X_NAND_LAST_TRANSFER_LENGTH); Loading @@ -507,6 +604,7 @@ static int pl35x_nand_write_page_raw(struct mtd_info *mtd, * @chip: Pointer to the NAND chip info structure * @buf: Pointer to the data buffer * @oob_required: Caller requires OOB data read to chip->oob_poi * @page: Page number to write * * This functions writes data and hardware generated ECC values in to the page. * Loading @@ -523,6 +621,9 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd, unsigned long data_phase_addr; uint8_t *oob_ptr; u32 ret; struct pl35x_nand_info *xnand = container_of(chip, struct pl35x_nand_info, chip); unsigned long nand_offset = (unsigned long __force)xnand->nand_base; for ( ; (eccsteps - 1); eccsteps--) { chip->write_buf(mtd, p, eccsize); Loading @@ -533,7 +634,9 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd, /* Set ECC Last bit to 1 */ data_phase_addr = (unsigned long __force)chip->IO_ADDR_W; data_phase_addr -= nand_offset; data_phase_addr |= PL35X_NAND_ECC_LAST; data_phase_addr += nand_offset; chip->IO_ADDR_W = (void __iomem * __force)data_phase_addr; chip->write_buf(mtd, p, PL35X_NAND_LAST_TRANSFER_LENGTH); Loading @@ -547,7 +650,9 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd, return ret; /* Clear ECC last bit */ data_phase_addr = (unsigned long __force)chip->IO_ADDR_W; data_phase_addr -= nand_offset; data_phase_addr &= ~PL35X_NAND_ECC_LAST; data_phase_addr += nand_offset; chip->IO_ADDR_W = (void __iomem * __force)data_phase_addr; /* Write the spare area with ECC bytes */ Loading @@ -556,8 +661,10 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd, (mtd->oobsize - PL35X_NAND_LAST_TRANSFER_LENGTH)); data_phase_addr = (unsigned long __force)chip->IO_ADDR_W; data_phase_addr -= nand_offset; data_phase_addr |= PL35X_NAND_CLEAR_CS; data_phase_addr |= (1 << END_CMD_VALID_SHIFT); data_phase_addr += nand_offset; chip->IO_ADDR_W = (void __iomem * __force)data_phase_addr; oob_ptr += (mtd->oobsize - PL35X_NAND_LAST_TRANSFER_LENGTH); chip->write_buf(mtd, oob_ptr, PL35X_NAND_LAST_TRANSFER_LENGTH); Loading @@ -571,6 +678,7 @@ static int pl35x_nand_write_page_hwecc(struct mtd_info *mtd, * @chip: Pointer to the NAND chip info structure * @buf: Pointer to the data buffer * @oob_required: Caller requires OOB data read to chip->oob_poi * @page: Page number to write * * Return: Always return zero */ Loading Loading @@ -623,6 +731,9 @@ static int pl35x_nand_read_page_hwecc(struct mtd_info *mtd, unsigned long data_phase_addr; uint8_t *oob_ptr; u32 ret; struct pl35x_nand_info *xnand = container_of(chip, struct pl35x_nand_info, chip); unsigned long nand_offset = (unsigned long __force)xnand->nand_base; for ( ; (eccsteps - 1); eccsteps--) { chip->read_buf(mtd, p, eccsize); Loading @@ -633,7 +744,9 @@ static int pl35x_nand_read_page_hwecc(struct mtd_info *mtd, /* Set ECC Last bit to 1 */ data_phase_addr = (unsigned long __force)chip->IO_ADDR_R; data_phase_addr -= nand_offset; data_phase_addr |= PL35X_NAND_ECC_LAST; data_phase_addr += nand_offset; chip->IO_ADDR_R = (void __iomem * __force)data_phase_addr; chip->read_buf(mtd, p, PL35X_NAND_LAST_TRANSFER_LENGTH); Loading @@ -643,7 +756,9 @@ static int pl35x_nand_read_page_hwecc(struct mtd_info *mtd, /* Clear ECC last bit */ data_phase_addr = (unsigned long __force)chip->IO_ADDR_R; data_phase_addr -= nand_offset; data_phase_addr &= ~PL35X_NAND_ECC_LAST; data_phase_addr += nand_offset; chip->IO_ADDR_R = (void __iomem * __force)data_phase_addr; /* Read the stored ECC value */ Loading @@ -653,7 +768,9 @@ static int pl35x_nand_read_page_hwecc(struct mtd_info *mtd, /* de-assert chip select */ data_phase_addr = (unsigned long __force)chip->IO_ADDR_R; data_phase_addr -= nand_offset; data_phase_addr |= PL35X_NAND_CLEAR_CS; data_phase_addr += nand_offset; chip->IO_ADDR_R = (void __iomem * __force)data_phase_addr; oob_ptr += (mtd->oobsize - PL35X_NAND_LAST_TRANSFER_LENGTH); Loading Loading @@ -707,6 +824,8 @@ static int pl35x_nand_read_page_swecc(struct mtd_info *mtd, ret = mtd_ooblayout_get_eccbytes(mtd, ecc_calc, chip->oob_poi, 0, chip->ecc.total); if (ret) return ret; eccsteps = chip->ecc.steps; p = buf; Loading @@ -726,14 +845,34 @@ static int pl35x_nand_read_page_swecc(struct mtd_info *mtd, /** * pl35x_nand_select_chip - Select the flash device * @mtd: Pointer to the mtd info structure * @chip: Pointer to the NAND chip info structure * @chipnr: chipnumber to select, -1 for deselect * * This function is empty as the NAND controller handles chip select line * internally based on the chip address passed in command and data phase. */ static void pl35x_nand_select_chip(struct mtd_info *mtd, int chip) static void pl35x_nand_select_chip(struct mtd_info *mtd, int chipnr) { unsigned long data_phase_addr; struct pl35x_nand_info *xnand; unsigned long nand_offset; struct nand_chip *chip; /* * Chip selection will happen in command/data operation */ if (chipnr >= 0) return; /* de-assert chip select */ chip = mtd_to_nand(mtd); data_phase_addr = (unsigned long __force)chip->IO_ADDR_R; xnand = container_of(chip, struct pl35x_nand_info, chip); nand_offset = (unsigned long __force)xnand->nand_base; data_phase_addr -= nand_offset; data_phase_addr |= PL35X_NAND_CLEAR_CS; data_phase_addr += nand_offset; chip->IO_ADDR_R = (void __iomem * __force)data_phase_addr; chip->read_byte(mtd); } /** Loading @@ -746,11 +885,6 @@ static void pl35x_nand_select_chip(struct mtd_info *mtd, int chip) static void pl35x_nand_cmd_function(struct mtd_info *mtd, unsigned int command, int column, int page_addr) { if (command == NAND_CMD_READ0) pr_debug("NAND READ\n"); if (command == NAND_CMD_UNLOCK1) pr_debug("NAND UNLOCK1\n"); if (command == NAND_CMD_SET_FEATURES) pr_debug("NAND NAND_CMD_SET_FEATURES\n"); struct nand_chip *chip = mtd_to_nand(mtd); const struct pl35x_nand_command_format *curr_cmd = NULL; struct pl35x_nand_info *xnand = Loading Loading @@ -808,24 +942,24 @@ static void pl35x_nand_cmd_function(struct mtd_info *mtd, unsigned int command, else addrcycles = curr_cmd->addr_cycles; cmd_phase_addr = (unsigned long __force)xnand->nand_base | cmd_phase_addr = (unsigned long __force)xnand->nand_base + ( (addrcycles << ADDR_CYCLES_SHIFT) | (end_cmd_valid << END_CMD_VALID_SHIFT) | (COMMAND_PHASE) | (end_cmd << END_CMD_SHIFT) | (curr_cmd->start_cmd << START_CMD_SHIFT); (curr_cmd->start_cmd << START_CMD_SHIFT)); cmd_addr = (void __iomem * __force)cmd_phase_addr; /* Get the data phase address */ end_cmd_valid = 0; data_phase_addr = (unsigned long __force)xnand->nand_base | data_phase_addr = (unsigned long __force)xnand->nand_base + ( (0x0 << CLEAR_CS_SHIFT) | (end_cmd_valid << END_CMD_VALID_SHIFT) | (DATA_PHASE) | (end_cmd << END_CMD_SHIFT) | (0x0 << ECC_LAST_SHIFT); (0x0 << ECC_LAST_SHIFT)); chip->IO_ADDR_R = (void __iomem * __force)data_phase_addr; chip->IO_ADDR_W = chip->IO_ADDR_R; Loading Loading @@ -922,8 +1056,6 @@ static void pl35x_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, struct nand_chip *chip = mtd_to_nand(mtd); unsigned long *ptr = (unsigned long *)buf; pr_debug("pl35x_nand_write_buf: datasize=%d len=%d len>>2=%d\n",sizeof(ptr[0]),len,len>>2); len >>= 2; for (i = 0; i < len; i++) Loading Loading @@ -1072,6 +1204,7 @@ static int pl35x_nand_detect_ondie_ecc(struct mtd_info *mtd) /** * pl35x_nand_ecc_init - Initialize the ecc information as per the ecc mode * @mtd: Pointer to the mtd_info structure * @ecc: Pointer to ECC control structure * @ondie_ecc_state: ondie ecc status * * This function initializes the ecc block and functional pointers as per the Loading Loading @@ -1099,7 +1232,7 @@ static void pl35x_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc, */ ecc->bytes = 0; mtd_set_ooblayout(mtd, &fsmc_ecc_ooblayout_ondie64_ops); ecc->read_page = pl35x_nand_read_page_raw; ecc->read_page = pl35x_nand_read_page_ondie; ecc->write_page = pl35x_nand_write_page_raw; ecc->size = mtd->writesize; /* Loading Loading @@ -1188,9 +1321,10 @@ static int pl35x_nand_probe(struct platform_device *pdev) nand_chip->cmdfunc = pl35x_nand_cmd_function; nand_chip->dev_ready = pl35x_nand_device_ready; nand_chip->select_chip = pl35x_nand_select_chip; nand_chip->onfi_set_features = pl35x_nand_onfi_set_features; nand_chip->onfi_get_features = pl35x_nand_onfi_get_features; //nand_chip->onfi_set_features = nand_onfi_get_set_features_notsupp; //nand_chip->onfi_get_features = nand_onfi_get_set_features_notsupp; /* If we don't set this delay driver sets 20us by default */ nand_chip->chip_delay = 30; Loading Loading @@ -1273,7 +1407,6 @@ static struct platform_driver pl35x_nand_driver = { .remove = pl35x_nand_remove, .driver = { .name = PL35X_NAND_DRIVER_NAME, .owner = THIS_MODULE, .of_match_table = pl35x_nand_of_match, }, }; Loading