]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - drivers/mtd/nand/fsl_ifc_nand.c
ARM: imx6: clocks: remove function local definitions of mxc_ccm_reg and anatop_regs
[karo-tx-uboot.git] / drivers / mtd / nand / fsl_ifc_nand.c
index 1808a7ffba8ebb8fe0a02474d99096e535ae6e1c..975b0d461318ff8f396de11e6021a9f3fca431a9 100644 (file)
 #include <asm/errno.h>
 #include <fsl_ifc.h>
 
-#define FSL_IFC_V1_1_0 0x01010000
-#define MAX_BANKS      4
+#ifndef CONFIG_SYS_FSL_IFC_BANK_COUNT
+#define CONFIG_SYS_FSL_IFC_BANK_COUNT  4
+#endif
+
+#define MAX_BANKS      CONFIG_SYS_FSL_IFC_BANK_COUNT
 #define ERR_BYTE       0xFF /* Value returned for read bytes
                                when read failed */
-#define IFC_TIMEOUT_MSECS 10 /* Maximum number of mSecs to wait for IFC
-                               NAND Machine */
 
 struct fsl_ifc_ctrl;
 
@@ -45,8 +46,8 @@ struct fsl_ifc_ctrl {
        struct fsl_ifc_mtd *chips[MAX_BANKS];
 
        /* device info */
-       struct fsl_ifc *regs;
-       uint8_t __iomem *addr;   /* Address of assigned IFC buffer        */
+       struct fsl_ifc regs;
+       void __iomem *addr;      /* Address of assigned IFC buffer        */
        unsigned int cs_nand;    /* On which chipsel NAND is connected    */
        unsigned int page;       /* Last page written to / read from      */
        unsigned int read_bytes; /* Number of bytes read during command   */
@@ -224,14 +225,14 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
        struct nand_chip *chip = mtd->priv;
        struct fsl_ifc_mtd *priv = chip->priv;
        struct fsl_ifc_ctrl *ctrl = priv->ctrl;
-       struct fsl_ifc *ifc = ctrl->regs;
+       struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
        int buf_num;
 
        ctrl->page = page_addr;
 
        /* Program ROW0/COL0 */
-       out_be32(&ifc->ifc_nand.row0, page_addr);
-       out_be32(&ifc->ifc_nand.col0, (oob ? IFC_NAND_COL_MS : 0) | column);
+       ifc_out32(&ifc->ifc_nand.row0, page_addr);
+       ifc_out32(&ifc->ifc_nand.col0, (oob ? IFC_NAND_COL_MS : 0) | column);
 
        buf_num = page_addr & priv->bufnum_mask;
 
@@ -288,29 +289,30 @@ static int fsl_ifc_run_command(struct mtd_info *mtd)
        struct nand_chip *chip = mtd->priv;
        struct fsl_ifc_mtd *priv = chip->priv;
        struct fsl_ifc_ctrl *ctrl = priv->ctrl;
-       struct fsl_ifc *ifc = ctrl->regs;
-       long long end_tick;
-       u32 eccstat[4];
+       struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
+       u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
+       u32 time_start;
+       u32 eccstat[8] = {0};
        int i;
 
        /* set the chip select for NAND Transaction */
-       out_be32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand);
+       ifc_out32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand);
 
        /* start read/write seq */
-       out_be32(&ifc->ifc_nand.nandseq_strt,
-                IFC_NAND_SEQ_STRT_FIR_STRT);
+       ifc_out32(&ifc->ifc_nand.nandseq_strt,
+                 IFC_NAND_SEQ_STRT_FIR_STRT);
 
        /* wait for NAND Machine complete flag or timeout */
-       end_tick = usec2ticks(IFC_TIMEOUT_MSECS * 1000) + get_ticks();
+       time_start = get_timer(0);
 
