From: LiuShuo <b35362@freescale.com>
To: Scott Wood <scottwood@freescale.com>
Cc: Artem.Bityutskiy@nokia.com, linuxppc-dev@lists.ozlabs.org,
linux-kernel@vger.kernel.org, Liu Shuo <Shuo.Liu@freescale.com>,
Shengzhou Liu <Shengzhou.Liu@freescale.com>,
linux-mtd@lists.infradead.org, akpm@linux-foundation.org,
dwmw2@infradead.org
Subject: Re: [PATCH v3 3/3] mtd/nand : workaround for Freescale FCM to support large-page Nand chip
Date: Wed, 23 Nov 2011 20:14:11 +0800 [thread overview]
Message-ID: <4ECCE393.2030600@freescale.com> (raw)
In-Reply-To: <4ECC368C.3010801@freescale.com>
=E4=BA=8E 2011=E5=B9=B411=E6=9C=8823=E6=97=A5 07:55, Scott Wood =E5=86=99=
=E9=81=93:
> On 11/15/2011 03:29 AM, b35362@freescale.com wrote:
>> From: Liu Shuo<b35362@freescale.com>
>>
>> Freescale FCM controller has a 2K size limitation of buffer RAM. In or=
der
>> to support the Nand flash chip whose page size is larger than 2K bytes=
,
>> we read/write 2k data repeatedly by issuing FIR_OP_RB/FIR_OP_WB and sa=
ve
>> them to a large buffer.
>>
>> Signed-off-by: Liu Shuo<Shuo.Liu@freescale.com>
>> Signed-off-by: Shengzhou Liu<Shengzhou.Liu@freescale.com>
>> Signed-off-by: Li Yang<leoli@freescale.com>
>> ---
>> drivers/mtd/nand/fsl_elbc_nand.c | 216 ++++++++++++++++++++++++++++=
+++++++---
>> 1 files changed, 199 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_e=
lbc_nand.c
>> index c2c231b..415f87e 100644
>> --- a/drivers/mtd/nand/fsl_elbc_nand.c
>> +++ b/drivers/mtd/nand/fsl_elbc_nand.c
>> @@ -55,7 +55,9 @@ struct fsl_elbc_mtd {
>> struct device *dev;
>> int bank; /* Chip select bank number */
>> u8 __iomem *vbase; /* Chip select base virtual address */
>> - int page_size; /* NAND page size (0=3D512, 1=3D2048) */
>> + int page_size; /* NAND page size (0=3D512, 1=3D2048, 2=3D40=
96...),
>> + * the mutiple of 2048.
>> + */
> That "..." isn't very descriptive. What happens with 8192-byte pages?
> Is it 3 or 4?
>
> Please just get rid of this and use mtd->writesize.
>
>> + for (i =3D 1; i< priv->page_size; i++) {
>> + /*
>> + * Maybe there are some reasons of FCM hardware timming,
>> + * we must insert a FIR_OP_NOP(0x00) before FIR_OP_RB.
>> + */
> s/timming/timing/
>
>> /* PAGEPROG reuses all of the setup from SEQIN and adds the length =
*/
>> case NAND_CMD_PAGEPROG: {
>> + int len;
>> dev_vdbg(priv->dev,
>> "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG "
>> "writing %d bytes.\n", elbc_fcm_ctrl->index);
>> -
>> /* if the write did not start at 0 or is not a full page
>> * then set the exact length, otherwise use a full page
>> * write so the HW generates the ECC.
>> */
>> - if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column !=3D 0 ||
>> + if (elbc_fcm_ctrl->column>=3D mtd->writesize) {
>> + /* write oob */
>> + if (priv->page_size> 1) {
>> + /* when pagesize of chip is greater than 2048,
>> + * we have to write full page to write spare
>> + * region, so we fill '0xff' to main region
>> + * and some bytes of spare region which we
>> + * don't want to rewrite.
>> + * (write '1' won't change the original value)
>> + */
>> + memset(elbc_fcm_ctrl->buffer, 0xff,
>> + elbc_fcm_ctrl->column);
> I don't like relying on this -- can we use RNDIN instead to do a
> discontiguous write?
>
I have no better way to implement it now.
Some chips have 'NOP' limitation, so I don't use the FIR_OP_UA to do a=20
oob write.
>> + len =3D 2112;
> len =3D min(elbc_fcm_ctrl->index, 2112);
when do a oob write (writesize > 2048), elbc_fcm_ctrl->index is greater=20
writesize
(is 4096 at least).
>> + } else
>> + len =3D mtd->writesize + mtd->oobsize -
>> + elbc_fcm_ctrl->column;
>> + out_be32(&lbc->fbcr, len);
> len =3D elbc_fcm_ctrl->index - elbc_fcm_ctrl->column;
>
> Use braces on both sides of the if/else if it's needed on one side.
>> + } else if (elbc_fcm_ctrl->column !=3D 0 ||
>> elbc_fcm_ctrl->index !=3D mtd->writesize + mtd->oobsize)
>> out_be32(&lbc->fbcr, elbc_fcm_ctrl->index);
> This should have set fbcr to index - column as well (after adjusting --
> though really it's not a supported use case. We should only be seeing
> column !=3D 0 for oob.
>
I have make a independent to fix this issue.
(In fact,documentation says FCM will stop automatically after
reading the last byte of spare region)
>> @@ -625,10 +776,16 @@ static int fsl_elbc_verify_buf(struct mtd_info *=
mtd, const u_char *buf, int len)
>> return -EINVAL;
>> }
>>
>> - for (i =3D 0; i< len; i++)
>> - if (in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index + i])
>> - !=3D buf[i])
>> - break;
>> + if (mtd->writesize> 2048)
>> + for (i =3D 0; i< len; i++)
>> + if (elbc_fcm_ctrl->buffer[elbc_fcm_ctrl->index + i]
>> + !=3D buf[i])
>> + break;
>> + else
>> + for (i =3D 0; i< len; i++)
>> + if (in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index + i])
>> + !=3D buf[i])
>> + break;
> Please use braces around multiline if/for bodies, even if they're
> technically a single statement -- especially when you've got a dangling
> else.
>
>> elbc_fcm_ctrl->index +=3D len;
>> return i =3D=3D len&& elbc_fcm_ctrl->status =3D=3D LTESR_CC ? 0 : =
-EIO;
>> @@ -657,6 +814,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info=
*mtd)
>> struct fsl_elbc_mtd *priv =3D chip->priv;
>> struct fsl_lbc_ctrl *ctrl =3D priv->ctrl;
>> struct fsl_lbc_regs __iomem *lbc =3D ctrl->regs;
>> + struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl =3D ctrl->nand;
>> unsigned int al;
>>
>> /* calculate FMR Address Length field */
>> @@ -707,12 +865,17 @@ static int fsl_elbc_chip_init_tail(struct mtd_in=
fo *mtd)
>> dev_dbg(priv->dev, "fsl_elbc_init: mtd->oobsize =3D %d\n",
>> mtd->oobsize);
>>
>> + kfree(elbc_fcm_ctrl->buffer);
>> + elbc_fcm_ctrl->buffer =3D NULL;
>> +
>> /* adjust Option Register and ECC to match Flash page size */
>> if (mtd->writesize =3D=3D 512) {
>> priv->page_size =3D 0;
>> clrbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS);
>> - } else if (mtd->writesize =3D=3D 2048) {
>> - priv->page_size =3D 1;
>> + } else if (mtd->writesize>=3D 2048) {
>> + /* page_size =3D writesize / 2048 */
>> + priv->page_size =3D mtd->writesize>> 11;
> Why not just write priv->page_size =3D mtd->writesize / 2048 in the cod=
e
> rather than the comment (it compiles to the same code)? Other than
> because you were requested to remove priv->page_size, that is. :-)
>
>> setbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS);
>> /* adjust ecc setup if needed */
>> if ((in_be32(&lbc->bank[priv->bank].br)& BR_DECC) =3D=3D
>> @@ -723,6 +886,14 @@ static int fsl_elbc_chip_init_tail(struct mtd_inf=
o *mtd)
>> &fsl_elbc_oob_lp_eccm0;
>> chip->badblock_pattern =3D&largepage_memorybased;
>> }
>> +
>> + /* re-malloc if pagesize> 2048*/
>> + if (mtd->writesize> 2048) {
>> + elbc_fcm_ctrl->buffer =3D kmalloc(mtd->writesize +
>> + mtd->oobsize, GFP_KERNEL);
>> + if (!elbc_fcm_ctrl->buffer)
>> + return -ENOMEM;
>> + }
>> } else {
>> dev_err(priv->dev,
>> "fsl_elbc_init: page size %d is not supported\n",
> buffer is a controller-wide resource, but you're setting it based on th=
e
> most-recently-probed NAND chip. It should be large enough to
> accommodate the largest page size in use on any connected chip. Even i=
f
> all chips in the system have the same page size, you're introducing a
> race if a previously-probed chip is already in use (the controller lock
> is not held here).
>
> Just allocate a buffer large enough for a 16K page size in the main ini=
t
> function, and print an error in the tail if you encounter a larger page
> size.
>
>> @@ -886,6 +1057,17 @@ static int __devinit fsl_elbc_nand_probe(struct =
platform_device *pdev)
>> goto err;
>> }
>> elbc_fcm_ctrl->counter++;
>> + /*
>> + * Freescale FCM controller has a 2K size limitation of buffer
>> + * RAM, so elbc_fcm_ctrl->buffer have to be used if writesize
>> + * of chip is greater than 2048.
>> + * We malloc a large enough buffer at this point, because we
>> + * don't know writesize before calling nand_scan(). We will
>> + * re-malloc later if needed.
>> + */
>> + elbc_fcm_ctrl->buffer =3D kmalloc(4096 * 6, GFP_KERNEL);
>> + if (!elbc_fcm_ctrl->buffer)
>> + return -ENOMEM;
> Clean up properly if you fail to allocate the buffer. This includes
> freeing elbc_fcm_ctrl, setting fsl_lbc_ctrl_dev->nand to NULL, and
> releasing fsl_elbc_nand_mutex.
> -Scott
- LiuShuo
next prev parent reply other threads:[~2011-11-23 12:10 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-11-15 9:29 [PATCH 1/3] mtd/nand: fix coding style issue in drivers/mtd/nand/fsl_elbc.c b35362
2011-11-15 9:29 ` [PATCH 2/3] mtd/nand : set Nand flash page address to FBAR and FPAR correctly b35362
2011-11-15 9:29 ` [PATCH v3 3/3] mtd/nand : workaround for Freescale FCM to support large-page Nand chip b35362
2011-11-22 21:04 ` Artem Bityutskiy
2011-11-22 23:55 ` Scott Wood
2011-11-23 1:56 ` LiuShuo
2011-11-23 12:14 ` LiuShuo [this message]
2011-11-28 21:41 ` Scott Wood
2011-11-17 22:13 ` [PATCH 2/3] mtd/nand : set Nand flash page address to FBAR and FPAR correctly Artem Bityutskiy
2011-11-18 2:08 ` LiuShuo
2011-11-22 21:05 ` Artem Bityutskiy
2011-11-15 11:26 ` [PATCH 1/3] mtd/nand: fix coding style issue in drivers/mtd/nand/fsl_elbc.c Jenkins, Clive
2011-11-15 13:10 ` David Woodhouse
2011-11-15 14:42 ` Jenkins, Clive
2011-11-15 15:05 ` David Woodhouse
2011-11-15 14:51 ` David Laight
2011-11-17 22:08 ` Artem Bityutskiy
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=4ECCE393.2030600@freescale.com \
--to=b35362@freescale.com \
--cc=Artem.Bityutskiy@nokia.com \
--cc=Shengzhou.Liu@freescale.com \
--cc=Shuo.Liu@freescale.com \
--cc=akpm@linux-foundation.org \
--cc=dwmw2@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mtd@lists.infradead.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=scottwood@freescale.com \
/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).