All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kyungmin Park <kmpark@infradead.org>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH] JFFS2 command support on OneNAND
Date: Wed, 27 Aug 2008 14:45:20 +0900	[thread overview]
Message-ID: <20080827054520.GA26061@july> (raw)

JFFS2 command support on OneNAND

Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>

diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c
index c031d80..c6920c9 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 /* !CONFIG_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,43 @@ 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,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 defice type %d\n", type);
 
 	return 1;
 }
@@ -1065,8 +1119,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 +1139,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 +1546,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;
 
@@ -2181,7 +2238,7 @@ U_BOOT_CMD(
 	"'mtdids' - linux kernel mtd device id <-> u-boot device id mapping\n\n"
 	"mtdids=<idmap>[,<idmap>,...]\n\n"
 	"<idmap>    := <dev-id>=<mtd-id>\n"
-	"<dev-id>   := 'nand'|'nor'<dev-num>\n"
+	"<dev-id>   := 'nand'|'nor'|'onenand'<dev-num>\n"
 	"<dev-num>  := mtd device number, 0...\n"
 	"<mtd-id>   := unique device tag used by linux kernel to find mtd device (mtd->name)\n\n"
 	"'mtdparts' - partition list\n\n"
diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c
index b5e7ab8..65ae819 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,6 +441,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;
 }
@@ -348,6 +459,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..551fd0c 100644
--- a/include/jffs2/load_kernel.h
+++ b/include/jffs2/load_kernel.h
@@ -28,9 +28,12 @@
 #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")
+#define MTD_DEV_TYPE_NOR	0x0001
+#define MTD_DEV_TYPE_NAND	0x0002
+#define MTD_DEV_TYPE_ONENAND	0x0004
+
+#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;

             reply	other threads:[~2008-08-27  5:45 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-08-27  5:45 Kyungmin Park [this message]
2008-09-06 20:50 ` [U-Boot] [PATCH] JFFS2 command support on OneNAND Wolfgang Denk

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080827054520.GA26061@july \
    --to=kmpark@infradead.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.