Issue in oamp nand driver with 32-bit reads in prefetch mode
Steve Sakoman
sakoman at gmail.com
Sat Jan 2 10:02:36 EST 2010
On Thu, Dec 31, 2009 at 4:20 AM, Vimal Singh <vimal.newwork at gmail.com> wrote:
> On Wed, Dec 30, 2009 at 3:17 AM, Steve Sakoman <sakoman at gmail.com> wrote:
>> On Tue, Dec 29, 2009 at 12:38 PM, Steve Sakoman <sakoman at gmail.com> wrote:
>>
>>> I can confirm that this issue exists on Overo too. Sadly, switching
>>> to 16 bit reads does not fix the issue for me. I'll start digging to
>>> see if I can find what's broken.
>>
>> I can also confirm that there are days when I am not even capable of
>> applying a patch properly :-(
>>
>> Switching to 16 bit read accesses does indeed fix the ECC issue on Overo too.
>>
>> Which still leaves us needing to find the root cause of the breakage . . .
>
> There is a bug in nand prefetch read routine, which comes into effect
> only if nand device is a 16-bit device (as we have in zoom boards).
> This bug is effective only with below combination of conditions:
> 1. nand deivce, in use, is a 16 bit device
> 2. nand driver supports 'subpage' read
> 3. SW ECC is in use
>
> This was not seen old kernel (ex: .23), because when, in early days,
> we tested this (nand prefetch read in LDP boards) there was no
> 'subpage read' support.
> Later when we had subpage read in (.27) kernel, we had hw ecc enabled
> always in our internal tree. So, we missed this bug.
>
> Here is a patch to fix this issue:
>
> diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
> index 1bb799f..75004fe 100644
> --- a/drivers/mtd/nand/omap2.c
> +++ b/drivers/mtd/nand/omap2.c
> @@ -295,11 +295,14 @@ static void omap_read_buf_pref(struct
> u32 *p = (u32 *)buf;
>
> /* take care of subpage reads */
> - for (; len % 4 != 0; ) {
> - *buf++ = __raw_readb(info->nand.IO_ADDR_R);
> - len--;
> + if (len % 4) {
> + if (info->nand.options & NAND_BUSWIDTH_16)
> + omap_read_buf16(mtd, buf, len % 4);
> + else
> + omap_read_buf8(mtd, buf, len % 4);
> + p = (u32 *) (buf + len % 4);
> + len -= len % 4;
> }
> - p = (u32 *) buf;
>
> /* configure and start prefetch transfer */
> ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0);
I tested this on Overo and can confirm that it fixes the issue.
Steve
More information about the linux-arm-kernel
mailing list