/* * this is the callback that the NAND core calls to write a page. Since * writing a page with ECC or without is similar, all the work is done * by write_page above. */ static int denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required, int page) { struct denali_nand_info *denali = mtd_to_denali(mtd); /* * for regular page writes, we let HW handle all the ECC * data written to the device. */ if (oob_required) /* switch to main + spare access */ denali_mode_main_spare_access(denali); else /* switch to main access only */ denali_mode_main_access(denali); return write_page(mtd, chip, buf, false, oob_required); }
/* * This is the callback that the NAND core calls to write a page without ECC. * raw access is similar to ECC page writes, so all the work is done in the * write_page() function above. */ static int denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required) { struct denali_nand_info *denali = mtd_to_denali(mtd); /* * for raw page writes, we want to disable ECC and simply write * whatever data is in the buffer. */ if (oob_required) /* switch to main + spare access */ denali_mode_main_spare_access(denali); else /* switch to main access only */ denali_mode_main_access(denali); return write_page(mtd, chip, buf, true, oob_required); }
static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { struct denali_nand_info *denali = mtd_to_denali(mtd); uint32_t irq_status, irq_mask = INTR_STATUS__DMA_CMD_COMP; if (denali->page != page) { debug("Missing NAND_CMD_READ0 command\n"); return -EIO; } if (oob_required) /* switch to main + spare access */ denali_mode_main_spare_access(denali); else /* switch to main access only */ denali_mode_main_access(denali); /* setting up the DMA where ecc_enable is true */ irq_status = denali_dma_configuration(denali, DENALI_READ, false, irq_mask, oob_required); memcpy(buf, denali->buf.dma_buf, mtd->writesize); /* check whether any ECC error */ if (irq_status & INTR_STATUS__ECC_UNCOR_ERR) { /* is the ECC cause by erase page, check using read_page_raw */ debug(" Uncorrected ECC detected\n"); denali_read_page_raw(mtd, chip, buf, oob_required, denali->page); if (is_erased(buf, mtd->writesize) == true && is_erased(chip->oob_poi, mtd->oobsize) == true) { debug(" ECC error cause by erased block\n"); /* false alarm, return the 0xFF */ } else { return -EBADMSG; } } memcpy(buf, denali->buf.dma_buf, mtd->writesize); return 0; }
/* raw include ECC value and all the spare area */ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { struct denali_nand_info *denali = mtd_to_denali(mtd); uint32_t irq_status, irq_mask = INTR_STATUS__DMA_CMD_COMP; if (denali->page != page) { debug("Missing NAND_CMD_READ0 command\n"); return -EIO; } if (oob_required) /* switch to main + spare access */ denali_mode_main_spare_access(denali); else /* switch to main access only */ denali_mode_main_access(denali); /* setting up the DMA where ecc_enable is false */ irq_status = denali_dma_configuration(denali, DENALI_READ, true, irq_mask, oob_required); /* if timeout happen, error out */ if (!(irq_status & INTR_STATUS__DMA_CMD_COMP)) { debug("DMA timeout for denali_read_page_raw\n"); return -EIO; } /* splitting the content to destination buffer holder */ memcpy(chip->oob_poi, (denali->buf.dma_buf + mtd->writesize), mtd->oobsize); memcpy(buf, denali->buf.dma_buf, mtd->writesize); return 0; }