RE: EBH with OneNAND doesn't work

Kyungmin Park
2005-12-21T07:25:10Z

Hi

As you know the OneNAND has only 16bit bandwidth
When you access OneNAND with 8bit bandwidth, OneNAND can't work correctly

In the previous JFFS2 w/o EBH, there's no problem with OOB.
But JFFS2 w/ EBH is different. we have to handle byte access in OneNAND

The previous patch is handle byte without optimized memory copy
The following patch handles only byte offset.

Please apply the following patch and test again

Thank you
Kyungmin Park

p.s, Does it need to check byte access in 'offset', I never see that case.

Index: drivers/mtd/onenand/onenand_base.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/onenand/onenand_base.c,v
retrieving revision 1.12
diff -u -p -r1.12 onenand_base.c
--- drivers/mtd/onenand/onenand_base.c 21 Dec 2005 04:59:19 -0000 1.12
+++ drivers/mtd/onenand/onenand_base.c 21 Dec 2005 07:05:16 -0000
@@ -373,6 +373,17 @@ static int onenand_read_bufferram(struct

bufferram += onenand_bufferram_offset(mtd, area);

+ if (ONENAND_CHECK_BYTE_ACCESS(count)) {
+ unsigned short word;
+
+ /* Align with word(16-bit) size */
+ count--;
+
+ /* Read word and save byte */
+ word = this->read_word(bufferram + offset + count);
+ buffer[count] = (word & 0xff);
+ }
+
memcpy(buffer, bufferram + offset, count);

return 0;
@@ -400,6 +411,17 @@ static int onenand_sync_read_bufferram(s

this->mmcontrol(mtd, ONENAND_SYS_CFG1_SYNC_READ);

+ if (ONENAND_CHECK_BYTE_ACCESS(count)) {
+ unsigned short word;
+
+ /* Align with word(16-bit) size */
+ count--;
+
+ /* Read word and save byte */
+ word = this->read_word(bufferram + offset + count);
+ buffer[count] = (word & 0xff);
+ }
+
memcpy(buffer, bufferram + offset, count);

this->mmcontrol(mtd, 0);
@@ -427,6 +449,22 @@ static int onenand_write_bufferram(struc

bufferram += onenand_bufferram_offset(mtd, area);

+ if (ONENAND_CHECK_BYTE_ACCESS(count)) {
+ unsigned short word;
+ int byte_offset;
+
+ /* Align with word(16-bit) size */
+ count--;
+
+ /* Calculate byte access offset */
+ byte_offset = offset + count;
+
+ /* Read word and save byte */
+ word = this->read_word(bufferram + byte_offset);
+ word = (word & ~0xff) | buffer[count];
+ this->write_word(word, bufferram + byte_offset);
+ }
+
memcpy(bufferram + offset, buffer, count);

return 0;
Index: include/linux/mtd/onenand.h
===================================================================
RCS file: /home/cvs/mtd/include/linux/mtd/onenand.h,v
retrieving revision 1.10
diff -u -p -r1.10 onenand.h
--- include/linux/mtd/onenand.h 21 Dec 2005 02:55:41 -0000 1.10
+++ include/linux/mtd/onenand.h 21 Dec 2005 07:05:16 -0000
@@ -130,6 +130,9 @@ struct onenand_chip {
#define ONENAND_SET_SYS_CFG1(v, this) \
(this->write_word(v, this->base + ONENAND_REG_SYS_CFG1))

+/* Check byte access in OneNAND */
+#define ONENAND_CHECK_BYTE_ACCESS(addr) (addr & 0x1)
+
/*
* Options bits
*/

> >
> > diff -uN ..
> > --- linux/drivers/mtd/onenand/onenand_base.c 2005-12-19
> > 10:46:37.000000000 +0100
> > +++ linux/drivers/mtd/onenand/onenand_base.c 2005-12-16
> > 02:02:11.000000000 +0100
> > @@ -33,8 +33,8 @@
> > 56, 57, 58, 59, 60,
> > },
> > .oobfree = {
> > + {14, 2}, { 2, 3}, {18, 3}, {30, 2},
> > + {34, 3}, {46, 2}, {50, 3}, {62, 2} }
> > - {2, 3}, {14, 2}, {18, 3}, {30, 2},
> > - {24, 3}, {46, 2}, {40, 3}, {62, 2} }
> > };
> >
> > /**
> > @@ -367,33 +367,12 @@
> > {
> > struct onenand_chip *this = mtd->priv;
> > void __iomem *bufferram;
> > + unsigned short *p;
> > + int i;
> >
> > bufferram = this->base + area;
> >
> > bufferram += onenand_bufferram_offset(mtd, area);
> >
> > + p = (unsigned short *)buffer;
> > + for (i=0; i< (count >> 1 ); i++)
> > + p[i] = onenand_readw(bufferram + offset + 2*i);
> > + if(count%2)
> > + buffer[count-1] = (unsigned char) (0xff &
> > onenand_readw(bufferram + offset + count - 1));
> > +
> > - memcpy(buffer, bufferram + offset, count);
> >
> > return 0;
> > }
> > @@ -442,40 +421,12 @@
> > {
> > struct onenand_chip *this = mtd->priv;
> > void __iomem *bufferram;
> > + unsigned short *p;
> > + int i;
> >
> > bufferram = this->base + area;
> >
> > bufferram += onenand_bufferram_offset(mtd, area);
> >
> > + p = (unsigned short *)buffer;
> > + for (i=0; i< (count >> 1 ); i++){
> > + onenand_writew(*p, bufferram + offset + 2 * i);
> > + p++;
> > + }
> > + if(count%2)
> > + printk("FATAL ERROR:
> onenand_write_bufferram count is
> > odd : %x\n", count);
> > + if(offset%2)
> > + printk("FATAL ERROR:
> onenand_write_bufferram offset is
> > odd : %x\n", offset);
> > +
> > - memcpy(bufferram + offset, buffer, count);
> >
> > return 0;
> > }
> >

T