-       while (end_tick > get_ticks()) {
-               ctrl->status = in_be32(&ifc->ifc_nand.nand_evter_stat);
+       while (get_timer(time_start) < timeo) {
+               ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
 
                if (ctrl->status & IFC_NAND_EVTER_STAT_OPC)
                        break;
        }
 
-       out_be32(&ifc->ifc_nand.nand_evter_stat, ctrl->status);
+       ifc_out32(&ifc->ifc_nand.nand_evter_stat, ctrl->status);
 
        if (ctrl->status & IFC_NAND_EVTER_STAT_FTOER)
                printf("%s: Flash Time Out Error\n", __func__);
@@ -323,8 +325,15 @@ static int fsl_ifc_run_command(struct mtd_info *mtd)
                int sector = bufnum * chip->ecc.steps;
                int sector_end = sector + chip->ecc.steps - 1;
 
-               for (i = sector / 4; i <= sector_end / 4; i++)
-                       eccstat[i] = in_be32(&ifc->ifc_nand.nand_eccstat[i]);
+               for (i = sector / 4; i <= sector_end / 4; i++) {
+                       if (i >= ARRAY_SIZE(eccstat)) {
+                               printf("%s: eccstat too small for %d\n",
+                                      __func__, i);
+                               return -EIO;
+                       }
+
+                       eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]);
+               }
 
                for (i = sector; i <= sector_end; i++) {
                        errors = check_read_ecc(mtd, ctrl, eccstat, i);
@@ -360,34 +369,34 @@ static void fsl_ifc_do_read(struct nand_chip *chip,
 {
        struct fsl_ifc_mtd *priv = chip->priv;
        struct fsl_ifc_ctrl *ctrl = priv->ctrl;
-       struct fsl_ifc *ifc = ctrl->regs;
+       struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
 
        /* Program FIR/IFC_NAND_FCR0 for Small/Large page */
        if (mtd->writesize > 512) {
-               out_be32(&ifc->ifc_nand.nand_fir0,
-                        (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
-                        (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
-                        (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
-                        (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) |
-                        (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT));
-               out_be32(&ifc->ifc_nand.nand_fir1, 0x0);
-
-               out_be32(&ifc->ifc_nand.nand_fcr0,
-                       (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
-                       (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
+               ifc_out32(&ifc->ifc_nand.nand_fir0,
+                         (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+                         (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+                         (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
+                         (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) |
+                         (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT));
+               ifc_out32(&ifc->ifc_nand.nand_fir1, 0x0);
+
+               ifc_out32(&ifc->ifc_nand.nand_fcr0,
+                         (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
+                         (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
        } else {
-               out_be32(&ifc->ifc_nand.nand_fir0,
-                        (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
-                        (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
-                        (IFC_FIR_OP_RA0  << IFC_NAND_FIR0_OP2_SHIFT) |
-                        (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT));
+               ifc_out32(&ifc->ifc_nand.nand_fir0,
+                         (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+                         (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+                         (IFC_FIR_OP_RA0  << IFC_NAND_FIR0_OP2_SHIFT) |
+                         (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT));
 
                if (oob)
-                       out_be32(&ifc->ifc_nand.nand_fcr0,
-                                NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT);
+                       ifc_out32(&ifc->ifc_nand.nand_fcr0,
+                                 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT);
                else
-                       out_be32(&ifc->ifc_nand.nand_fcr0,
-                               NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
+                       ifc_out32(&ifc->ifc_nand.nand_fcr0,
+                                 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
        }
 }
 
@@ -398,7 +407,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
        struct nand_chip *chip = mtd->priv;
        struct fsl_ifc_mtd *priv = chip->priv;
        struct fsl_ifc_ctrl *ctrl = priv->ctrl;
-       struct fsl_ifc *ifc = ctrl->regs;
+       struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
 
        /* clear the read buffer */
        ctrl->read_bytes = 0;
@@ -408,7 +417,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
        switch (command) {
        /* READ0 read the entire buffer to use hardware ECC. */
        case NAND_CMD_READ0: {
-               out_be32(&ifc->ifc_nand.nand_fbcr, 0);
+               ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
                set_addr(mtd, 0, page_addr, 0);
 
                ctrl->read_bytes = mtd->writesize + mtd->oobsize;
@@ -424,7 +433,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
        /* READOOB reads only the OOB because no ECC is performed. */
        case NAND_CMD_READOOB:
-               out_be32(&ifc->ifc_nand.nand_fbcr, mtd->oobsize - column);
+               ifc_out32(&ifc->ifc_nand.nand_fbcr, mtd->oobsize - column);
                set_addr(mtd, column, page_addr, 1);
 
                ctrl->read_bytes = mtd->writesize + mtd->oobsize;
@@ -441,19 +450,19 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
                if (command == NAND_CMD_PARAM)
                        timing = IFC_FIR_OP_RBCD;
 
-               out_be32(&ifc->ifc_nand.nand_fir0,
-                               (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
-                               (IFC_FIR_OP_UA  << IFC_NAND_FIR0_OP1_SHIFT) |
-                               (timing << IFC_NAND_FIR0_OP2_SHIFT));
-               out_be32(&ifc->ifc_nand.nand_fcr0,
-                               command << IFC_NAND_FCR0_CMD0_SHIFT);
-               out_be32(&ifc->ifc_nand.row3, column);
+               ifc_out32(&ifc->ifc_nand.nand_fir0,
+                         (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+                         (IFC_FIR_OP_UA  << IFC_NAND_FIR0_OP1_SHIFT) |
+                         (timing << IFC_NAND_FIR0_OP2_SHIFT));
+               ifc_out32(&ifc->ifc_nand.nand_fcr0,
+                         command << IFC_NAND_FCR0_CMD0_SHIFT);
+               ifc_out32(&ifc->ifc_nand.row3, column);
 
                /*
                 * although currently it's 8 bytes for READID, we always read
                 * the maximum 256 bytes(for PARAM)
                 */
-               out_be32(&ifc->ifc_nand.nand_fbcr, 256);
+               ifc_out32(&ifc->ifc_nand.nand_fbcr, 256);
                ctrl->read_bytes = 256;
 
                set_addr(mtd, 0, 0, 0);
@@ -468,16 +477,16 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
        /* ERASE2 uses the block and page address from ERASE1 */
        case NAND_CMD_ERASE2:
-               out_be32(&ifc->ifc_nand.nand_fir0,
-                        (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
-                        (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) |
-                        (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT));
+               ifc_out32(&ifc->ifc_nand.nand_fir0,
+                         (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+                         (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+                         (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT));
 
-               out_be32(&ifc->ifc_nand.nand_fcr0,
-                        (NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) |
-                        (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT));
+               ifc_out32(&ifc->ifc_nand.nand_fcr0,
+                         (NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) |
+                         (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT));
 
-               out_be32(&ifc->ifc_nand.nand_fbcr, 0);
+               ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
                ctrl->read_bytes = 0;
                fsl_ifc_run_command(mtd);
                return;
@@ -494,17 +503,18 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
                                (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) |
                                (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT);
 
-                       out_be32(&ifc->ifc_nand.nand_fir0,
-                                (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
-                                (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
-                                (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
-                                (IFC_FIR_OP_WBCD  << IFC_NAND_FIR0_OP3_SHIFT) |
-                                (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT));
-                       out_be32(&ifc->ifc_nand.nand_fir1,
-                                (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) |
-                                (IFC_FIR_OP_RDSTAT <<
+                       ifc_out32(&ifc->ifc_nand.nand_fir0,
+                                 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+                                 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+                                 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
+                                 (IFC_FIR_OP_WBCD  <<
+                                               IFC_NAND_FIR0_OP3_SHIFT) |
+                                 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT));
+                       ifc_out32(&ifc->ifc_nand.nand_fir1,
+                                 (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) |
+                                 (IFC_FIR_OP_RDSTAT <<
                                        IFC_NAND_FIR1_OP6_SHIFT) |
-                                (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT));
+                                 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT));
                } else {
                        nand_fcr0 = ((NAND_CMD_PAGEPROG <<
                                        IFC_NAND_FCR0_CMD1_SHIFT) |
@@ -513,18 +523,18 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
                                    (NAND_CMD_STATUS <<
                                        IFC_NAND_FCR0_CMD3_SHIFT));
 
-                       out_be32(&ifc->ifc_nand.nand_fir0,
-                                (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
-                                (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) |
-                                (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) |
-                                (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
-                                (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT));
-                       out_be32(&ifc->ifc_nand.nand_fir1,
-                                (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) |
-                                (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) |
-                                (IFC_FIR_OP_RDSTAT <<
+                       ifc_out32(&ifc->ifc_nand.nand_fir0,
+                                 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+                                 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) |
+                                 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) |
+                                 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
+                                 (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT));
+                       ifc_out32(&ifc->ifc_nand.nand_fir1,
+                                 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) |
+                                 (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) |
+                                 (IFC_FIR_OP_RDSTAT <<
                                        IFC_NAND_FIR1_OP7_SHIFT) |
-                                (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT));
+                                 (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT));
 
                        if (column >= mtd->writesize)
                                nand_fcr0 |=
@@ -539,7 +549,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
                        column -= mtd->writesize;
                        ctrl->oob = 1;
                }
-               out_be32(&ifc->ifc_nand.nand_fcr0, nand_fcr0);
+               ifc_out32(&ifc->ifc_nand.nand_fcr0, nand_fcr0);
                set_addr(mtd, column, page_addr, ctrl->oob);
                return;
        }
@@ -547,35 +557,42 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
        /* PAGEPROG reuses all of the setup from SEQIN and adds the length */
        case NAND_CMD_PAGEPROG:
                if (ctrl->oob)
-                       out_be32(&ifc->ifc_nand.nand_fbcr,
-                                       ctrl->index - ctrl->column);
+                       ifc_out32(&ifc->ifc_nand.nand_fbcr,
+                                 ctrl->index - ctrl->column);
                else
-                       out_be32(&ifc->ifc_nand.nand_fbcr, 0);
+                       ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);
 
                fsl_ifc_run_command(mtd);
                return;
 
        case NAND_CMD_STATUS:
-               out_be32(&ifc->ifc_nand.nand_fir0,
-                               (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
-                               (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT));
-               out_be32(&ifc->ifc_nand.nand_fcr0,
-                               NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT);
-               out_be32(&ifc->ifc_nand.nand_fbcr, 1);
+               ifc_out32(&ifc->ifc_nand.nand_fir0,
+                         (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+                         (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT));
+               ifc_out32(&ifc->ifc_nand.nand_fcr0,
+                         NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT);
+               ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
                set_addr(mtd, 0, 0, 0);
                ctrl->read_bytes = 1;
 
                fsl_ifc_run_command(mtd);
 
-               /* Chip sometimes reporting write protect even when it's not */
-               out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP);
+               /*
+                * The chip always seems to report that it is
+                * write-protected, even when it is not.
+                */
+               if (chip->options & NAND_BUSWIDTH_16)
+                       ifc_out16(ctrl->addr,
+                                 ifc_in16(ctrl->addr) | NAND_STATUS_WP);
+               else
+                       out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP);
                return;
 
        case NAND_CMD_RESET:
-               out_be32(&ifc->ifc_nand.nand_fir0,
-                               IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT);
-               out_be32(&ifc->ifc_nand.nand_fcr0,
-                               NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT);
+               ifc_out32(&ifc->ifc_nand.nand_fir0,
+                         IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT);
+               ifc_out32(&ifc->ifc_nand.nand_fcr0,
+                         NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT);
                fsl_ifc_run_command(mtd);
                return;
 
@@ -608,7 +625,7 @@ static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
                len = bufsize - ctrl->index;
        }
 
-       memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
+       memcpy_toio(ctrl->addr + ctrl->index, buf, len);
        ctrl->index += len;
 }
 
@@ -621,11 +638,16 @@ static u8 fsl_ifc_read_byte(struct mtd_info *mtd)
        struct nand_chip *chip = mtd->priv;
        struct fsl_ifc_mtd *priv = chip->priv;
        struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+       unsigned int offset;
 
-       /* If there are still bytes in the IFC buffer, then use the
-        * next byte. */
-       if (ctrl->index < ctrl->read_bytes)
-               return in_8(&ctrl->addr[ctrl->index++]);
+       /*
+        * If there are still bytes in the IFC buffer, then use the
+        * next byte.
+        */
+       if (ctrl->index < ctrl->read_bytes) {
+               offset = ctrl->index++;
+               return in_8(ctrl->addr + offset);
+       }
 
        printf("%s beyond end of buffer\n", __func__);
        return ERR_BYTE;
@@ -647,8 +669,7 @@ static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
         * next byte.
         */
        if (ctrl->index < ctrl->read_bytes) {
-               data = in_be16((uint16_t *)&ctrl->
-                                       addr[ctrl->index]);
+               data = ifc_in16(ctrl->addr + ctrl->index);
                ctrl->index += 2;
                return (uint8_t)data;
        }
@@ -671,7 +692,7 @@ static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
                return;
 
        avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
-       memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail);
+       memcpy_fromio(buf, ctrl->addr + ctrl->index, avail);
        ctrl->index += avail;
 
        if (len > avail)
@@ -680,39 +701,6 @@ static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
                       __func__, len, avail);
 }
 
-/*
- * Verify buffer against the IFC Controller Data Buffer
- */
-static int fsl_ifc_verify_buf(struct mtd_info *mtd,
-                              const u_char *buf, int len)
-{
-       struct nand_chip *chip = mtd->priv;
-       struct fsl_ifc_mtd *priv = chip->priv;
-       struct fsl_ifc_ctrl *ctrl = priv->ctrl;
-       int i;
-
-       if (len < 0) {
-               printf("%s of %d bytes", __func__, len);
-               return -EINVAL;
-       }
-
-       if ((unsigned int)len > ctrl->read_bytes - ctrl->index) {
-               printf("%s beyond end of buffer "
-                      "(%d requested, %u available)\n",
-                      __func__, len, ctrl->read_bytes - ctrl->index);
-
-               ctrl->index = ctrl->read_bytes;
-               return -EINVAL;
-       }
-
-       for (i = 0; i < len; i++)
-               if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i])
-                       break;
-
-       ctrl->index += len;
-       return i == len && ctrl->status == IFC_NAND_EVTER_STAT_OPC ? 0 : -EIO;
-}
-
 /* This function is called after Program and Erase Operations to
  * check for success or failure.
  */
@@ -720,19 +708,19 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
 {
        struct fsl_ifc_mtd *priv = chip->priv;
        struct fsl_ifc_ctrl *ctrl = priv->ctrl;
-       struct fsl_ifc *ifc = ctrl->regs;
+       struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
        u32 nand_fsr;
 
        if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
                return NAND_STATUS_FAIL;
 
        /* Use READ_STATUS command, but wait for the device to be ready */
-       out_be32(&ifc->ifc_nand.nand_fir0,
-                (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
-                (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT));
-       out_be32(&ifc->ifc_nand.nand_fcr0, NAND_CMD_STATUS <<
-                       IFC_NAND_FCR0_CMD0_SHIFT);
-       out_be32(&ifc->ifc_nand.nand_fbcr, 1);
+       ifc_out32(&ifc->ifc_nand.nand_fir0,
+                 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+                 (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT));
+       ifc_out32(&ifc->ifc_nand.nand_fcr0, NAND_CMD_STATUS <<
+                 IFC_NAND_FCR0_CMD0_SHIFT);
+       ifc_out32(&ifc->ifc_nand.nand_fbcr, 1);
        set_addr(mtd, 0, 0, 0);
        ctrl->read_bytes = 1;
 
@@ -741,7 +729,7 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
        if (ctrl->status != IFC_NAND_EVTER_STAT_OPC)
                return NAND_STATUS_FAIL;
 
-       nand_fsr = in_be32(&ifc->ifc_nand.nand_fsr);
+       nand_fsr = ifc_in32(&ifc->ifc_nand.nand_fsr);
 
        /* Chip sometimes reporting write protect even when it's not */
        nand_fsr = nand_fsr | NAND_STATUS_WP;
@@ -777,83 +765,117 @@ static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 
 static void fsl_ifc_ctrl_init(void)
 {
+       uint32_t ver = 0;
        ifc_ctrl = kzalloc(sizeof(*ifc_ctrl), GFP_KERNEL);
        if (!ifc_ctrl)
                return;
 
-       ifc_ctrl->regs = IFC_BASE_ADDR;
+       ifc_ctrl->regs.gregs = IFC_FCM_BASE_ADDR;
+
+       ver = ifc_in32(&ifc_ctrl->regs.gregs->ifc_rev);
+       if (ver >= FSL_IFC_V2_0_0)
+               ifc_ctrl->regs.rregs =
+                       (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_64KOFFSET;
+       else
+               ifc_ctrl->regs.rregs =
+                       (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_4KOFFSET;
 
        /* clear event registers */
-       out_be32(&ifc_ctrl->regs->ifc_nand.nand_evter_stat, ~0U);
-       out_be32(&ifc_ctrl->regs->ifc_nand.pgrdcmpl_evt_stat, ~0U);
+       ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.nand_evter_stat, ~0U);
+       ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.pgrdcmpl_evt_stat, ~0U);
 
        /* Enable error and event for any detected errors */
-       out_be32(&ifc_ctrl->regs->ifc_nand.nand_evter_en,
-                       IFC_NAND_EVTER_EN_OPC_EN |
-                       IFC_NAND_EVTER_EN_PGRDCMPL_EN |
-                       IFC_NAND_EVTER_EN_FTOER_EN |
-                       IFC_NAND_EVTER_EN_WPER_EN);
+       ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.nand_evter_en,
+                 IFC_NAND_EVTER_EN_OPC_EN |
+                 IFC_NAND_EVTER_EN_PGRDCMPL_EN |
+                 IFC_NAND_EVTER_EN_FTOER_EN |
+                 IFC_NAND_EVTER_EN_WPER_EN);
 
-       out_be32(&ifc_ctrl->regs->ifc_nand.ncfgr, 0x0);
+       ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.ncfgr, 0x0);
 }
 
 static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
 {
 }
 
-static void fsl_ifc_sram_init(void)
+static int fsl_ifc_sram_init(uint32_t ver)
 {
-       struct fsl_ifc *ifc = ifc_ctrl->regs;
+       struct fsl_ifc_runtime *ifc = ifc_ctrl->regs.rregs;
        uint32_t cs = 0, csor = 0, csor_8k = 0, csor_ext = 0;
-       long long end_tick;
+       uint32_t ncfgr = 0;
+       u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
+       u32 time_start;
+
+       if (ver > FSL_IFC_V1_1_0) {
+               ncfgr = ifc_in32(&ifc->ifc_nand.ncfgr);
+               ifc_out32(&ifc->ifc_nand.ncfgr, ncfgr | IFC_NAND_SRAM_INIT_EN);
+
+               /* wait for  SRAM_INIT bit to be clear or timeout */
+               time_start = get_timer(0);
+               while (get_timer(time_start) < timeo) {
+                       ifc_ctrl->status =
+                               ifc_in32(&ifc->ifc_nand.nand_evter_stat);
+
+                       if (!(ifc_ctrl->status & IFC_NAND_SRAM_INIT_EN))
+                               return 0;
+               }
+               printf("fsl-ifc: Failed to Initialise SRAM\n");
+               return 1;
+       }
 
        cs = ifc_ctrl->cs_nand >> IFC_NAND_CSEL_SHIFT;
 
        /* Save CSOR and CSOR_ext */
-       csor = in_be32(&ifc_ctrl->regs->csor_cs[cs].csor);
-       csor_ext = in_be32(&ifc_ctrl->regs->csor_cs[cs].csor_ext);
+       csor = ifc_in32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor);
+       csor_ext = ifc_in32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext);
 
        /* chage PageSize 8K and SpareSize 1K*/
        csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000;
-       out_be32(&ifc_ctrl->regs->csor_cs[cs].csor, csor_8k);
-       out_be32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, 0x0000400);
+       ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor, csor_8k);
+       ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext, 0x0000400);
 
        /* READID */
-       out_be32(&ifc->ifc_nand.nand_fir0,
-                       (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
-                       (IFC_FIR_OP_UA  << IFC_NAND_FIR0_OP1_SHIFT) |
-                       (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
-       out_be32(&ifc->ifc_nand.nand_fcr0,
-                       NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT);
-       out_be32(&ifc->ifc_nand.row3, 0x0);
+       ifc_out32(&ifc->ifc_nand.nand_fir0,
+                 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+                 (IFC_FIR_OP_UA  << IFC_NAND_FIR0_OP1_SHIFT) |
+                 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
+       ifc_out32(&ifc->ifc_nand.nand_fcr0,
+                 NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT);
+       ifc_out32(&ifc->ifc_nand.row3, 0x0);
 
-       out_be32(&ifc->ifc_nand.nand_fbcr, 0x0);
+       ifc_out32(&ifc->ifc_nand.nand_fbcr, 0x0);
 
        /* Program ROW0/COL0 */
-       out_be32(&ifc->ifc_nand.row0, 0x0);
-       out_be32(&ifc->ifc_nand.col0, 0x0);
+       ifc_out32(&ifc->ifc_nand.row0, 0x0);
+       ifc_out32(&ifc->ifc_nand.col0, 0x0);
 
        /* set the chip select for NAND Transaction */
-       out_be32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand);
+       ifc_out32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand);
 
        /* start read seq */
-       out_be32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT);
+       ifc_out32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT);
 
-       /* wait for NAND Machine complete flag or timeout */
-       end_tick = usec2ticks(IFC_TIMEOUT_MSECS * 1000) + get_ticks();
+       time_start = get_timer(0);
 
-       while (end_tick > get_ticks()) {
-               ifc_ctrl->status = in_be32(&ifc->ifc_nand.nand_evter_stat);
+       while (get_timer(time_start) < timeo) {
+               ifc_ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
 
                if (ifc_ctrl->status & IFC_NAND_EVTER_STAT_OPC)
                        break;
        }
 
-       out_be32(&ifc->ifc_nand.nand_evter_stat, ifc_ctrl->status);
+       if (ifc_ctrl->status != IFC_NAND_EVTER_STAT_OPC) {
+               printf("fsl-ifc: Failed to Initialise SRAM\n");
+               return 1;
+       }
+
+       ifc_out32(&ifc->ifc_nand.nand_evter_stat, ifc_ctrl->status);
 
        /* Restore CSOR and CSOR_ext */
-       out_be32(&ifc_ctrl->regs->csor_cs[cs].csor, csor);
-       out_be32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, csor_ext);
+       ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor, csor);
+       ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext, csor_ext);
+
+       return 0;
 }
 
 static int fsl_ifc_chip_init(int devnum, u8 *addr)
@@ -862,8 +884,9 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr)
        struct nand_chip *nand;
        struct fsl_ifc_mtd *priv;
        struct nand_ecclayout *layout;
+       struct fsl_ifc_fcm *gregs = NULL;
        uint32_t cspr = 0, csor = 0, ver = 0;
-       int ret;
+       int ret = 0;
 
        if (!ifc_ctrl) {
                fsl_ifc_ctrl_init();
@@ -877,14 +900,15 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr)
 
        priv->ctrl = ifc_ctrl;
        priv->vbase = addr;
+       gregs = ifc_ctrl->regs.gregs;
 
        /* Find which chip select it is connected to.
         */
        for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) {
                phys_addr_t phys_addr = virt_to_phys(addr);
 
-               cspr = in_be32(&ifc_ctrl->regs->cspr_cs[priv->bank].cspr);
-               csor = in_be32(&ifc_ctrl->regs->csor_cs[priv->bank].csor);
+               cspr = ifc_in32(&gregs->cspr_cs[priv->bank].cspr);
+               csor = ifc_in32(&gregs->csor_cs[priv->bank].csor);
 
                if ((cspr & CSPR_V) && (cspr & CSPR_MSEL) == CSPR_MSEL_NAND &&
                    (cspr & CSPR_BA) == CSPR_PHYS_ADDR(phys_addr)) {
@@ -910,7 +934,6 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr)
 
        nand->write_buf = fsl_ifc_write_buf;
        nand->read_buf = fsl_ifc_read_buf;
-       nand->verify_buf = fsl_ifc_verify_buf;
        nand->select_chip = fsl_ifc_select_chip;
        nand->cmdfunc = fsl_ifc_cmdfunc;
        nand->waitfunc = fsl_ifc_wait;
@@ -1004,9 +1027,14 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr)
                nand->ecc.mode = NAND_ECC_SOFT;
        }
 
-       ver = in_be32(&ifc_ctrl->regs->ifc_rev);
-       if (ver == FSL_IFC_V1_1_0)
-               fsl_ifc_sram_init();
+       ver = ifc_in32(&gregs->ifc_rev);
+       if (ver >= FSL_IFC_V1_1_0)
+               ret = fsl_ifc_sram_init(ver);
+       if (ret)
+               return ret;
+
+       if (ver >= FSL_IFC_V2_0_0)
+               priv->bufnum_mask = (priv->bufnum_mask * 2) + 1;
 
        ret = nand_scan_ident(mtd, 1, NULL);
        if (ret)