]> git.karo-electronics.de Git - karo-tx-uboot.git/blobdiff - drivers/mtd/nand/fsl_elbc_nand.c
nand/fsl: add NAND_NO_SUBPAGE_WRITE to eLBC and IFC drivers
[karo-tx-uboot.git] / drivers / mtd / nand / fsl_elbc_nand.c
index 4d1e527db103f54359f6744fa9df601007ca5ce6..834a8a64983f35d01abdb1383cd928fbb155b6ff 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <common.h>
 #include <malloc.h>
+#include <nand.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -57,7 +58,6 @@ struct fsl_elbc_ctrl;
 /* mtd information per set */
 
 struct fsl_elbc_mtd {
-       struct mtd_info mtd;
        struct nand_chip chip;
        struct fsl_elbc_ctrl *ctrl;
 
@@ -340,18 +340,21 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
        /* READID must read all 5 possible bytes while CEB is active */
        case NAND_CMD_READID:
-               vdbg("fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
+       case NAND_CMD_PARAM:
+               vdbg("fsl_elbc_cmdfunc: NAND_CMD 0x%x.\n", command);
 
                out_be32(&lbc->fir, (FIR_OP_CW0 << FIR_OP0_SHIFT) |
                                    (FIR_OP_UA  << FIR_OP1_SHIFT) |
                                    (FIR_OP_RBW << FIR_OP2_SHIFT));
-               out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
-               /* 5 bytes for manuf, device and exts */
-               out_be32(&lbc->fbcr, 5);
-               ctrl->read_bytes = 5;
+               out_be32(&lbc->fcr, command << FCR_CMD0_SHIFT);
+               /*
+                * although currently it's 8 bytes for READID, we always read
+                * the maximum 256 bytes(for PARAM)
+                */
+               out_be32(&lbc->fbcr, 256);
+               ctrl->read_bytes = 256;
                ctrl->use_mdr = 1;
-               ctrl->mdr = 0;
-
+               ctrl->mdr = column;
                set_addr(mtd, 0, 0, 0);
                fsl_elbc_run_command(mtd);
                return;
@@ -683,10 +686,13 @@ static void fsl_elbc_ctrl_init(void)
        elbc_ctrl->addr = NULL;
 }
 
-int board_nand_init(struct nand_chip *nand)
+static int fsl_elbc_chip_init(int devnum, u8 *addr)
 {
+       struct mtd_info *mtd = &nand_info[devnum];
+       struct nand_chip *nand;
        struct fsl_elbc_mtd *priv;
        uint32_t br = 0, or = 0;
+       int ret;
 
        if (!elbc_ctrl) {
                fsl_elbc_ctrl_init();
@@ -699,19 +705,19 @@ int board_nand_init(struct nand_chip *nand)
                return -ENOMEM;
 
        priv->ctrl = elbc_ctrl;
-       priv->vbase = nand->IO_ADDR_R;
+       priv->vbase = addr;
 
        /* Find which chip select it is connected to.  It'd be nice
         * if we could pass more than one datum to the NAND driver...
         */
        for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) {
-               phys_addr_t base_addr = virt_to_phys(nand->IO_ADDR_R);
+               phys_addr_t phys_addr = virt_to_phys(addr);
 
                br = in_be32(&elbc_ctrl->regs->bank[priv->bank].br);
                or = in_be32(&elbc_ctrl->regs->bank[priv->bank].or);
 
                if ((br & BR_V) && (br & BR_MSEL) == BR_MS_FCM &&
-                   (br & or & BR_BA) == BR_PHYS_ADDR(base_addr))
+                   (br & or & BR_BA) == BR_PHYS_ADDR(phys_addr))
                        break;
        }
 
@@ -721,6 +727,9 @@ int board_nand_init(struct nand_chip *nand)
                return -ENODEV;
        }
 
+       nand = &priv->chip;
+       mtd->priv = nand;
+
        elbc_ctrl->chips[priv->bank] = priv;
 
        /* fill in nand_chip structure */
@@ -739,7 +748,7 @@ int board_nand_init(struct nand_chip *nand)
 
        /* set up nand options */
        nand->options = NAND_NO_READRDY | NAND_NO_AUTOINCR |
-                       NAND_USE_FLASH_BBT;
+                       NAND_USE_FLASH_BBT | NAND_NO_SUBPAGE_WRITE;
 
        nand->controller = &elbc_ctrl->controller;
        nand->priv = priv;
@@ -791,5 +800,32 @@ int board_nand_init(struct nand_chip *nand)
                }
        }
 
+       ret = nand_scan_ident(mtd, 1, NULL);
+       if (ret)
+               return ret;
+
+       ret = nand_scan_tail(mtd);
+       if (ret)
+               return ret;
+
+       ret = nand_register(devnum);
+       if (ret)
+               return ret;
+
        return 0;
 }
+
+#ifndef CONFIG_SYS_NAND_BASE_LIST
+#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE }
+#endif
+
+static unsigned long base_address[CONFIG_SYS_MAX_NAND_DEVICE] =
+       CONFIG_SYS_NAND_BASE_LIST;
+
+void board_nand_init(void)
+{
+       int i;
+
+       for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
+               fsl_elbc_chip_init(i, (u8 *)base_address[i]);
+}