]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/mtd/nand/fsl_ifc_nand.c
driver/mtd:IFC NAND:Initialise internal SRAM before any write
[karo-tx-linux.git] / drivers / mtd / nand / fsl_ifc_nand.c
index 9602c1b7e27e8e5a70c66f50a47df04693b4bf1e..01e2f2e87d8c2b7166f548f6ec14d557b596673b 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/mtd/nand_ecc.h>
 #include <asm/fsl_ifc.h>
 
+#define FSL_IFC_V1_1_0 0x01010000
 #define ERR_BYTE               0xFF /* Value returned for read
                                        bytes when read failed  */
 #define IFC_TIMEOUT_MSECS      500  /* Maximum number of mSecs to wait
@@ -773,13 +774,62 @@ static int fsl_ifc_chip_init_tail(struct mtd_info *mtd)
        return 0;
 }
 
+static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv)
+{
+       struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+       struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
+       uint32_t csor = 0, csor_8k = 0, csor_ext = 0;
+       uint32_t cs = priv->bank;
+
+       /* Save CSOR and CSOR_ext */
+       csor = in_be32(&ifc->csor_cs[cs].csor);
+       csor_ext = in_be32(&ifc->csor_cs[cs].csor_ext);
+
+       /* chage PageSize 8K and SpareSize 1K*/
+       csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000;
+       out_be32(&ifc->csor_cs[cs].csor, csor_8k);
+       out_be32(&ifc->csor_cs[cs].csor_ext, 0x0000400);
+
+       /* READID */
+       out_be32(&ifc->ifc_nand.nand_fir0,
+                       (IFC_FIR_OP_CMD0 << 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);
+
+       out_be32(&ifc->ifc_nand.nand_fbcr, 0x0);
+
+       /* Program ROW0/COL0 */
+       out_be32(&ifc->ifc_nand.row0, 0x0);
+       out_be32(&ifc->ifc_nand.col0, 0x0);
+
+       /* set the chip select for NAND Transaction */
+       out_be32(&ifc->ifc_nand.nand_csel, cs << IFC_NAND_CSEL_SHIFT);
+
+       /* start read seq */
+       out_be32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT);
+
+       /* wait for command complete flag or timeout */
+       wait_event_timeout(ctrl->nand_wait, ctrl->nand_stat,
+                          IFC_TIMEOUT_MSECS * HZ/1000);
+
+       if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC)
+               printk(KERN_ERR "fsl-ifc: Failed to Initialise SRAM\n");
+
+       /* Restore CSOR and CSOR_ext */
+       out_be32(&ifc->csor_cs[cs].csor, csor);
+       out_be32(&ifc->csor_cs[cs].csor_ext, csor_ext);
+}
+
 static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
 {
        struct fsl_ifc_ctrl *ctrl = priv->ctrl;
        struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
        struct nand_chip *chip = &priv->chip;
        struct nand_ecclayout *layout;
-       u32 csor;
+       u32 csor, ver;
 
        /* Fill in fsl_ifc_mtd structure */
        priv->mtd.priv = chip;
@@ -874,6 +924,10 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
                chip->ecc.mode = NAND_ECC_SOFT;
        }
 
+       ver = in_be32(&ifc->ifc_rev);
+       if (ver == FSL_IFC_V1_1_0)
+               fsl_ifc_sram_init(priv);
+
        return 0;
 }