Patchwork [v2,3/3] Add 4-bit ECC support for large page NAND chips on Davinci

login
register
mail settings
Submitter Sandeep Paulraj
Date June 16, 2009, 8:23 p.m.
Message ID <1245183812-11500-1-git-send-email-s-paulraj@ti.com>
Download mbox | patch
Permalink /patch/28744/
State New, archived
Headers show

Comments

Sandeep Paulraj - June 16, 2009, 8:23 p.m.
From: Sandeep Paulraj <s-paulraj@ti.com>

The patch applies to linux-mtd GIT tree

This patch adds 4-bit ECC support for large page NAND chips using the new ECC
mode NAND_ECC_HW_OOB_FIRST. The platform data from board-dm355-evm has been
adjusted to use this mode.

The patches have been verified on DM355 device with 2K and 4K page size 
Micron devices using mtd-tests.
Error correction upto 4-bits has also been verified using
nandwrite/nanddump utilities.

Reviewed-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Sandeep Paulraj <s-paulraj@ti.com>
Signed-off-by: Sneha Narnakaje <nsnehaprabha@ti.com>
---
 drivers/mtd/nand/davinci_nand.c |   65 ++++++++++++++++++++++++++++++++++----
 1 files changed, 58 insertions(+), 7 deletions(-)
