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; _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot