@ -14,7 +14,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
drivers/mtd/nand/mtk_nand2.c | 2304 +++++++++++++++++++++++++++++++++++
drivers/mtd/nand/mtk_nand2.h | 452 +++++++
drivers/mtd/nand/nand_base.c | 6 +-
drivers/mtd/nand/nand_bbt.c | 19 +
drivers/mtd/nand/nand_def.h | 123 ++
drivers/mtd/nand/nand_device_list.h | 55 +
drivers/mtd/nand/partition.h | 115 ++
@ -1299,7 +1298,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+
--- /dev/null
+++ b/drivers/mtd/nand/mtk_nand2.c
@@ -0,0 +1,236 5 @@
@@ -0,0 +1,234 5 @@
+/******************************************************************************
+* mtk_nand2.c - MTK NAND Flash Device Driver
+ *
@ -1347,8 +1346,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+unsigned int CFG_BLOCKSIZE;
+
+static int shift_on_bbt = 0;
+extern void nand_bbt_set(struct mtd_info *mtd, int page, int flag);
+extern int nand_bbt_get(struct mtd_info *mtd, int page);
+int mtk_nand_read_oob_hw(struct mtd_info *mtd, struct nand_chip *chip, int page);
+
+static const char * const probe_types[] = { "cmdlinepart", "ofpart", NULL };
@ -1397,9 +1394,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+BOOL g_bHwEcc = true;
+
+
+static u8 *local_buffer_16_align; // 16 byte aligned buffer, for HW issue
+static u8 local_buffer[4096 + 512];
+
+extern void nand_release_device(struct mtd_info *mtd);
+extern int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state);
+
@ -1420,6 +1414,25 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+
+static u8 nand_badblock_offset = 0;
+
+static void nand_bbt_set(struct mtd_info *mtd, int page, int flag)
+{
+ struct nand_chip *this = mtd->priv;
+ int block;
+
+ block = (int)(page >> (this->bbt_erase_shift - this->page_shift - 1));
+ this->bbt[block >> 3] &= ~(0x03 << (block & 0x6));
+ this->bbt[block >> 3] |= (flag & 0x3) << (block & 0x6);
+}
+
+static int nand_bbt_get(struct mtd_info *mtd, int page)
+{
+ struct nand_chip *this = mtd->priv;
+ int block;
+
+ block = (int)(page >> (this->bbt_erase_shift - this->page_shift - 1));
+ return (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
+}
+
+void nand_enable_clock(void)
+{
+ //enable_clock(MT65XX_PDN_PERI_NFI, "NAND");
@ -2164,10 +2177,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ struct nand_chip *nand = mtd->priv;
+ u32 u4SecNum = u4PageSize >> 9;
+
+ if (((u32) pPageBuf % 16) && local_buffer_16_align)
+ buf = local_buffer_16_align;
+ else
+ buf = pPageBuf;
+ buf = pPageBuf;
+ if (mtk_nand_ready_for_read(nand, u4RowAddr, 0, true, buf)) {
+ int j;
+ for (j = 0 ; j < u4SecNum; j++) {
@ -2185,9 +2195,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ mtk_nand_stop_read();
+ }
+
+ if (buf == local_buffer_16_align)
+ memcpy(pPageBuf, buf, u4PageSize);
+
+ return bRet;
+}
+
@ -2201,12 +2208,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+
+ MSG(WRITE, "mtk_nand_exec_write_page, page: 0x%x\n", u4RowAddr);
+
+ if (((u32) pPageBuf % 16) && local_buffer_16_align) {
+ printk(KERN_INFO "Data buffer not 16 bytes aligned: %p\n", pPageBuf);
+ memcpy(local_buffer_16_align, pPageBuf, mtd->writesize);
+ buf = local_buffer_16_align;
+ } else
+ buf = pPageBuf;
+ buf = pPageBuf;
+
+ if (mtk_nand_ready_for_write(chip, u4RowAddr, 0, true, buf)) {
+ mtk_nand_write_fdm_data(chip, pFDMBuf, u4SecNum);
@ -3390,9 +3392,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ return -ENOMEM;
+ }
+
+ /* Allocate memory for 16 byte aligned buffer */
+ local_buffer_16_align = local_buffer + 16 - ((u32) local_buffer % 16);
+ printk(KERN_INFO "Allocate 16 byte aligned buffer: %p\n", local_buffer_16_align);
+ host->hw = hw;
+
+ /* init mtd data structure */
@ -3515,23 +3514,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ nand_chip->chip_shift = ffs(nand_chip->chipsize) - 1;//0x1C;//ffs(nand_chip->chipsize) - 1;
+ nand_chip->cmd_ctrl = mtk_nfc_cmd_ctrl;
+
+ /* allocate buffers or call select_chip here or a bit earlier*/
+ {
+ struct nand_buffers *nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize + mtd->oobsize * 3, GFP_KERNEL);
+ if (!nbuf) {
+ return -ENOMEM;
+ }
+ nbuf->ecccalc = (uint8_t *)(nbuf + 1);
+ nbuf->ecccode = nbuf->ecccalc + mtd->oobsize;
+ nbuf->databuf = nbuf->ecccode + mtd->oobsize;
+
+ nand_chip->buffers = nbuf;
+ nand_chip->options |= NAND_OWN_BUFFERS;
+ }
+
+ nand_chip->oob_poi = nand_chip->buffers->databuf + mtd->writesize;
+ nand_chip->badblockpos = 0;
+
+ if (devinfo.pagesize == 4096)
+ layout = &nand_oob_128;
+ else if (devinfo.pagesize == 2048)
@ -3555,6 +3537,9 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ mtd->oobsize = devinfo.sparesize;
+ hw->nfi_cs_num = 1;
+
+ nand_chip->options |= NAND_USE_BOUNCE_BUFFER;
+ nand_chip->buf_align = 16;
+
+ /* Scan to find existance of the device */
+ if (nand_scan(mtd, hw->nfi_cs_num)) {
+ MSG(INIT, "%s : nand_scan fail.\n", MODULE_NAME);
@ -3607,9 +3592,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ MSG(INIT, "[NFI] mtk_nand_probe fail, err = %d!\n", err);
+ nand_release(mtd);
+ platform_set_drvdata(pdev, NULL);
+ if ( NULL != nand_chip->buffers) {
+ kfree(nand_chip->buffers);
+ }
+ kfree(host);
+ nand_disable_clock();
+ return err;
@ -3623,9 +3605,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ struct nand_chip *nand_chip = &host->nand_chip;
+
+ nand_release(mtd);
+ if ( NULL != nand_chip->buffers) {
+ kfree(nand_chip->buffers);
+ }
+ kfree(host);
+ nand_disable_clock();
+
@ -4149,34 +4128,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
nand_get_device(struct mtd_info *mtd, int new_state)
{
struct nand_chip *chip = mtd_to_nand(mtd);
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -1215,6 +1215,25 @@ err:
return res;
}
+void nand_bbt_set(struct mtd_info *mtd, int page, int flag)
+{
+ struct nand_chip *this = mtd->priv;
+ int block;
+
+ block = (int)(page >> (this->bbt_erase_shift - this->page_shift - 1));
+ this->bbt[block >> 3] &= ~(0x03 << (block & 0x6));
+ this->bbt[block >> 3] |= (flag & 0x3) << (block & 0x6);
+}
+
+int nand_bbt_get(struct mtd_info *mtd, int page)
+{
+ struct nand_chip *this = mtd->priv;
+ int block;
+
+ block = (int)(page >> (this->bbt_erase_shift - this->page_shift - 1));
+ return (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
+}
+
/**
* nand_update_bbt - update bad block table(s)
* @mtd: MTD device structure
--- /dev/null
+++ b/drivers/mtd/nand/nand_def.h
@@ -0,0 +1,123 @@