From: <b35362@freescale.com>
To: <dwmw2@infradead.org>
Cc: Liu Shuo <b35362@freescale.com>,
linuxppc-dev@ozlabs.org, linux-mtd@lists.infradead.org
Subject: [PATCH v2] mtd/nand : workaround for Freescale FCM to support large-page Nand chip
Date: Tue, 12 Jul 2011 12:48:42 +0800 [thread overview]
Message-ID: <1310446122-18050-1-git-send-email-b35362@freescale.com> (raw)
From: Liu Shuo <b35362@freescale.com>
Freescale FCM controller has a 2K size limitation of buffer RAM. In order
to support the Nand flash chip whose page size is larger than 2K bytes,
we divide a page into multi-2K pages for MTD layer driver. In that case,
we force to set the page size to 2K bytes. We convert the page address of
MTD layer driver to a real page address in flash chips and a column index
in fsl_elbc driver. We can issue any column address by UA instruction of
elbc controller.
Signed-off-by: Liu Shuo <b35362@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
drivers/mtd/nand/fsl_elbc_nand.c | 66 ++++++++++++++++++++++++++++++-------
1 files changed, 53 insertions(+), 13 deletions(-)
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index a212116..884a9f1 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -76,6 +76,13 @@ struct fsl_elbc_fcm_ctrl {
unsigned int oob; /* Non zero if operating on OOB data */
unsigned int counter; /* counter for the initializations */
char *oob_poi; /* Place to write ECC after read back */
+
+ /*
+ * If writesize > 2048, these two members are used to calculate
+ * the real page address and real column address.
+ */
+ int subpage_shift;
+ int subpage_mask;
};
/* These map to the positions used by the FCM hardware ECC generator */
@@ -164,18 +171,27 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
int buf_num;
+ u32 real_ca = column;
- elbc_fcm_ctrl->page = page_addr;
+ if (priv->page_size && elbc_fcm_ctrl->subpage_shift) {
+ real_ca = (page_addr & elbc_fcm_ctrl->subpage_mask) * 2112;
+ page_addr >>= elbc_fcm_ctrl->subpage_shift;
+ }
- out_be32(&lbc->fbar,
- page_addr >> (chip->phys_erase_shift - chip->page_shift));
+ elbc_fcm_ctrl->page = page_addr;
if (priv->page_size) {
+ real_ca += (oob ? 2048 : 0);
+ elbc_fcm_ctrl->use_mdr = 1;
+ elbc_fcm_ctrl->mdr = real_ca;
+
+ out_be32(&lbc->fbar, page_addr >> 6);
out_be32(&lbc->fpar,
((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) |
(oob ? FPAR_LP_MS : 0) | column);
buf_num = (page_addr & 1) << 2;
} else {
+ out_be32(&lbc->fbar, page_addr >> 5);
out_be32(&lbc->fpar,
((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) |
(oob ? FPAR_SP_MS : 0) | column);
@@ -256,10 +272,11 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
if (priv->page_size) {
out_be32(&lbc->fir,
(FIR_OP_CM0 << FIR_OP0_SHIFT) |
- (FIR_OP_CA << FIR_OP1_SHIFT) |
- (FIR_OP_PA << FIR_OP2_SHIFT) |
- (FIR_OP_CM1 << FIR_OP3_SHIFT) |
- (FIR_OP_RBW << FIR_OP4_SHIFT));
+ (FIR_OP_UA << FIR_OP1_SHIFT) |
+ (FIR_OP_UA << FIR_OP2_SHIFT) |
+ (FIR_OP_PA << FIR_OP3_SHIFT) |
+ (FIR_OP_CM1 << 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));
@@ -399,12 +416,13 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
if (priv->page_size) {
out_be32(&lbc->fir,
(FIR_OP_CM2 << FIR_OP0_SHIFT) |
- (FIR_OP_CA << FIR_OP1_SHIFT) |
- (FIR_OP_PA << FIR_OP2_SHIFT) |
- (FIR_OP_WB << FIR_OP3_SHIFT) |
- (FIR_OP_CM3 << FIR_OP4_SHIFT) |
- (FIR_OP_CW1 << FIR_OP5_SHIFT) |
- (FIR_OP_RS << FIR_OP6_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_CM3 << FIR_OP5_SHIFT) |
+ (FIR_OP_CW1 << FIR_OP6_SHIFT) |
+ (FIR_OP_RS << FIR_OP7_SHIFT));
} else {
out_be32(&lbc->fir,
(FIR_OP_CM0 << FIR_OP0_SHIFT) |
@@ -453,6 +471,9 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
full_page = 1;
}
+ if (priv->page_size)
+ elbc_fcm_ctrl->use_mdr = 1;
+
fsl_elbc_run_command(mtd);
/* Read back the page in order to fill in the ECC for the
@@ -654,9 +675,28 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_lbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
unsigned int al;
+ /*
+ * Hack for supporting the flash chip whose writesize is
+ * larger than 2K bytes.
+ */
+ if (mtd->writesize > 2048) {
+ elbc_fcm_ctrl->subpage_shift = ffs(mtd->writesize >> 11) - 1;
+ elbc_fcm_ctrl->subpage_mask =
+ (1 << elbc_fcm_ctrl->subpage_shift) - 1;
+ /*
+ * Rewrite mtd->writesize, mtd->oobsize, chip->page_shift
+ * and chip->pagemask.
+ */
+ mtd->writesize = 2048;
+ mtd->oobsize = 64;
+ chip->page_shift = ffs(mtd->writesize) - 1;
+ chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
+ }
+
/* calculate FMR Address Length field */
al = 0;
if (chip->pagemask & 0xffff0000)
--
1.7.1
next reply other threads:[~2011-07-12 5:44 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-07-12 4:48 b35362 [this message]
2011-08-03 6:15 ` [PATCH v2] mtd/nand : workaround for Freescale FCM to support large-page Nand chip Li Yang-R58472
2011-08-15 15:59 ` Artem Bityutskiy
2011-08-15 16:11 ` Scott Wood
2011-08-15 16:24 ` Artem Bityutskiy
2011-09-02 7:10 ` Stijn Devriendt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1310446122-18050-1-git-send-email-b35362@freescale.com \
--to=b35362@freescale.com \
--cc=dwmw2@infradead.org \
--cc=linux-mtd@lists.infradead.org \
--cc=linuxppc-dev@ozlabs.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).