]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
mtd: vf610_nfc: specify transfer size before each transfer
authorStefan Agner <stefan@agner.ch>
Tue, 24 Mar 2015 16:54:20 +0000 (17:54 +0100)
committerLothar Waßmann <LW@KARO-electronics.de>
Tue, 1 Sep 2015 12:38:12 +0000 (14:38 +0200)
Testing showed, that commands like STATUS made the buffer dirty
when executed with NFC_SECSZ set to the page size. It looks
like the controller transfers bogus data when this register
is configured. When setting it to 0, the buffer does not get
altered while the status command still seems to work flawless.

Signed-off-by: Stefan Agner <stefan@agner.ch>
drivers/mtd/nand/vf610_nfc.c

index 32a98dc55a1a01c98c9e1072ee4ccc7b07ff1b4a..46a2a8bf19ffa27a7450ea27ac246d87afc7e98e 100644 (file)
@@ -146,6 +146,7 @@ struct vf610_nfc {
        void __iomem      *regs;
        uint               column;
        int                spareonly;
+       int                page_sz;
        int                page;
        /* Status and ID are in alternate locations. */
        int                alt_buf;
@@ -329,6 +330,11 @@ static void vf610_nfc_addr_cycle(struct mtd_info *mtd, int column, int page)
                                    ROW_ADDR_SHIFT, page);
 }
 
+static inline void vf610_nfc_transfer_size(void __iomem *regbase, int size)
+{
+       __raw_writel(size, regbase + NFC_SECTOR_SIZE);
+}
+
 /* Send command to NAND chip */
 static void vf610_nfc_command(struct mtd_info *mtd, unsigned command,
                              int column, int page)
@@ -342,12 +348,14 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command,
        switch (command) {
        case NAND_CMD_PAGEPROG:
                nfc->page = -1;
+               vf610_nfc_transfer_size(nfc->regs, nfc->page_sz);
                vf610_nfc_send_commands(nfc->regs, NAND_CMD_SEQIN,
                                        command, PROGRAM_PAGE_CMD_CODE);
                vf610_nfc_addr_cycle(mtd, column, page);
                break;
 
        case NAND_CMD_RESET:
+               vf610_nfc_transfer_size(nfc->regs, 0);
                vf610_nfc_send_command(nfc->regs, command, RESET_CMD_CODE);
                break;
        /*
@@ -363,6 +371,7 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command,
                if (nfc->page == page)
                        return;
                nfc->page = page;
+               vf610_nfc_transfer_size(nfc->regs, nfc->page_sz);
                vf610_nfc_send_commands(nfc->regs, NAND_CMD_READ0,
                                        NAND_CMD_READSTART, READ_PAGE_CMD_CODE);
                vf610_nfc_addr_cycle(mtd, column, page);
@@ -370,6 +379,7 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command,
 
        case NAND_CMD_ERASE1:
                nfc->page = -1;
+               vf610_nfc_transfer_size(nfc->regs, 0);
                vf610_nfc_send_commands(nfc->regs, command,
                                        NAND_CMD_ERASE2, ERASE_CMD_CODE);
                vf610_nfc_addr_cycle(mtd, column, page);
@@ -377,11 +387,13 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command,
 
        case NAND_CMD_READID:
                nfc->alt_buf = ALT_BUF_ID;
+               vf610_nfc_transfer_size(nfc->regs, 0);
                vf610_nfc_send_command(nfc->regs, command, READ_ID_CMD_CODE);
                break;
 
        case NAND_CMD_STATUS:
                nfc->alt_buf = ALT_BUF_STAT;
+               vf610_nfc_transfer_size(nfc->regs, 0);
                vf610_nfc_send_command(nfc->regs, command,
                                       STATUS_READ_CMD_CODE);
                break;
@@ -579,7 +591,6 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr)
        struct nand_chip *chip;
        struct vf610_nfc *nfc;
        int err = 0;
-       int page_sz;
        struct vf610_nfc_config cfg = {
                .hardware_ecc = 1,
 #ifdef CONFIG_SYS_NAND_BUSWIDTH_16BIT
@@ -633,9 +644,8 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr)
        chip->bbt_td = &bbt_main_descr;
        chip->bbt_md = &bbt_mirror_descr;
 
-       page_sz = PAGE_2K + OOB_64;
-       page_sz += cfg.width == 16 ? 1 : 0;
-       vf610_nfc_write(mtd, NFC_SECTOR_SIZE, page_sz);
+       nfc->page_sz = PAGE_2K + OOB_64;
+       nfc->page_sz += cfg.width == 16 ? 1 : 0;
 
        /* Set configuration register. */
        vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_ADDR_AUTO_INCR_BIT);
@@ -664,16 +674,15 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr)
 
        chip->ecc.mode = NAND_ECC_SOFT; /* default */
 
-       page_sz = mtd->writesize + mtd->oobsize;
+       nfc->page_sz = mtd->writesize + mtd->oobsize;
 
        /* Single buffer only, max 256 OOB minus ECC status */
-       if (page_sz > PAGE_2K + 256 - 8) {
+       if (nfc->page_sz > PAGE_2K + 256 - 8) {
                dev_err(nfc->dev, "Unsupported flash size\n");
                err = -ENXIO;
                goto error;
        }
-       page_sz += cfg.width == 16 ? 1 : 0;
-       vf610_nfc_write(mtd, NFC_SECTOR_SIZE, page_sz);
+       nfc->page_sz += cfg.width == 16 ? 1 : 0;
 
        if (cfg.hardware_ecc) {
                if (mtd->writesize != PAGE_2K && mtd->oobsize < 64) {