void __iomem            *sram_bank0;
        dma_addr_t              sram_bank0_phys;
        bool                    use_nfc_sram;
+       bool                    write_by_sram;
 
        bool                    is_initialized;
        struct completion       comp_nfc;
 
        /* Point to the sram bank which include readed data via NFC */
        void __iomem            *data_in_sram;
+       bool                    will_write_sram;
 };
 static struct atmel_nfc        nand_nfc;
 
                *t++ = readl_relaxed(s++);
 }
 
+static void memcpy32_toio(void __iomem *trg, const void *src, int size)
+{
+       int i;
+       u32 __iomem *t = trg;
+       const u32 *s = src;
+
+       for (i = 0; i < (size >> 2); i++)
+               writel_relaxed(*s++, t++);
+}
+
 /*
  * Minimal-overhead PIO for data access.
  */
                dma_dst_addr = phys_addr;
        } else {
                dma_src_addr = phys_addr;
-               dma_dst_addr = host->io_phys;
+
+               if (nfc && nfc->write_by_sram)
+                       dma_dst_addr = nfc_sram_phys(host);
+               else
+                       dma_dst_addr = host->io_phys;
        }
 
        tx = dma_dev->device_prep_dma_memcpy(host->dma_chan, dma_dst_addr,
        int i, j;
        unsigned long end_time;
 
-       pmecc_enable(host, NAND_ECC_WRITE);
-
-       chip->write_buf(mtd, (u8 *)buf, mtd->writesize);
+       if (!host->nfc || !host->nfc->write_by_sram) {
+               pmecc_enable(host, NAND_ECC_WRITE);
+               chip->write_buf(mtd, (u8 *)buf, mtd->writesize);
+       }
 
        end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS);
        while ((pmecc_readl_relaxed(host->ecc, SR) & PMECC_SR_BUSY)) {
        case NAND_CMD_SEQIN:
        case NAND_CMD_RNDIN:
                nfcwr = NFCADDR_CMD_NFCWR;
+               if (host->nfc->will_write_sram && command == NAND_CMD_SEQIN)
+                       dataen = NFCADDR_CMD_DATAEN;
                break;
        default:
                break;
        }
 }
 
+static int nfc_sram_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+                       uint32_t offset, int data_len, const uint8_t *buf,
+                       int oob_required, int page, int cached, int raw)
+{
+       int cfg, len;
+       int status = 0;
+       struct atmel_nand_host *host = chip->priv;
+       void __iomem *sram = host->nfc->sram_bank0 + nfc_get_sram_off(host);
+
+       /* Subpage write is not supported */
+       if (offset || (data_len < mtd->writesize))
+               return -EINVAL;
+
+       cfg = nfc_readl(host->nfc->hsmc_regs, CFG);
+       len = mtd->writesize;
+
+       if (unlikely(raw)) {
+               len += mtd->oobsize;
+               nfc_writel(host->nfc->hsmc_regs, CFG, cfg | NFC_CFG_WSPARE);
+       } else
+               nfc_writel(host->nfc->hsmc_regs, CFG, cfg & ~NFC_CFG_WSPARE);
+
+       /* Copy page data to sram that will write to nand via NFC */
+       if (use_dma) {
+               if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) != 0)
+                       /* Fall back to use cpu copy */
+                       memcpy32_toio(sram, buf, len);
+       } else {
+               memcpy32_toio(sram, buf, len);
+       }
+
+       if (chip->ecc.mode == NAND_ECC_HW && host->has_pmecc)
+               /*
+                * When use NFC sram, need set up PMECC before send
+                * NAND_CMD_SEQIN command. Since when the nand command
+                * is sent, nfc will do transfer from sram and nand.
+                */
+               pmecc_enable(host, NAND_ECC_WRITE);
+
+       host->nfc->will_write_sram = true;
+       chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
+       host->nfc->will_write_sram = false;
+
+       if (likely(!raw))
+               /* Need to write ecc into oob */
+               status = chip->ecc.write_page(mtd, chip, buf, oob_required);
+
+       if (status < 0)
+               return status;
+
+       chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+       status = chip->waitfunc(mtd, chip);
+
+       if ((status & NAND_STATUS_FAIL) && (chip->errstat))
+               status = chip->errstat(mtd, chip, FL_WRITING, status, page);
+
+       if (status & NAND_STATUS_FAIL)
+               return -EIO;
+
+       return 0;
+}
+
 static int nfc_sram_init(struct mtd_info *mtd)
 {
        struct nand_chip *chip = mtd->priv;
 
        nfc_writel(host->nfc->hsmc_regs, CFG, cfg_nfc);
 
+       host->nfc->will_write_sram = false;
        nfc_set_sram_bank(host, 0);
 
-       dev_info(host->dev, "Using NFC Sram read\n");
+       /* Use Write page with NFC SRAM only for PMECC or ECC NONE. */
+       if (host->nfc->write_by_sram) {
+               if ((chip->ecc.mode == NAND_ECC_HW && host->has_pmecc) ||
+                               chip->ecc.mode == NAND_ECC_NONE)
+                       chip->write_page = nfc_sram_write_page;
+               else
+                       host->nfc->write_by_sram = false;
+       }
 
+       dev_info(host->dev, "Using NFC Sram read %s\n",
+                       host->nfc->write_by_sram ? "and write" : "");
        return 0;
 }
 
                } else {
                        nfc->use_nfc_sram = true;
                        nfc->sram_bank0_phys = (dma_addr_t)nfc_sram->start;
+
+                       if (pdev->dev.of_node)
+                               nfc->write_by_sram = of_property_read_bool(
+                                               pdev->dev.of_node,
+                                               "atmel,write-by-sram");
                }
        }