[U-Boot-Users] u-boot and OneNAND

Hello If I read code correctly u-boot have OneNAND driver. But when I check JFFS2 in u-boot it seems that JFFS2 can not work on OneNAND.
What is proposed way of working with OneNAND and u-boot? Do we have some support for bad block management?
Thanks in advace Mile

Hi,
On Wed, Jul 2, 2008 at 8:55 PM, Mile Davidovic md4uboot@gmail.com wrote:
Hello If I read code correctly u-boot have OneNAND driver. But when I check JFFS2 in u-boot it seems that JFFS2 can not work on OneNAND.
Yes, it's not yet implemented.
What is proposed way of working with OneNAND and u-boot? Do we have some support for bad block management?
Now there's no proper method on OneNAND in open source. but some time later, the UBI is candidate. If UBI is introduced to u-boot.
Thank you, Kyungmin Park

On Thu, Jul 3, 2008 at 1:58 PM, Kyungmin Park kmpark@infradead.org wrote:
Hi,
On Wed, Jul 2, 2008 at 8:55 PM, Mile Davidovic md4uboot@gmail.com wrote:
Hello If I read code correctly u-boot have OneNAND driver. But when I check JFFS2 in u-boot it seems that JFFS2 can not work on OneNAND.
Yes, it's not yet implemented.
Feel free to use this patch. the mtdparts and fsload is working, but I'm not suer it's working correctly.
Thank you, Kyungmin Park --- diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c index 1b67e73..51c742c 100644 --- a/common/cmd_jffs2.c +++ b/common/cmd_jffs2.c @@ -51,7 +51,7 @@ * mtdids=<idmap>[,<idmap>,...] * * <idmap> := <dev-id>=<mtd-id> - * <dev-id> := 'nand'|'nor'<dev-num> + * <dev-id> := 'nand'|'nor'|'onenand'<dev-num> * <dev-num> := mtd device number, 0... * <mtd-id> := unique device tag used by linux kernel to find mtd device (mtd->name) * @@ -103,9 +103,17 @@ #include <nand.h> #endif /* !CFG_NAND_LEGACY */ #endif + +#if defined(CONFIG_CMD_ONENAND) +#include <linux/mtd/mtd.h> +#include <linux/mtd/onenand.h> + +extern struct mtd_info onenand_mtd; +#endif + /* enable/disable debugging messages */ #define DEBUG_JFFS -#undef DEBUG_JFFS +//#undef DEBUG_JFFS
#ifdef DEBUG_JFFS # define DEBUGF(fmt, args...) printf(fmt ,##args) @@ -401,6 +409,42 @@ static int part_validate_nand(struct mtdids *id, struct part_info *part) }
/** + * Performs sanity check for supplied OneNAND flash partition. + * Table of existing OneNAND flash devices is searched and partition device + * is located. Alignment with the granularity of nand erasesize is verified. + * + * @param id of the parent device + * @param part partition to validate + * @return 0 if partition is valid, 1 otherwise + */ +static int part_validate_onenand(struct mtdids *id, struct part_info *part) +{ +#if defined(CONFIG_CMD_ONENAND) + /* info for OneNAND chips */ + struct mtd_info *mtd; + + mtd = &onenand_mtd; + + if ((unsigned long)(part->offset) % mtd->erasesize) { + printf("%s%d: partition (%s) start offset alignment incorrect\n", + MTD_DEV_TYPE(id->type), id->num, part->name); + return 1; + } + + if (part->size % mtd->erasesize) { + printf("%s%d: partition (%s) size alignment incorrect\n", + MTD_DEV_TYPE(id->type), id->num, part->name); + return 1; + } + + return 0; +#else + return 1; +#endif +} + + +/** * Performs sanity check for supplied partition. Offset and size are verified * to be within valid range. Partition type is checked and either * parts_validate_nor() or parts_validate_nand() is called with the argument @@ -436,6 +480,8 @@ static int part_validate(struct mtdids *id, struct part_info *part) return part_validate_nand(id, part); else if (id->type == MTD_DEV_TYPE_NOR) return part_validate_nor(id, part); + else if (id->type == MTD_DEV_TYPE_ONENAND) + return part_validate_onenand(id, part); else DEBUGF("part_validate: invalid dev type\n");
@@ -755,7 +801,16 @@ static int device_validate(u8 type, u8 num, u32 *size) #else printf("support for NAND devices not present\n"); #endif - } + } else if (type == MTD_DEV_TYPE_ONENAND) { +#if defined(CONFIG_CMD_ONENAND) + *size = onenand_mtd.size; + printk("%s[%d] size %d\n", __func__, __LINE__, *size); + return 0; +#else + printf("support for OneNAND devices not present\n"); +#endif + } else + printf("Unknown defice type %d\n", type);
return 1; } @@ -1065,8 +1120,8 @@ static struct mtdids* id_find_by_mtd_id(const char *mtd_id, unsigned int mtd_id_ #endif /* #ifdef CONFIG_JFFS2_CMDLINE */
/** - * Parse device id string <dev-id> := 'nand'|'nor'<dev-num>, return device - * type and number. + * Parse device id string <dev-id> := 'nand'|'nor'|'onenand'<dev-num>, + * return device type and number. * * @param id string describing device id * @param ret_id output pointer to next char after parse completes (output) @@ -1085,6 +1140,9 @@ int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num) } else if (strncmp(p, "nor", 3) == 0) { *dev_type = MTD_DEV_TYPE_NOR; p += 3; + } else if (strncmp(p, "onenand", 7) == 0) { + *dev_type = MTD_DEV_TYPE_ONENAND; + p += 7; } else { printf("incorrect device type in %s\n", id); return 1; @@ -1489,7 +1547,7 @@ static int parse_mtdids(const char *const ids) while(p && (*p != '\0')) {
ret = 1; - /* parse 'nor'|'nand'<dev-num> */ + /* parse 'nor'|'nand'|'onenand'<dev-num> */ if (id_parse(p, &p, &type, &num) != 0) break;
@@ -1503,6 +1561,7 @@ static int parse_mtdids(const char *const ids) if (device_validate(type, num, &size) != 0) return 1;
+ printf("%s[%d]\n", __func__, __LINE__); /* locate <mtd-id> */ mtd_id = p; if ((p = strchr(mtd_id, ',')) != NULL) { @@ -1516,6 +1575,7 @@ static int parse_mtdids(const char *const ids) break; }
+ printf("%s[%d]\n", __func__, __LINE__); /* check if this id is already on the list */ int double_entry = 0; list_for_each(entry, &mtdids) { @@ -1531,11 +1591,13 @@ static int parse_mtdids(const char *const ids) break; }
+ printf("%s[%d]\n", __func__, __LINE__); /* allocate mtdids structure */ if (!(id = (struct mtdids *)malloc(sizeof(struct mtdids) + mtd_id_len))) { printf("out of memory\n"); break; } + printf("%s[%d]\n", __func__, __LINE__); memset(id, 0, sizeof(struct mtdids) + mtd_id_len); id->num = num; id->type = type; diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c index 7e27ee1..05397ef 100644 --- a/fs/jffs2/jffs2_1pass.c +++ b/fs/jffs2/jffs2_1pass.c @@ -270,6 +270,109 @@ static void put_fl_mem_nand(void *buf) } #endif
+#if defined(CONFIG_CMD_ONENAND) + +#include <linux/mtd/mtd.h> +#include <linux/mtd/onenand.h> + +extern struct mtd_info onenand_mtd; + +#define ONENAND_PAGE_SIZE 2048 +#define ONENAND_PAGE_SHIFT 11 +#define ONENAND_PAGE_MASK (~(ONENAND_PAGE_SIZE-1)) + +#ifndef ONENAND_CACHE_PAGES +#define ONENAND_CACHE_PAGES 4 +#endif +#define ONENAND_CACHE_SIZE (ONENAND_CACHE_PAGES*ONENAND_PAGE_SIZE) + +static u8* onenand_cache = NULL; +static u32 onenand_cache_off = (u32)-1; + +static int read_onenand_cached(u32 off, u32 size, u_char *buf) +{ + struct mtdids *id = current_part->dev->id; + u32 bytes_read = 0; + size_t retlen; + int cpy_bytes; + + while (bytes_read < size) { + if ((off + bytes_read < onenand_cache_off) || + (off + bytes_read >= onenand_cache_off+ONENAND_CACHE_SIZE)) { + onenand_cache_off = (off + bytes_read) & ONENAND_PAGE_MASK; + if (!onenand_cache) { + /* This memory never gets freed but 'cause + it's a bootloader, nobody cares */ + onenand_cache = malloc(ONENAND_CACHE_SIZE); + if (!onenand_cache) { + printf("read_onenand_cached: can't alloc cache size %d bytes\n", + ONENAND_CACHE_SIZE); + return -1; + } + } + + retlen = ONENAND_CACHE_SIZE; + if (onenand_read(&onenand_mtd, onenand_cache_off, retlen, + &retlen, onenand_cache) != 0 || + retlen != ONENAND_CACHE_SIZE) { + printf("read_onenand_cached: error reading nand off %#x size %d bytes\n", + onenand_cache_off, ONENAND_CACHE_SIZE); + return -1; + } + } + cpy_bytes = onenand_cache_off + ONENAND_CACHE_SIZE - (off + bytes_read); + if (cpy_bytes > size - bytes_read) + cpy_bytes = size - bytes_read; + memcpy(buf + bytes_read, + onenand_cache + off + bytes_read - onenand_cache_off, + cpy_bytes); + bytes_read += cpy_bytes; + } + return bytes_read; +} + +static void *get_fl_mem_onenand(u32 off, u32 size, void *ext_buf) +{ + u_char *buf = ext_buf ? (u_char*)ext_buf : (u_char*)malloc(size); + + if (NULL == buf) { + printf("get_fl_mem_onenand: can't alloc %d bytes\n", size); + return NULL; + } + if (read_onenand_cached(off, size, buf) < 0) { + if (!ext_buf) + free(buf); + return NULL; + } + + return buf; +} + +static void *get_node_mem_onenand(u32 off) +{ + struct jffs2_unknown_node node; + void *ret = NULL; + + if (NULL == get_fl_mem_onenand(off, sizeof(node), &node)) + return NULL; + + ret = get_fl_mem_onenand(off, node.magic == + JFFS2_MAGIC_BITMASK ? node.totlen : sizeof(node), + NULL); + if (!ret) { + printf("off = %#x magic %#x type %#x node.totlen = %d\n", + off, node.magic, node.nodetype, node.totlen); + } + return ret; +} + + +static void put_fl_mem_onenand(void *buf) +{ + free(buf); +} +#endif +
#if defined(CONFIG_CMD_FLASH) /* @@ -315,6 +418,11 @@ static inline void *get_fl_mem(u32 off, u32 size, void *ext_buf) return get_fl_mem_nand(off, size, ext_buf); #endif
+#if defined(CONFIG_CMD_ONENAND) + if (id->type == MTD_DEV_TYPE_ONENAND) + return get_fl_mem_onenand(off, size, ext_buf); +#endif + printf("get_fl_mem: unknown device type, using raw offset!\n"); return (void*)off; } @@ -334,6 +442,11 @@ static inline void *get_node_mem(u32 off) return get_node_mem_nand(off); #endif
+#if defined(CONFIG_CMD_ONENAND) + if (id->type == MTD_DEV_TYPE_ONENAND) + return get_node_mem_onenand(off); +#endif + printf("get_node_mem: unknown device type, using raw offset!\n"); return (void*)off; } @@ -347,6 +460,13 @@ static inline void put_fl_mem(void *buf) if (id->type == MTD_DEV_TYPE_NAND) return put_fl_mem_nand(buf); #endif + +#if defined(CONFIG_CMD_ONENAND) + struct mtdids *id = current_part->dev->id; + + if (id->type == MTD_DEV_TYPE_ONENAND) + return put_fl_mem_onenand(buf); +#endif }
/* Compression names */ diff --git a/include/jffs2/load_kernel.h b/include/jffs2/load_kernel.h index 882a80e..b46eca3 100644 --- a/include/jffs2/load_kernel.h +++ b/include/jffs2/load_kernel.h @@ -28,9 +28,14 @@ #include <linux/list.h>
/* mtd device types */ -#define MTD_DEV_TYPE_NOR 0x0001 -#define MTD_DEV_TYPE_NAND 0x0002 -#define MTD_DEV_TYPE(type) ((type == MTD_DEV_TYPE_NAND) ? "nand" : "nor") +enum { + MTD_DEV_TYPE_NOR, + MTD_DEV_TYPE_NAND, + MTD_DEV_TYPE_ONENAND, +}; + +#define MTD_DEV_TYPE(type) ((type == MTD_DEV_TYPE_NAND) ? "nand" : \ + (type == MTD_DEV_TYPE_ONENAND) ? "onenand" : "nor")
struct mtd_device { struct list_head link; diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index 4b0c2df..5bc905e 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -17,6 +17,7 @@ /* Note: The header order is impoertant */ #include <onenand_uboot.h>
+#include <linux/mtd/compat.h> #include <linux/mtd/bbm.h>
#define MAX_BUFFERRAM 2

Kyungmin Park wrote:
On Thu, Jul 3, 2008 at 1:58 PM, Kyungmin Park kmpark@infradead.org wrote:
Hi,
On Wed, Jul 2, 2008 at 8:55 PM, Mile Davidovic md4uboot@gmail.com wrote:
Hello If I read code correctly u-boot have OneNAND driver. But when I check JFFS2 in u-boot it seems that JFFS2 can not work on OneNAND.
Yes, it's not yet implemented.
Feel free to use this patch. the mtdparts and fsload is working, but I'm not suer it's working correctly.
Thank you, Kyungmin Park
diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c index 1b67e73..51c742c 100644 --- a/common/cmd_jffs2.c +++ b/common/cmd_jffs2.c
I don't know what the rest of the list thinks, but I would like to see a "Signed-off-by" line (and/or a note on where the code came from - e.g. linux) on all patches whether they are preliminary or not. I would hate to get into a "where did this code come from" quandary over a code that came from, was influenced by, or simply looked like a patch that was posted without proper traceability.
Thanks, gvb

On Fri, Jul 4, 2008 at 9:57 AM, Jerry Van Baren gvb.uboot@gmail.com wrote:
Kyungmin Park wrote:
On Thu, Jul 3, 2008 at 1:58 PM, Kyungmin Park kmpark@infradead.org wrote:
Hi,
On Wed, Jul 2, 2008 at 8:55 PM, Mile Davidovic md4uboot@gmail.com wrote:
Hello If I read code correctly u-boot have OneNAND driver. But when I check JFFS2 in u-boot it seems that JFFS2 can not work on OneNAND.
Yes, it's not yet implemented.
Feel free to use this patch. the mtdparts and fsload is working, but I'm not suer it's working correctly.
Thank you, Kyungmin Park
diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c index 1b67e73..51c742c 100644 --- a/common/cmd_jffs2.c +++ b/common/cmd_jffs2.c
I don't know what the rest of the list thinks, but I would like to see a "Signed-off-by" line (and/or a note on where the code came from - e.g. linux) on all patches whether they are preliminary or not. I would hate to get into a "where did this code come from" quandary over a code that came from, was influenced by, or simply looked like a patch that was posted without proper traceability.
Since it's not fully tested and maybe have a bug. If some users are having test and get ack I will repost this one with sign-off. And it's code almost same as NAND except some parts. It's early hacking for supporting jffs2 comand on OneNAND.
Thank you, Kyungmin Park

Hello, Thanks a lot for patch.
With this patch we will have possibility to load file from JFFS2 into memory and execute this which is fine.
But what is proper way for storing JFFS2 image in OneNAND? If I can create JFFS2 partiion in u-boot, how I can store files in? Do we need to have Linux up and runing?
Thanks in advance Mile
On Fri, Jul 4, 2008 at 5:33 AM, Kyungmin Park kmpark@infradead.org wrote:
On Fri, Jul 4, 2008 at 9:57 AM, Jerry Van Baren gvb.uboot@gmail.com wrote:
Kyungmin Park wrote:
On Thu, Jul 3, 2008 at 1:58 PM, Kyungmin Park kmpark@infradead.org wrote:
Hi,
On Wed, Jul 2, 2008 at 8:55 PM, Mile Davidovic md4uboot@gmail.com wrote:
Hello If I read code correctly u-boot have OneNAND driver. But when I check JFFS2 in u-boot it seems that JFFS2 can not work on OneNAND.
Yes, it's not yet implemented.
Feel free to use this patch. the mtdparts and fsload is working, but I'm not suer it's working correctly.
Thank you, Kyungmin Park
diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c index 1b67e73..51c742c 100644 --- a/common/cmd_jffs2.c +++ b/common/cmd_jffs2.c
I don't know what the rest of the list thinks, but I would like to see a "Signed-off-by" line (and/or a note on where the code came from - e.g. linux) on all patches whether they are preliminary or not. I would hate
to
get into a "where did this code come from" quandary over a code that came from, was influenced by, or simply looked like a patch that was posted without proper traceability.
Since it's not fully tested and maybe have a bug. If some users are having test and get ack I will repost this one with sign-off. And it's code almost same as NAND except some parts. It's early hacking for supporting jffs2 comand on OneNAND.
Thank you, Kyungmin Park
participants (3)
-
Jerry Van Baren
-
Kyungmin Park
-
Mile Davidovic