[U-Boot-Users] [PATCH] JFFS2 command support on OneNAND (take #2)

JFFS2 command support on OneNAND.
- Fix typo. - Fix nand_bbt_descr redefinition when NAND and OneNAND are enabled.
TODO: Use NAND command interface (e.g.: part_validate_*nand()).
Signed-off-by: Kyungmin Park kyungmin.park@samsung.com Signed-off-by: Fathi Boudra fabo@debian.org --- diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c index b4698be..43e33dd 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,6 +103,13 @@ #include <nand.h> #endif /* !CFG_NAND_LEGACY */ #endif + +#if defined(CONFIG_CMD_ONENAND) +#include <linux/mtd/mtd.h> +#include <linux/mtd/onenand.h> +#include <onenand_uboot.h> +#endif + /* enable/disable debugging messages */ #define DEBUG_JFFS #undef DEBUG_JFFS @@ -401,6 +408,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 +479,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 +800,15 @@ 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; + return 0; +#else + printf("support for OneNAND devices not present\n"); +#endif + } else + printf("Unknown device type %d\n", type);
return 1; } @@ -1065,8 +1118,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 +1138,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 +1545,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;
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c index 87344ab..04d4088 100644 --- a/drivers/mtd/onenand/onenand_bbt.c +++ b/drivers/mtd/onenand/onenand_bbt.c @@ -21,6 +21,7 @@ #include <linux/mtd/compat.h> #include <linux/mtd/mtd.h> #include <linux/mtd/onenand.h> +#include <linux/mtd/bbm.h> #include <malloc.h>
#include <asm/errno.h> diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c index 8a06777..7dc29c4 100644 --- a/fs/jffs2/jffs2_1pass.c +++ b/fs/jffs2/jffs2_1pass.c @@ -271,6 +271,107 @@ static void put_fl_mem_nand(void *buf) } #endif
+#if defined(CONFIG_CMD_ONENAND) + +#include <linux/mtd/mtd.h> +#include <linux/mtd/onenand.h> +#include <onenand_uboot.h> + +#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; +static u32 onenand_cache_off = (u32)-1; + +static int read_onenand_cached(u32 off, u32 size, u_char *buf) +{ + 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) /* @@ -316,6 +417,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; } @@ -335,19 +441,31 @@ 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; }
static inline void put_fl_mem(void *buf) { -#if defined(CONFIG_JFFS2_NAND) && \ - defined(CONFIG_CMD_NAND) +#if (defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND)) || \ + defined(CONFIG_CMD_ONENAND) struct mtdids *id = current_part->dev->id; +#endif
+#if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND) if (id->type == MTD_DEV_TYPE_NAND) return put_fl_mem_nand(buf); #endif + +#if defined(CONFIG_CMD_ONENAND) + 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..37871de 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..019d2b1 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -14,10 +14,10 @@
#include <linux/mtd/onenand_regs.h>
-/* Note: The header order is impoertant */ +/* Note: The header order is important */ #include <onenand_uboot.h>
-#include <linux/mtd/bbm.h> +#include <linux/mtd/compat.h>
#define MAX_BUFFERRAM 2 #define MAX_ONENAND_PAGESIZE (2048 + 64) diff --git a/include/onenand_uboot.h b/include/onenand_uboot.h index 4449f98..24ace2a 100644 --- a/include/onenand_uboot.h +++ b/include/onenand_uboot.h @@ -27,6 +27,8 @@ typedef int wait_queue_head_t; struct mtd_info; struct erase_info;
+extern struct mtd_info onenand_mtd; + /* Functions */ extern void onenand_init(void); extern int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,

In message 200807300920.41289.fabo@debian.org you wrote:
JFFS2 command support on OneNAND.
- Fix typo.
- Fix nand_bbt_descr redefinition when NAND and OneNAND are enabled.
TODO: Use NAND command interface (e.g.: part_validate_*nand()).
Signed-off-by: Kyungmin Park kyungmin.park@samsung.com Signed-off-by: Fathi Boudra fabo@debian.org
diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c index b4698be..43e33dd 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,6 +103,13 @@ #include <nand.h> #endif /* !CFG_NAND_LEGACY */ #endif
+#if defined(CONFIG_CMD_ONENAND) +#include <linux/mtd/mtd.h> +#include <linux/mtd/onenand.h> +#include <onenand_uboot.h> +#endif
/* enable/disable debugging messages */ #define DEBUG_JFFS #undef DEBUG_JFFS @@ -401,6 +408,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)
The whole function should only be defined...
@@ -436,6 +479,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);
... and called when CONFIG_CMD_ONENAND is set.
@@ -755,7 +800,15 @@ 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;
return 0;
+#else
printf("support for OneNAND devices not present\n");
+#endif
- } else
printf("Unknown device type %d\n", type);
Same here - if CONFIG_CMD_ONENAND is not set, no new code should be added.
@@ -1065,8 +1118,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 +1138,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;
Ditto here.
+static int read_onenand_cached(u32 off, u32 size, u_char *buf) +{
- 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",
Lines too long.
...
printf("read_onenand_cached: error reading nand off %#x size %d bytes\n",
onenand_cache_off, ONENAND_CACHE_SIZE);
Ditto.
diff --git a/include/jffs2/load_kernel.h b/include/jffs2/load_kernel.h index 882a80e..37871de 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,
+};
Please don't. Leave as it was.
Best regards,
Wolfgang Denk