Troy Kisky - June 18, 2009, 9:16 p.m.
s-paulraj@ti.com wrote:
> From: Sandeep Paulraj <s-paulraj@ti.com>
> 
> The patch applies to linux-mtd GIT tree
> 
> This patch adds 4-bit ECC support for large page NAND chips using the new ECC
> mode NAND_ECC_HW_OOB_FIRST. The platform data from board-dm355-evm has been
> adjusted to use this mode.
> 
> The patches have been verified on DM355 device with 2K and 4K page size 
> Micron devices using mtd-tests.
> Error correction upto 4-bits has also been verified using
> nandwrite/nanddump utilities.
> 
> Reviewed-by: David Brownell <dbrownell@users.sourceforge.net>
> Signed-off-by: Sandeep Paulraj <s-paulraj@ti.com>
> Signed-off-by: Sneha Narnakaje <nsnehaprabha@ti.com>
> ---
>  drivers/mtd/nand/davinci_nand.c |   65 ++++++++++++++++++++++++++++++++++----
>  1 files changed, 58 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
> index ba6940d..2ff0712 100644
> --- a/drivers/mtd/nand/davinci_nand.c
> +++ b/drivers/mtd/nand/davinci_nand.c
> @@ -500,6 +500,49 @@ static struct nand_ecclayout hwecc4_small __initconst = {
>  	},
>  };
>  
> +/* An ECC layout for using 4-bit ECC with large-page (2048bytes) flash,
> + * storing ten ECC bytes plus the manufacturer's bad block marker byte,
> + * and not overlapping the default BBT markers.
> + */
> +static struct nand_ecclayout hwecc4_2048 __initconst = {
> +	.eccbytes = 40,
> +	.eccpos = { /* 2 bytes at offset 0 hold the badblock markers */
> +		/* 4 bytes at offset 8 hold BBT header */
> +		/* 1 byte at offset 12 holds BBT version */
> +		/* 8 bytes at offset 16 hold JFFS2 clean markers */
> +		24, 25, 26, 27, 28, 29,	30, 31, 32, 33,
> +		34, 35, 36, 37, 38, 39,	40, 41, 42, 43,
> +		44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
> +		54, 55, 56, 57, 58, 59, 60, 61, 62, 63, },
> +	.oobfree = {
> +		{.offset = 16, .length = 8, },

why not  offset = 2, length = 22
Won't the badblock marker show if this is used as a BBT?
Can JFFS2 not use the same bytes when not a BBT?

> +		{.offset = 64, },

You can kill the above line.

> +	},
> +};
> +
> +/* An ECC layout for using 4-bit ECC with large-page (4096bytes) flash,
> + * storing ten ECC bytes plus the manufacturer's bad block marker byte,
> + * and not overlapping the default BBT markers.
> + */
> +static struct nand_ecclayout hwecc4_4096 __initconst = {
> +	.eccbytes = 80,
> +	.eccpos = { /* 2 bytes at offset 0 hold the badblock markers */
> +		/* 4 bytes at offset 8 hold BBT header */
> +		/* 1 byte at offset 12 holds BBT version */
> +		/* 8 bytes at offset 16 hold JFFS2 clean markers */
> +		24, 25, 26, 27, 28, 29,	30, 31, 32, 33,
> +		34, 35, 36, 37, 38, 39,	40, 41, 42, 43,
> +		44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
> +		54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
> +		64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
> +		74, 75, 76, 77, 78, 69,	80, 81, 82, 83,
> +		84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
> +		94, 95, 96, 97, 98, 99, 100, 101, 102, 103, },

Can these not be at the end??? i.e. 48-127

> +	.oobfree = {
> +		{.offset = 16, .length = 8, },
> +		{.offset = 104, },
> +	},
> +};
>  
>  static int __init nand_davinci_probe(struct platform_device *pdev)
>  {
> @@ -689,15 +732,23 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
>  				info->mtd.oobsize - 16;
>  			goto syndrome_done;
>  		}
> +		if (chunks == 4) {
> +			info->ecclayout = hwecc4_2048;
> +			info->ecclayout.oobfree[1].length = info->mtd.oobsize -
> +				info->ecclayout.oobfree[1].offset;

This can be removed, it is already 0.

> +			info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST;
> +			goto syndrome_done;
> +		}
> +		if (chunks == 8) {
> +			info->ecclayout = hwecc4_4096;
> +			info->ecclayout.oobfree[1].length = info->mtd.oobsize -
> +				info->ecclayout.oobfree[1].offset;
> +			info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST;
> +			goto syndrome_done;
> +		}
>  
> -		/* For large page chips we'll be wanting to use a
> -		 * not-yet-implemented mode that reads OOB data
> -		 * before reading the body of the page, to avoid
> -		 * the "infix OOB" model of NAND_ECC_HW_SYNDROME
> -		 * (and preserve manufacturer badblock markings).
> -		 */
>  		dev_warn(&pdev->dev, "no 4-bit ECC support yet "
> -				"for large page NAND\n");
> +				"for >4K page NAND\n");
>  		ret = -EIO;
>  		goto err_scan;
>
Sandeep Paulraj - June 18, 2009, 9:34 p.m.
> -----Original Message-----
> From: Troy Kisky [mailto:troy.kisky@boundarydevices.com]
> Sent: Thursday, June 18, 2009 5:16 PM
> To: Paulraj, Sandeep
> Cc: davinci-linux-open-source@linux.davincidsp.com; linux-
> mtd@lists.infradead.org; dwmw2@infradead.org; tglx@linutronix.de;
> akpm@linux-foundation.org
> Subject: Re: [PATCH v2 3/3] Add 4-bit ECC support for large page NAND
> chips on Davinci
> 
> s-paulraj@ti.com wrote:
> > From: Sandeep Paulraj <s-paulraj@ti.com>
> >
> > The patch applies to linux-mtd GIT tree
> >
> > This patch adds 4-bit ECC support for large page NAND chips using the
> new ECC
> > mode NAND_ECC_HW_OOB_FIRST. The platform data from board-dm355-evm has
> been
> > adjusted to use this mode.
> >
> > The patches have been verified on DM355 device with 2K and 4K page size
> > Micron devices using mtd-tests.
> > Error correction upto 4-bits has also been verified using
> > nandwrite/nanddump utilities.
> >
> > Reviewed-by: David Brownell <dbrownell@users.sourceforge.net>
> > Signed-off-by: Sandeep Paulraj <s-paulraj@ti.com>
> > Signed-off-by: Sneha Narnakaje <nsnehaprabha@ti.com>
> > ---
> >  drivers/mtd/nand/davinci_nand.c |   65
> ++++++++++++++++++++++++++++++++++----
> >  1 files changed, 58 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/mtd/nand/davinci_nand.c
> b/drivers/mtd/nand/davinci_nand.c
> > index ba6940d..2ff0712 100644
> > --- a/drivers/mtd/nand/davinci_nand.c
> > +++ b/drivers/mtd/nand/davinci_nand.c
> > @@ -500,6 +500,49 @@ static struct nand_ecclayout hwecc4_small
> __initconst = {
> >  	},
> >  };
> >
> > +/* An ECC layout for using 4-bit ECC with large-page (2048bytes) flash,
> > + * storing ten ECC bytes plus the manufacturer's bad block marker byte,
> > + * and not overlapping the default BBT markers.
> > + */
> > +static struct nand_ecclayout hwecc4_2048 __initconst = {
> > +	.eccbytes = 40,
> > +	.eccpos = { /* 2 bytes at offset 0 hold the badblock markers */
> > +		/* 4 bytes at offset 8 hold BBT header */
> > +		/* 1 byte at offset 12 holds BBT version */
> > +		/* 8 bytes at offset 16 hold JFFS2 clean markers */
> > +		24, 25, 26, 27, 28, 29,	30, 31, 32, 33,
> > +		34, 35, 36, 37, 38, 39,	40, 41, 42, 43,
> > +		44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
> > +		54, 55, 56, 57, 58, 59, 60, 61, 62, 63, },
> > +	.oobfree = {
> > +		{.offset = 16, .length = 8, },
> 
> why not  offset = 2, length = 22
> Won't the badblock marker show if this is used as a BBT?
> Can JFFS2 not use the same bytes when not a BBT?
[Sandeep] We do not want any overlap between the ECC bytes and any of the above so just reserving as explained above and using the last 40 bytes.
> 
> > +		{.offset = 64, },
> 
> You can kill the above line.
> 
> > +	},
> > +};
> > +
> > +/* An ECC layout for using 4-bit ECC with large-page (4096bytes) flash,
> > + * storing ten ECC bytes plus the manufacturer's bad block marker byte,
> > + * and not overlapping the default BBT markers.
> > + */
> > +static struct nand_ecclayout hwecc4_4096 __initconst = {
> > +	.eccbytes = 80,
> > +	.eccpos = { /* 2 bytes at offset 0 hold the badblock markers */
> > +		/* 4 bytes at offset 8 hold BBT header */
> > +		/* 1 byte at offset 12 holds BBT version */
> > +		/* 8 bytes at offset 16 hold JFFS2 clean markers */
> > +		24, 25, 26, 27, 28, 29,	30, 31, 32, 33,
> > +		34, 35, 36, 37, 38, 39,	40, 41, 42, 43,
> > +		44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
> > +		54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
> > +		64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
> > +		74, 75, 76, 77, 78, 69,	80, 81, 82, 83,
> > +		84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
> > +		94, 95, 96, 97, 98, 99, 100, 101, 102, 103, },
> 
> Can these not be at the end??? i.e. 48-127
[Sandeep] I am just using the first available free bytes.
To answer your question, yes it can be at the end but I do not see any reason why it has to be at the end
Any reason why you insist that it should be at the end.

> 
> > +	.oobfree = {
> > +		{.offset = 16, .length = 8, },
> > +		{.offset = 104, },
> > +	},
> > +};
> >
> >  static int __init nand_davinci_probe(struct platform_device *pdev)
> >  {
> > @@ -689,15 +732,23 @@ static int __init nand_davinci_probe(struct
> platform_device *pdev)
> >  				info->mtd.oobsize - 16;
> >  			goto syndrome_done;
> >  		}
> > +		if (chunks == 4) {
> > +			info->ecclayout = hwecc4_2048;
> > +			info->ecclayout.oobfree[1].length = info->mtd.oobsize -
> > +				info->ecclayout.oobfree[1].offset;
> 
> This can be removed, it is already 0.
> 
> > +			info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST;
> > +			goto syndrome_done;
> > +		}
> > +		if (chunks == 8) {
> > +			info->ecclayout = hwecc4_4096;
> > +			info->ecclayout.oobfree[1].length = info->mtd.oobsize -
> > +				info->ecclayout.oobfree[1].offset;
> > +			info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST;
> > +			goto syndrome_done;
> > +		}
> >
> > -		/* For large page chips we'll be wanting to use a
> > -		 * not-yet-implemented mode that reads OOB data
> > -		 * before reading the body of the page, to avoid
> > -		 * the "infix OOB" model of NAND_ECC_HW_SYNDROME
> > -		 * (and preserve manufacturer badblock markings).
> > -		 */
> >  		dev_warn(&pdev->dev, "no 4-bit ECC support yet "
> > -				"for large page NAND\n");
> > +				"for >4K page NAND\n");
> >  		ret = -EIO;
> >  		goto err_scan;
> >
>
Troy Kisky - June 18, 2009, 9:53 p.m.
Paulraj, Sandeep wrote:
> 
>> -----Original Message-----
>> From: Troy Kisky [mailto:troy.kisky@boundarydevices.com]
>> Sent: Thursday, June 18, 2009 5:16 PM
>> To: Paulraj, Sandeep
>> Cc: davinci-linux-open-source@linux.davincidsp.com; linux-
>> mtd@lists.infradead.org; dwmw2@infradead.org; tglx@linutronix.de;
>> akpm@linux-foundation.org
>> Subject: Re: [PATCH v2 3/3] Add 4-bit ECC support for large page NAND
>> chips on Davinci
>>
>> s-paulraj@ti.com wrote:
>>> From: Sandeep Paulraj <s-paulraj@ti.com>
>>>
>>> The patch applies to linux-mtd GIT tree
>>>
>>> This patch adds 4-bit ECC support for large page NAND chips using the
>> new ECC
>>> mode NAND_ECC_HW_OOB_FIRST. The platform data from board-dm355-evm has
>> been
>>> adjusted to use this mode.
>>>
>>> The patches have been verified on DM355 device with 2K and 4K page size
>>> Micron devices using mtd-tests.
>>> Error correction upto 4-bits has also been verified using
>>> nandwrite/nanddump utilities.
>>>
>>> Reviewed-by: David Brownell <dbrownell@users.sourceforge.net>
>>> Signed-off-by: Sandeep Paulraj <s-paulraj@ti.com>
>>> Signed-off-by: Sneha Narnakaje <nsnehaprabha@ti.com>
>>> ---
>>>  drivers/mtd/nand/davinci_nand.c |   65
>> ++++++++++++++++++++++++++++++++++----
>>>  1 files changed, 58 insertions(+), 7 deletions(-)
>>>
>>> diff --git a/drivers/mtd/nand/davinci_nand.c
>> b/drivers/mtd/nand/davinci_nand.c
>>> index ba6940d..2ff0712 100644
>>> --- a/drivers/mtd/nand/davinci_nand.c
>>> +++ b/drivers/mtd/nand/davinci_nand.c
>>> @@ -500,6 +500,49 @@ static struct nand_ecclayout hwecc4_small
>> __initconst = {
>>>  	},
>>>  };
>>>
>>> +/* An ECC layout for using 4-bit ECC with large-page (2048bytes) flash,
>>> + * storing ten ECC bytes plus the manufacturer's bad block marker byte,
>>> + * and not overlapping the default BBT markers.
>>> + */
>>> +static struct nand_ecclayout hwecc4_2048 __initconst = {
>>> +	.eccbytes = 40,
>>> +	.eccpos = { /* 2 bytes at offset 0 hold the badblock markers */
>>> +		/* 4 bytes at offset 8 hold BBT header */
>>> +		/* 1 byte at offset 12 holds BBT version */
>>> +		/* 8 bytes at offset 16 hold JFFS2 clean markers */
>>> +		24, 25, 26, 27, 28, 29,	30, 31, 32, 33,
>>> +		34, 35, 36, 37, 38, 39,	40, 41, 42, 43,
>>> +		44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
>>> +		54, 55, 56, 57, 58, 59, 60, 61, 62, 63, },
>>> +	.oobfree = {
>>> +		{.offset = 16, .length = 8, },
>> why not  offset = 2, length = 22
>> Won't the badblock marker show if this is used as a BBT?
>> Can JFFS2 not use the same bytes when not a BBT?

> [Sandeep] We do not want any overlap between the ECC bytes and any of the above so just reserving as explained above and using the last 40 bytes.

You mean that you want no overlap between JFFS2 and BBT header. Can you explain this need
or point me to a document that will explain it? Thanks...



>>> +		{.offset = 64, },
>> You can kill the above line.
>>
>>> +	},
>>> +};
>>> +
>>> +/* An ECC layout for using 4-bit ECC with large-page (4096bytes) flash,
>>> + * storing ten ECC bytes plus the manufacturer's bad block marker byte,
>>> + * and not overlapping the default BBT markers.
>>> + */
>>> +static struct nand_ecclayout hwecc4_4096 __initconst = {
>>> +	.eccbytes = 80,
>>> +	.eccpos = { /* 2 bytes at offset 0 hold the badblock markers */
>>> +		/* 4 bytes at offset 8 hold BBT header */
>>> +		/* 1 byte at offset 12 holds BBT version */
>>> +		/* 8 bytes at offset 16 hold JFFS2 clean markers */
>>> +		24, 25, 26, 27, 28, 29,	30, 31, 32, 33,
>>> +		34, 35, 36, 37, 38, 39,	40, 41, 42, 43,
>>> +		44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
>>> +		54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
>>> +		64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
>>> +		74, 75, 76, 77, 78, 69,	80, 81, 82, 83,
>>> +		84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
>>> +		94, 95, 96, 97, 98, 99, 100, 101, 102, 103, },
>> Can these not be at the end??? i.e. 48-127
> [Sandeep] I am just using the first available free bytes.
> To answer your question, yes it can be at the end but I do not see any reason why it has to be at the end
> Any reason why you insist that it should be at the end.


Well, for one, it is nice to have oobfree contiguous. But mainly, I hope
to eventually use a default layout which will have the oob data at the
end when 0 holds the badblock marker.


> 
>>> +	.oobfree = {
>>> +		{.offset = 16, .length = 8, },
>>> +		{.offset = 104, },

Then, the above line can disappear if the ecc is at the end.

>>> +	},
>>> +};
>>>
>>>  static int __init nand_davinci_probe(struct platform_device *pdev)
>>>  {
>>> @@ -689,15 +732,23 @@ static int __init nand_davinci_probe(struct
>> platform_device *pdev)
>>>  				info->mtd.oobsize - 16;
>>>  			goto syndrome_done;
>>>  		}
>>> +		if (chunks == 4) {
>>> +			info->ecclayout = hwecc4_2048;
>>> +			info->ecclayout.oobfree[1].length = info->mtd.oobsize -
>>> +				info->ecclayout.oobfree[1].offset;
>> This can be removed, it is already 0.
>>
>>> +			info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST;
>>> +			goto syndrome_done;
>>> +		}
>>> +		if (chunks == 8) {
>>> +			info->ecclayout = hwecc4_4096;
>>> +			info->ecclayout.oobfree[1].length = info->mtd.oobsize -
>>> +				info->ecclayout.oobfree[1].offset;

Along with this line.

>>> +			info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST;
>>> +			goto syndrome_done;
>>> +		}
>>>
>>> -		/* For large page chips we'll be wanting to use a
>>> -		 * not-yet-implemented mode that reads OOB data
>>> -		 * before reading the body of the page, to avoid
>>> -		 * the "infix OOB" model of NAND_ECC_HW_SYNDROME
>>> -		 * (and preserve manufacturer badblock markings).
>>> -		 */
>>>  		dev_warn(&pdev->dev, "no 4-bit ECC support yet "
>>> -				"for large page NAND\n");
>>> +				"for >4K page NAND\n");
>>>  		ret = -EIO;
>>>  		goto err_scan;
>>>
> 
> 
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>
David Brownell - June 19, 2009, 2:07 a.m.
On Thursday 18 June 2009, Troy Kisky wrote:
> > To answer your question, yes it can be at the end but I do not
> > see any reason why it has to be at the end 
> > Any reason why you insist that it should be at the end.
> 
> Well, for one, it is nice to have oobfree contiguous. But mainly, I hope
> to eventually use a default layout which will have the oob data at the
> end when 0 holds the badblock marker.

