[U-Boot] [PATCH 2/2] mtd/nand : workaround for Freescale FCM to supportlarge-page Nand chip
Mike Hench
mhench at elutions.com
Fri Jul 8 21:10:03 CEST 2011
Ok, so to port Liu Shuo's huge page nand to fake 2k page patch to uboot
We either need to introduce a callback after mtd initialization
(Which would have to be outside the driver) or lie about the ID info
coming from the driver.
I choose the second.
Does this look reasonable to you guys?
The IPL boot loader part is NOT included here.
The new stuff is fix_id_info()
diff -purN orig/drivers/mtd/nand/fsl_elbc_nand.c
u-boot-2011.06/drivers/mtd/nand/fsl_elbc_nand.c
--- orig/drivers/mtd/nand/fsl_elbc_nand.c 2011-07-08
14:18:18.634544056 -0500
+++ u-boot-2011.06/drivers/mtd/nand/fsl_elbc_nand.c 2011-07-08
14:17:58.592570060 -0500
@@ -86,6 +86,10 @@ struct fsl_elbc_ctrl {
unsigned int use_mdr; /* Non zero if the MDR is to be set
*/
unsigned int oob; /* Non zero if operating on OOB data
*/
uint8_t *oob_poi; /* Place to write ECC after read back
*/
+
+ int subpage_shift; /* If writesize > 2048, these two
members*/
+ int subpage_mask; /* are used to calculate the real page
*/
+ /* address and real column address */
};
/* These map to the positions used by the FCM hardware ECC generator */
@@ -173,10 +177,20 @@ static void set_addr(struct mtd_info *mt
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
fsl_lbc_t *lbc = ctrl->regs;
int buf_num;
+ u32 real_ca = column;
+
+ if (priv->page_size && ctrl->subpage_shift) {
+ real_ca = (page_addr & ctrl->subpage_mask) * 2112;
+ page_addr >>= ctrl->subpage_shift;
+ }
ctrl->page = page_addr;
if (priv->page_size) {
+ real_ca += (oob ? 2048 : 0);
+ ctrl->use_mdr = 1;
+ ctrl->mdr = real_ca;
+
out_be32(&lbc->fbar, page_addr >> 6);
out_be32(&lbc->fpar,
((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI)
|
@@ -265,11 +279,12 @@ static void fsl_elbc_do_read(struct nand
if (priv->page_size) {
out_be32(&lbc->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
- (FIR_OP_CA << FIR_OP1_SHIFT) |
- (FIR_OP_PA << FIR_OP2_SHIFT) |
- (FIR_OP_CW1 << FIR_OP3_SHIFT) |
- (FIR_OP_RBW << FIR_OP4_SHIFT));
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_UA << FIR_OP1_SHIFT) |
+ (FIR_OP_UA << FIR_OP2_SHIFT) |
+ (FIR_OP_PA << FIR_OP3_SHIFT) |
+ (FIR_OP_CW1 << FIR_OP4_SHIFT) |
+ (FIR_OP_RBW << FIR_OP5_SHIFT));
out_be32(&lbc->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) |
(NAND_CMD_READSTART <<
FCR_CMD1_SHIFT));
@@ -288,6 +303,28 @@ static void fsl_elbc_do_read(struct nand
}
}
+#ifdef CONFIG_NAND_FSL_ELBC_HUGE_PAGE_WORKAROUND
+void fix_id_info(struct fsl_elbc_ctrl *ctrl)
+{
+ int ext = in_8(&ctrl->addr[ctrl->index+3]);
+
+ /* Hack for supporting the flash chip whose writesize is
+ * larger than 2K bytes. if the page size is 4k or greater
+ * say it is 2k.
+ */
+ if(ext == 0xff)
+ return;
+ if((ext & 0x3) >= 2) {
+ ctrl->subpage_shift = (ext & 0x3) - 1;
+ ctrl->subpage_mask = (1 << ctrl->subpage_shift) - 1;
+ ext &= ~0x3;
+ ext |= 1;
+ out_8(&ctrl->addr[ctrl->index+3], ext);
+ ext = in_8(&ctrl->addr[ctrl->index+3]);
+ }
+}
+#endif
+
/* cmdfunc send commands to the FCM */
static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int
command,
int column, int page_addr)
@@ -355,6 +392,9 @@ static void fsl_elbc_cmdfunc(struct mtd_
set_addr(mtd, 0, 0, 0);
fsl_elbc_run_command(mtd);
+#ifdef CONFIG_NAND_FSL_ELBC_HUGE_PAGE_WORKAROUND
+ fix_id_info(ctrl);
+#endif
return;
/* ERASE1 stores the block and page address */
@@ -399,10 +439,11 @@ static void fsl_elbc_cmdfunc(struct mtd_
out_be32(&lbc->fir,
(FIR_OP_CW0 << FIR_OP0_SHIFT) |
- (FIR_OP_CA << FIR_OP1_SHIFT) |
- (FIR_OP_PA << FIR_OP2_SHIFT) |
- (FIR_OP_WB << FIR_OP3_SHIFT) |
- (FIR_OP_CW1 << FIR_OP4_SHIFT));
+ (FIR_OP_UA << FIR_OP1_SHIFT) |
+ (FIR_OP_UA << FIR_OP2_SHIFT) |
+ (FIR_OP_PA << FIR_OP3_SHIFT) |
+ (FIR_OP_WB << FIR_OP4_SHIFT) |
+ (FIR_OP_CW1 << FIR_OP5_SHIFT));
} else {
fcr = (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT) |
(NAND_CMD_SEQIN << FCR_CMD2_SHIFT);
@@ -453,6 +494,10 @@ static void fsl_elbc_cmdfunc(struct mtd_
full_page = 1;
}
+ if (priv->page_size)
+ ctrl->use_mdr = 1;
+
+
fsl_elbc_run_command(mtd);
ctrl->oob_poi = NULL;
More information about the U-Boot
mailing list