On Wed, Jul 30, 2008 at 09:20:39AM +0200, Fathi BOUDRA wrote:
TODO: Use NAND command interface (e.g.: part_validate_*nand()).
Do you mean merging the NAND and OneNAND versions of the jffs2 code, through the (mostly already existing) function pointer interface?
I'd really like to see that done before merging, unless there's a consensus from others that it can't wait.
-Scott

JFFS2 command support on OneNAND.
- Fix typo. - Fix nand_bbt_descr redefinition when NAND and OneNAND are enabled.
Since last comments: - Add some CONFIG_CMD_ONENAND to prevent adding new code. - Fix line too long. - Revert mtd device types definition.
TODO: Use NAND command interface (e.g.: part_validate_*nand()).
Signed-off-by: Kyungmin Park kyungmin.park@samsung.com Signed-off-by: Fathi Boudra fabo@debian.org --- diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c index b4698be..16ca8f7 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,6 +103,13 @@ #include <nand.h> #endif /* !CFG_NAND_LEGACY */ #endif + +#if defined(CONFIG_CMD_ONENAND) +#include <linux/mtd/mtd.h> +#include <linux/mtd/onenand.h> +#include <onenand_uboot.h> +#endif + /* enable/disable debugging messages */ #define DEBUG_JFFS #undef DEBUG_JFFS @@ -401,6 +408,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 +479,10 @@ 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); +#if defined(CONFIG_CMD_ONENAND) + else if (id->type == MTD_DEV_TYPE_ONENAND) + return part_validate_onenand(id, part); +#endif else DEBUGF("part_validate: invalid dev type\n");
@@ -755,7 +802,15 @@ 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; + return 0; +#else + printf("support for OneNAND devices not present\n"); +#endif + } else + printf("Unknown device 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,11 @@ 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; +#if defined(CONFIG_CMD_ONENAND) + } else if (strncmp(p, "onenand", 7) == 0) { + *dev_type = MTD_DEV_TYPE_ONENAND; + p += 7; +#endif } else { printf("incorrect device type in %s\n", id); return 1; @@ -1489,7 +1549,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;
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c index 87344ab..04d4088 100644 --- a/drivers/mtd/onenand/onenand_bbt.c +++ b/drivers/mtd/onenand/onenand_bbt.c @@ -21,6 +21,7 @@ #include <linux/mtd/compat.h> #include <linux/mtd/mtd.h> #include <linux/mtd/onenand.h> +#include <linux/mtd/bbm.h> #include <malloc.h>
#include <asm/errno.h> diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c index 8a06777..5539ca9 100644 --- a/fs/jffs2/jffs2_1pass.c +++ b/fs/jffs2/jffs2_1pass.c @@ -271,6 +271,107 @@ static void put_fl_mem_nand(void *buf) } #endif
+#if defined(CONFIG_CMD_ONENAND) + +#include <linux/mtd/mtd.h> +#include <linux/mtd/onenand.h> +#include <onenand_uboot.h> + +#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; +static u32 onenand_cache_off = (u32)-1; + +static int read_onenand_cached(u32 off, u32 size, u_char *buf) +{ + 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("%s: can't alloc cache size %d bytes\n", + __FUNCTION__, 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("%s: error reading nand off %#x size %d bytes\n", + __FUNCTION__, 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("%s: can't alloc %d bytes\n", __FUNCTION__, 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) /* @@ -316,6 +417,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; } @@ -335,19 +441,31 @@ 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; }
static inline void put_fl_mem(void *buf) { -#if defined(CONFIG_JFFS2_NAND) && \ - defined(CONFIG_CMD_NAND) +#if (defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND)) || \ + defined(CONFIG_CMD_ONENAND) struct mtdids *id = current_part->dev->id; +#endif
+#if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND) if (id->type == MTD_DEV_TYPE_NAND) return put_fl_mem_nand(buf); #endif + +#if defined(CONFIG_CMD_ONENAND) + 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..8e7c515 100644 --- a/include/jffs2/load_kernel.h +++ b/include/jffs2/load_kernel.h @@ -30,7 +30,9 @@ /* 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") +#define MTD_DEV_TYPE_ONENAND 0x0003 +#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..019d2b1 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -14,10 +14,10 @@
#include <linux/mtd/onenand_regs.h>
-/* Note: The header order is impoertant */ +/* Note: The header order is important */ #include <onenand_uboot.h>
-#include <linux/mtd/bbm.h> +#include <linux/mtd/compat.h>
#define MAX_BUFFERRAM 2 #define MAX_ONENAND_PAGESIZE (2048 + 64) diff --git a/include/onenand_uboot.h b/include/onenand_uboot.h index 4449f98..24ace2a 100644 --- a/include/onenand_uboot.h +++ b/include/onenand_uboot.h @@ -27,6 +27,8 @@ typedef int wait_queue_head_t; struct mtd_info; struct erase_info;
+extern struct mtd_info onenand_mtd; + /* Functions */ extern void onenand_init(void); extern int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,

Dear Fathi BOUDRA,
In message 200808051330.15387.fabo@debian.org you wrote:
JFFS2 command support on OneNAND.
- Fix typo.
- Fix nand_bbt_descr redefinition when NAND and OneNAND are enabled.
Since last comments:
- Add some CONFIG_CMD_ONENAND to prevent adding new code.
- Fix line too long.
- Revert mtd device types definition.
TODO: Use NAND command interface (e.g.: part_validate_*nand()).
Signed-off-by: Kyungmin Park kyungmin.park@samsung.com Signed-off-by: Fathi Boudra fabo@debian.org
diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c index b4698be..16ca8f7 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)
^^^^^^^^^^^^^^^^^ Line wrapped.
@@ -103,6 +103,13 @@ #include <nand.h> #endif /* !CFG_NAND_LEGACY */ #endif
+#if defined(CONFIG_CMD_ONENAND) +#include <linux/mtd/mtd.h> +#include <linux/mtd/onenand.h> +#include <onenand_uboot.h> +#endif
/* enable/disable debugging messages */ #define DEBUG_JFFS #undef DEBUG_JFFS @@ -401,6 +408,42 @@ static int part_validate_nand(struct mtdids *id, struct part_info *part)
^^^^^^^^^^^^^^^^^^^^^^^
Line wrapped.
Sorry, your patch was line-wrapped by your mailer. Please fix your mailer configuration and resubmit.
Best regards,
Wolfgang Denk
participants (3)
-
Fathi BOUDRA
-
Scott Wood
-
Wolfgang Denk