
by Align with word(16-bit) size as done in Linux
in - onenand_read_bufferram - onenand_sync_read_bufferram - onenand_write_bufferram
Signed-off-by: Wolfgang Denk wd@denx.de Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD plagnioj@jcrosoft.com Cc: Kyungmin Park kyungmin.park@samsung.com
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 174384e..d888e48 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -20,19 +20,6 @@ #include <asm/io.h> #include <asm/errno.h>
-/* It should access 16-bit instead of 8-bit */ -static inline void *memcpy(void *dst, const void *src, unsigned int len) -{ - void *ret = dst; - short *d = dst; - const short *s = src; - - len >>= 1; - while (len-- > 0) - *d++ = *s++; - return ret; -} - static const unsigned char ffchars[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16 */ @@ -358,6 +345,17 @@ static int onenand_read_bufferram(struct mtd_info *mtd, int area, bufferram = this->base + area; 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; @@ -385,6 +383,17 @@ static int onenand_sync_read_bufferram(struct mtd_info *mtd, int area,
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); @@ -412,6 +421,22 @@ static int onenand_write_bufferram(struct mtd_info *mtd, int area, bufferram = this->base + area; 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; diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index 4b0c2df..e959de4 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -119,6 +119,9 @@ struct onenand_chip { #define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1) #define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1)
+/* Check byte access in OneNAND */ +#define ONENAND_CHECK_BYTE_ACCESS(addr) (addr & 0x1) + /* * Options bits */