Also, I thought the agreement from previous discussions was to
put it at the end, keeping a contiguous oobfree area ... which
is why the OpenOCD [1] DaVinci NAND driver puts it at the end in
the standard HWECC4 mode (not HWECC4_INFIX):

 - with 2K pages ... ECC in bytes 24..63 inclusive.
 - with 4K pages ... ECC in bytes 48..127 inclusive.

Now, the 0.2.0 release for that hasn't frozen yet, but the idea
was to have it match what Linux does.

So if the plans for Linux change, make sure I know so I can submit
a patch ... though I'd rather see the previous agreement kept.

- Dave

[1] http://openocd.berlios.de/doc/html/index.html

Patch

diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index ba6940d..2ff0712 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -500,6 +500,49 @@  static struct nand_ecclayout hwecc4_small __initconst = {
 	},
 };
 
+/* An ECC layout for using 4-bit ECC with large-page (2048bytes) flash,
+ * storing ten ECC bytes plus the manufacturer's bad block marker byte,
+ * and not overlapping the default BBT markers.
+ */
+static struct nand_ecclayout hwecc4_2048 __initconst = {
+	.eccbytes = 40,
+	.eccpos = { /* 2 bytes at offset 0 hold the badblock markers */
+		/* 4 bytes at offset 8 hold BBT header */
+		/* 1 byte at offset 12 holds BBT version */
+		/* 8 bytes at offset 16 hold JFFS2 clean markers */
+		24, 25, 26, 27, 28, 29,	30, 31, 32, 33,
+		34, 35, 36, 37, 38, 39,	40, 41, 42, 43,
+		44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+		54, 55, 56, 57, 58, 59, 60, 61, 62, 63, },
+	.oobfree = {
+		{.offset = 16, .length = 8, },
+		{.offset = 64, },
+	},
+};
+
+/* An ECC layout for using 4-bit ECC with large-page (4096bytes) flash,
+ * storing ten ECC bytes plus the manufacturer's bad block marker byte,
+ * and not overlapping the default BBT markers.
+ */
+static struct nand_ecclayout hwecc4_4096 __initconst = {
+	.eccbytes = 80,
+	.eccpos = { /* 2 bytes at offset 0 hold the badblock markers */
+		/* 4 bytes at offset 8 hold BBT header */
+		/* 1 byte at offset 12 holds BBT version */
+		/* 8 bytes at offset 16 hold JFFS2 clean markers */
+		24, 25, 26, 27, 28, 29,	30, 31, 32, 33,
+		34, 35, 36, 37, 38, 39,	40, 41, 42, 43,
+		44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+		54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+		64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+		74, 75, 76, 77, 78, 69,	80, 81, 82, 83,
+		84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+		94, 95, 96, 97, 98, 99, 100, 101, 102, 103, },
+	.oobfree = {
+		{.offset = 16, .length = 8, },
+		{.offset = 104, },
+	},
+};
 
 static int __init nand_davinci_probe(struct platform_device *pdev)
 {
@@ -689,15 +732,23 @@  static int __init nand_davinci_probe(struct platform_device *pdev)
 				info->mtd.oobsize - 16;
 			goto syndrome_done;
 		}
+		if (chunks == 4) {
+			info->ecclayout = hwecc4_2048;
+			info->ecclayout.oobfree[1].length = info->mtd.oobsize -
+				info->ecclayout.oobfree[1].offset;
+			info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST;
+			goto syndrome_done;
+		}
+		if (chunks == 8) {
+			info->ecclayout = hwecc4_4096;
+			info->ecclayout.oobfree[1].length = info->mtd.oobsize -
+				info->ecclayout.oobfree[1].offset;
+			info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST;
+			goto syndrome_done;
+		}
 
-		/* For large page chips we'll be wanting to use a
-		 * not-yet-implemented mode that reads OOB data
-		 * before reading the body of the page, to avoid
-		 * the "infix OOB" model of NAND_ECC_HW_SYNDROME
-		 * (and preserve manufacturer badblock markings).
-		 */
 		dev_warn(&pdev->dev, "no 4-bit ECC support yet "
-				"for large page NAND\n");
+				"for >4K page NAND\n");
 		ret = -EIO;
 		goto err_scan;