[U-Boot-Users] [PATCH 3/3] OneNAND support (take #2)

Kyungmin Park kmpark at infradead.org
Mon Sep 10 10:15:14 CEST 2007


[PATCH 3/3] OneNAND support (take #2)

OneNAND support at U-Boot

Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
---
diff --git a/Makefile b/Makefile
index 0371d46..8926904 100644
--- a/Makefile
+++ b/Makefile
@@ -211,6 +211,7 @@ LIBS += drivers/libdrivers.a
 LIBS += drivers/bios_emulator/libatibiosemu.a
 LIBS += drivers/nand/libnand.a
 LIBS += drivers/nand_legacy/libnand_legacy.a
+LIBS += drivers/onenand/libonenand.a
 LIBS += drivers/net/libnet.a
 ifeq ($(CPU),mpc83xx)
 LIBS += drivers/qe/qe.a
diff --git a/common/Makefile b/common/Makefile
index ef7d097..fde5ad9 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -37,13 +37,14 @@ COBJS	= main.o ACEX1K.o altera.o bedbug.o circbuf.o cmd_autoscript.o \
 	  cmd_load.o cmd_log.o \
 	  cmd_mem.o cmd_mii.o cmd_misc.o cmd_mmc.o \
 	  cmd_nand.o cmd_net.o cmd_nvedit.o \
+	  cmd_onenand.o \
 	  cmd_pci.o cmd_pcmcia.o cmd_portio.o \
 	  cmd_reginfo.o cmd_reiser.o cmd_sata.o cmd_scsi.o cmd_spi.o \
 	  cmd_universe.o cmd_usb.o cmd_vfd.o \
 	  command.o console.o cyclon2.o devices.o dlmalloc.o docecc.o \
 	  environment.o env_common.o \
 	  env_nand.o env_dataflash.o env_flash.o env_eeprom.o \
-	  env_nvram.o env_nowhere.o \
+	  env_onenand.o env_nvram.o env_nowhere.o \
 	  exports.o \
 	  fdt_support.o flash.o fpga.o ft_build.o \
 	  hush.o kgdb.o lcd.o lists.o lynxkdi.o \
diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 1db0fc3..6770408 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -57,8 +57,9 @@ DECLARE_GLOBAL_DATA_PTR;
     !defined(CFG_ENV_IS_IN_FLASH)	&& \
     !defined(CFG_ENV_IS_IN_DATAFLASH)	&& \
     !defined(CFG_ENV_IS_IN_NAND)	&& \
+    !defined(CFG_ENV_IS_IN_ONENAND)	&& \
     !defined(CFG_ENV_IS_NOWHERE)
-# error Define one of CFG_ENV_IS_IN_{NVRAM|EEPROM|FLASH|DATAFLASH|NOWHERE}
+# error Define one of CFG_ENV_IS_IN_{NVRAM|EEPROM|FLASH|DATAFLASH|ONENAND|NOWHERE}
 #endif
 
 #define XMK_STR(x)	#x
@@ -553,7 +554,8 @@ int getenv_r (char *name, char *buf, unsigned len)
 
 #if defined(CFG_ENV_IS_IN_NVRAM) || defined(CFG_ENV_IS_IN_EEPROM) \
     || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_FLASH)) \
-    || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_NAND))
+    || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_NAND)) \
+    || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_ONENAND))
 int do_saveenv (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
 	extern char * env_name_spec;
@@ -608,7 +610,8 @@ U_BOOT_CMD(
 
 #if defined(CFG_ENV_IS_IN_NVRAM) || defined(CFG_ENV_IS_IN_EEPROM) \
     || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_FLASH)) \
-    || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_NAND))
+    || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_NAND)) \
+    || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_ONENAND))
 U_BOOT_CMD(
 	saveenv, 1, 0,	do_saveenv,
 	"saveenv - save environment variables to persistent storage\n",
diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c
new file mode 100644
index 0000000..dcda099
--- /dev/null
+++ b/common/cmd_onenand.c
@@ -0,0 +1,155 @@
+/*
+ *  U-Boot command for OneNAND support
+ *
+ *  Copyright (C) 2005-2007 Samsung Electronics
+ *  Kyungmin Park <kyungmin.park at samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <command.h>
+
+#ifdef CONFIG_CMD_ONENAND
+
+#include <linux/mtd/compat.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/onenand.h>
+
+#include <asm/io.h>
+
+extern struct mtd_info onenand_mtd;
+extern struct onenand_chip onenand_chip;
+
+int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	int ret = 0;
+
+	switch (argc) {
+	case 0:
+	case 1:
+		printf("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+
+	case 2:
+		if (strncmp(argv[1], "open", 4) == 0) {
+			onenand_init();
+			return 0;
+		}
+		onenand_print_device_info(onenand_chip.device_id, 1);
+		return 0;
+
+	default:
+		/* At least 4 args */
+		if (strncmp(argv[1], "erase", 5) == 0) {
+			struct erase_info instr;
+			ulong start, end;
+			ulong block;
+
+			start = simple_strtoul(argv[2], NULL, 10);
+			end = simple_strtoul(argv[3], NULL, 10);
+			start -= (unsigned long)onenand_chip.base;
+			end -= (unsigned long)onenand_chip.base;
+
+			if (!end || end < 0)
+				end = start;
+
+			printf("Erase block from %d to %d\n", start, end);
+
+			for (block = start; block <= end; block++) {
+				instr.addr = block << onenand_chip.erase_shift;
+				instr.len = 1 << onenand_chip.erase_shift;
+				ret = onenand_erase(&onenand_mtd, &instr);
+				if (ret) {
+					printf("erase failed %d\n", block);
+					break;
+				}
+			}
+
+			return 0;
+		}
+
+		if (strncmp(argv[1], "read", 4) == 0) {
+			ulong addr = simple_strtoul(argv[2], NULL, 16);
+			ulong ofs = simple_strtoul(argv[3], NULL, 16);
+			size_t len = simple_strtoul(argv[4], NULL, 16);
+			size_t retlen = 0;
+			int oob = strncmp(argv[1], "read.oob", 8) ? 0 : 1;
+
+			ofs -= (unsigned long)onenand_chip.base;
+
+			if (oob)
+				onenand_read_oob(&onenand_mtd, ofs, len,
+						 &retlen, (u_char *) addr);
+			else
+				onenand_read(&onenand_mtd, ofs, len, &retlen,
+					     (u_char *) addr);
+			printf("Done\n");
+
+			return 0;
+		}
+
+		if (strncmp(argv[1], "write", 5) == 0) {
+			ulong addr = simple_strtoul(argv[2], NULL, 16);
+			ulong ofs = simple_strtoul(argv[3], NULL, 16);
+			size_t len = simple_strtoul(argv[4], NULL, 16);
+			size_t retlen = 0;
+
+			ofs -= (unsigned long)onenand_chip.base;
+
+			onenand_write(&onenand_mtd, ofs, len, &retlen,
+				      (u_char *) addr);
+			printf("Done\n");
+
+			return 0;
+		}
+
+		if (strncmp(argv[1], "block", 5) == 0) {
+			ulong addr = simple_strtoul(argv[2], NULL, 16);
+			ulong block = simple_strtoul(argv[3], NULL, 10);
+			ulong page = simple_strtoul(argv[4], NULL, 10);
+			size_t len = simple_strtol(argv[5], NULL, 10);
+			size_t retlen = 0;
+			ulong ofs;
+			int oob = strncmp(argv[1], "block.oob", 9) ? 0 : 1;
+
+			ofs = block << onenand_chip.erase_shift;
+			if (page)
+				ofs += page << onenand_chip.page_shift;
+
+			if (!len) {
+				if (oob)
+					len = 64;
+				else
+					len = 512;
+			}
+
+			if (oob)
+				onenand_read_oob(&onenand_mtd, ofs, len,
+						 &retlen, (u_char *) addr);
+			else
+				onenand_read(&onenand_mtd, ofs, len, &retlen,
+					     (u_char *) addr);
+			return 0;
+		}
+
+		break;
+	}
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	onenand,	6,	1,	do_onenand,
+	"onenand - OneNAND sub-system\n",
+	"info   - show available OneNAND devices\n"
+	"onenand read[.oob] addr ofs len - read data at ofs with len to addr\n"
+	"onenand write addr ofs len - write data at ofs with len from addr\n"
+	"onenand erase saddr eaddr - erase block start addr to end addr\n"
+	"onenand block[.oob] addr block [page] [len] - "
+		"read data with (block [, page]) to addr"
+);
+
+#endif /* CONFIG_CMD_ONENAND */
diff --git a/common/env_onenand.c b/common/env_onenand.c
new file mode 100644
index 0000000..66107f9
--- /dev/null
+++ b/common/env_onenand.c
@@ -0,0 +1,134 @@
+/*
+ * (C) Copyright 2005-2007 Samsung Electronics
+ * Kyungmin Park <kyungmin.park at samsung.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#if defined(CFG_ENV_IS_IN_ONENAND)	/* Environment is in OneNAND */
+
+#include <command.h>
+#include <environment.h>
+#include <linux/stddef.h>
+#include <malloc.h>
+
+#include <linux/mtd/compat.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/onenand.h>
+
+extern struct mtd_info onenand_mtd;
+extern struct onenand_chip onenand_chip;
+
+/* References to names in env_common.c */
+extern uchar default_environment[];
+
+#define ONENAND_ENV_SIZE(mtd)	(mtd.oobblock - ENV_HEADER_SIZE)
+
+char *env_name_spec = "OneNAND";
+
+#ifdef ENV_IS_EMBEDDED
+extern uchar environment[];
+env_t *env_ptr = (env_t *) (&environment[0]);
+#else /* ! ENV_IS_EMBEDDED */
+static unsigned char onenand_env[MAX_ONENAND_PAGESIZE];
+env_t *env_ptr = (env_t *) onenand_env;
+#endif /* ENV_IS_EMBEDDED */
+
+uchar env_get_char_spec(int index)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	return (*((uchar *) (gd->env_addr + index)));
+}
+
+void env_relocate_spec(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+	unsigned long env_addr;
+	int use_default = 0;
+	int retlen;
+
+	env_addr = CFG_ENV_ADDR;
+	env_addr -= (unsigned long)onenand_chip.base;
+
+	/* Check OneNAND exist */
+	if (onenand_mtd.oobblock)
+		/* Ignore read fail */
+		onenand_read(&onenand_mtd, env_addr, onenand_mtd.oobblock,
+			     &retlen, (u_char *) env_ptr);
+	else
+		onenand_mtd.oobblock = MAX_ONENAND_PAGESIZE;
+
+	if (crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd)) !=
+	    env_ptr->crc)
+		use_default = 1;
+
+	if (use_default) {
+		memcpy(env_ptr->data, default_environment,
+		       ONENAND_ENV_SIZE(onenand_mtd));
+		env_ptr->crc =
+		    crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd));
+	}
+
+	gd->env_addr = (ulong) & env_ptr->data;
+	gd->env_valid = 1;
+}
+
+int saveenv(void)
+{
+	unsigned long env_addr = CFG_ENV_ADDR;
+	struct erase_info instr;
+	int retlen;
+
+	instr.len = CFG_ENV_SIZE;
+	instr.addr = env_addr;
+	instr.addr -= (unsigned long)onenand_chip.base;
+	if (onenand_erase(&onenand_mtd, &instr)) {
+		printf("OneNAND: erase failed at 0x%08x\n", env_addr);
+		return 1;
+	}
+
+	/* update crc */
+	env_ptr->crc =
+	    crc32(0, env_ptr->data, onenand_mtd.oobblock - ENV_HEADER_SIZE);
+
+	env_addr -= (unsigned long)onenand_chip.base;
+	if (onenand_write(&onenand_mtd, env_addr, onenand_mtd.oobblock, &retlen,
+	     (u_char *) env_ptr)) {
+		printf("OneNAND: write failed at 0x%08x\n", instr.addr);
+		return 2;
+	}
+
+	return 0;
+}
+
+int env_init(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	/* use default */
+	gd->env_addr = (ulong) & default_environment[0];
+	gd->env_valid = 1;
+
+	return 0;
+}
+
+#endif /* CFG_ENV_IS_IN_ONENAND */
diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h
index 3d91e99..f8eca87 100644
--- a/include/config_cmd_all.h
+++ b/include/config_cmd_all.h
@@ -59,6 +59,7 @@
 #define CONFIG_CMD_NAND		/* NAND support			*/
 #define CONFIG_CMD_NET		/* bootp, tftpboot, rarpboot	*/
 #define CONFIG_CMD_NFS		/* NFS support			*/
+#define CONFIG_CMD_ONENAND	/* OneNAND support		*/
 #define CONFIG_CMD_PCI		/* pciinfo			*/
 #define CONFIG_CMD_PCMCIA	/* PCMCIA support		*/
 #define CONFIG_CMD_PING		/* ping support			*/
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
new file mode 100644
index 0000000..f194cf1
--- /dev/null
+++ b/include/linux/mtd/bbm.h
@@ -0,0 +1,127 @@
+/*
+ *  linux/include/linux/mtd/bbm.h
+ *
+ *  NAND family Bad Block Management (BBM) header file
+ *    - Bad Block Table (BBT) implementation
+ *
+ *  Copyright (c) 2005-2007 Samsung Electronics
+ *  Kyungmin Park <kyungmin.park at samsung.com>
+ *
+ *  Copyright (c) 2000-2005
+ *  Thomas Gleixner <tglx at linuxtronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __LINUX_MTD_BBM_H
+#define __LINUX_MTD_BBM_H
+
+/* The maximum number of NAND chips in an array */
+#ifndef NAND_MAX_CHIPS
+#define NAND_MAX_CHIPS		8
+#endif
+
+/**
+ * struct nand_bbt_descr - bad block table descriptor
+ * @param options	options for this descriptor
+ * @param pages		the page(s) where we find the bbt, used with
+ * 			option BBT_ABSPAGE when bbt is searched,
+ * 			then we store the found bbts pages here.
+ *			Its an array and supports up to 8 chips now
+ * @param offs		offset of the pattern in the oob area of the page
+ * @param veroffs	offset of the bbt version counter in the oob are of the page
+ * @param version	version read from the bbt page during scan
+ * @param len		length of the pattern, if 0 no pattern check is performed
+ * @param maxblocks	maximum number of blocks to search for a bbt. This number of
+ *			blocks is reserved at the end of the device
+ *			where the tables are written.
+ * @param reserved_block_code	if non-0, this pattern denotes a reserved
+ *			(rather than bad) block in the stored bbt
+ * @param pattern	pattern to identify bad block table or factory marked
+ *			good / bad blocks, can be NULL, if len = 0
+ *
+ * Descriptor for the bad block table marker and the descriptor for the
+ * pattern which identifies good and bad blocks. The assumption is made
+ * that the pattern and the version count are always located in the oob area
+ * of the first block.
+ */
+struct nand_bbt_descr {
+	int options;
+	int pages[NAND_MAX_CHIPS];
+	int offs;
+	int veroffs;
+	uint8_t version[NAND_MAX_CHIPS];
+	int len;
+	int maxblocks;
+	int reserved_block_code;
+	uint8_t *pattern;
+};
+
+/* Options for the bad block table descriptors */
+
+/* The number of bits used per block in the bbt on the device */
+#define NAND_BBT_NRBITS_MSK	0x0000000F
+#define NAND_BBT_1BIT		0x00000001
+#define NAND_BBT_2BIT		0x00000002
+#define NAND_BBT_4BIT		0x00000004
+#define NAND_BBT_8BIT		0x00000008
+/* The bad block table is in the last good block of the device */
+#define NAND_BBT_LASTBLOCK	0x00000010
+/* The bbt is at the given page, else we must scan for the bbt */
+#define NAND_BBT_ABSPAGE	0x00000020
+/* The bbt is at the given page, else we must scan for the bbt */
+#define NAND_BBT_SEARCH		0x00000040
+/* bbt is stored per chip on multichip devices */
+#define NAND_BBT_PERCHIP	0x00000080
+/* bbt has a version counter at offset veroffs */
+#define NAND_BBT_VERSION	0x00000100
+/* Create a bbt if none axists */
+#define NAND_BBT_CREATE		0x00000200
+/* Search good / bad pattern through all pages of a block */
+#define NAND_BBT_SCANALLPAGES	0x00000400
+/* Scan block empty during good / bad block scan */
+#define NAND_BBT_SCANEMPTY	0x00000800
+/* Write bbt if neccecary */
+#define NAND_BBT_WRITE		0x00001000
+/* Read and write back block contents when writing bbt */
+#define NAND_BBT_SAVECONTENT	0x00002000
+/* Search good / bad pattern on the first and the second page */
+#define NAND_BBT_SCAN2NDPAGE	0x00004000
+
+/* The maximum number of blocks to scan for a bbt */
+#define NAND_BBT_SCAN_MAXBLOCKS	4
+
+/*
+ * Constants for oob configuration
+ */
+#define ONENAND_BADBLOCK_POS	0
+
+/**
+ * struct bbt_info - [GENERIC] Bad Block Table data structure
+ * @param bbt_erase_shift	[INTERN] number of address bits in a bbt entry
+ * @param badblockpos		[INTERN] position of the bad block marker in the oob area
+ * @param bbt			[INTERN] bad block table pointer
+ * @param badblock_pattern	[REPLACEABLE] bad block scan pattern used for initial bad block scan
+ * @param priv			[OPTIONAL] pointer to private bbm date
+ */
+struct bbm_info {
+	int bbt_erase_shift;
+	int badblockpos;
+	int options;
+
+	uint8_t *bbt;
+
+	int (*isbad_bbt) (struct mtd_info * mtd, loff_t ofs, int allowbbt);
+
+	/* TODO Add more NAND specific fileds */
+	struct nand_bbt_descr *badblock_pattern;
+
+	void *priv;
+};
+
+/* OneNAND BBT interface */
+extern int onenand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd);
+extern int onenand_default_bbt (struct mtd_info *mtd);
+
+#endif				/* __LINUX_MTD_BBM_H */
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
new file mode 100644
index 0000000..4b0c2df
--- /dev/null
+++ b/include/linux/mtd/onenand.h
@@ -0,0 +1,143 @@
+/*
+ *  linux/include/linux/mtd/onenand.h
+ *
+ *  Copyright (C) 2005-2007 Samsung Electronics
+ *  Kyungmin Park <kyungmin.park at samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_MTD_ONENAND_H
+#define __LINUX_MTD_ONENAND_H
+
+#include <linux/mtd/onenand_regs.h>
+
+/* Note: The header order is impoertant */
+#include <onenand_uboot.h>
+
+#include <linux/mtd/bbm.h>
+
+#define MAX_BUFFERRAM		2
+#define MAX_ONENAND_PAGESIZE	(2048 + 64)
+
+/* Scan and identify a OneNAND device */
+extern int onenand_scan (struct mtd_info *mtd, int max_chips);
+/* Free resources held by the OneNAND device */
+extern void onenand_release (struct mtd_info *mtd);
+
+/**
+ * onenand_state_t - chip states
+ * Enumeration for OneNAND flash chip state
+ */
+typedef enum {
+	FL_READY,
+	FL_READING,
+	FL_WRITING,
+	FL_ERASING,
+	FL_SYNCING,
+	FL_UNLOCKING,
+	FL_LOCKING,
+} onenand_state_t;
+
+/**
+ * struct onenand_bufferram - OneNAND BufferRAM Data
+ * @param block		block address in BufferRAM
+ * @param page		page address in BufferRAM
+ * @param valid		valid flag
+ */
+struct onenand_bufferram {
+	int block;
+	int page;
+	int valid;
+};
+
+/**
+ * struct onenand_chip - OneNAND Private Flash Chip Data
+ * @param base		[BOARDSPECIFIC] address to access OneNAND
+ * @param chipsize	[INTERN] the size of one chip for multichip arrays
+ * @param device_id	[INTERN] device ID
+ * @param verstion_id	[INTERN] version ID
+ * @param options	[BOARDSPECIFIC] various chip options. They can partly be set to inform onenand_scan about
+ * @param erase_shift	[INTERN] number of address bits in a block
+ * @param page_shift	[INTERN] number of address bits in a page
+ * @param ppb_shift	[INTERN] number of address bits in a pages per block
+ * @param page_mask	[INTERN] a page per block mask
+ * @param bufferam_index	[INTERN] BufferRAM index
+ * @param bufferam	[INTERN] BufferRAM info
+ * @param readw		[REPLACEABLE] hardware specific function for read short
+ * @param writew	[REPLACEABLE] hardware specific function for write short
+ * @param command	[REPLACEABLE] hardware specific function for writing commands to the chip
+ * @param wait		[REPLACEABLE] hardware specific function for wait on ready
+ * @param read_bufferram	[REPLACEABLE] hardware specific function for BufferRAM Area
+ * @param write_bufferram	[REPLACEABLE] hardware specific function for BufferRAM Area
+ * @param chip_lock	[INTERN] spinlock used to protect access to this structure and the chip
+ * @param wq		[INTERN] wait queue to sleep on if a OneNAND operation is in progress
+ * @param state		[INTERN] the current state of the OneNAND device
+ * @param autooob	[REPLACEABLE] the default (auto)placement scheme
+ * @param priv		[OPTIONAL] pointer to private chip date
+ */
+struct onenand_chip {
+	void __iomem *base;
+	unsigned int chipsize;
+	unsigned int device_id;
+	unsigned int options;
+
+	unsigned int erase_shift;
+	unsigned int page_shift;
+	unsigned int ppb_shift;	/* Pages per block shift */
+	unsigned int page_mask;
+
+	unsigned int bufferram_index;
+	struct onenand_bufferram bufferram[MAX_BUFFERRAM];
+
+	int (*command) (struct mtd_info * mtd, int cmd, loff_t address,
+			size_t len);
+	int (*wait) (struct mtd_info * mtd, int state);
+	int (*read_bufferram) (struct mtd_info * mtd, int area,
+			       unsigned char *buffer, int offset, size_t count);
+	int (*write_bufferram) (struct mtd_info * mtd, int area,
+				const unsigned char *buffer, int offset,
+				size_t count);
+	unsigned short (*read_word) (void __iomem * addr);
+	void (*write_word) (unsigned short value, void __iomem * addr);
+	void (*mmcontrol) (struct mtd_info * mtd, int sync_read);
+
+	spinlock_t chip_lock;
+	wait_queue_head_t wq;
+	onenand_state_t state;
+
+	struct nand_oobinfo *autooob;
+
+	void *bbm;
+
+	void *priv;
+};
+
+#define ONENAND_CURRENT_BUFFERRAM(this)		(this->bufferram_index)
+#define ONENAND_NEXT_BUFFERRAM(this)		(this->bufferram_index ^ 1)
+#define ONENAND_SET_NEXT_BUFFERRAM(this)	(this->bufferram_index ^= 1)
+
+/*
+ * Options bits
+ */
+#define ONENAND_CONT_LOCK		(0x0001)
+
+/*
+ * OneNAND Flash Manufacturer ID Codes
+ */
+#define ONENAND_MFR_SAMSUNG	0xec
+#define ONENAND_MFR_UNKNOWN	0x00
+
+/**
+ * struct nand_manufacturers - NAND Flash Manufacturer ID Structure
+ * @param name:		Manufacturer name
+ * @param id:		manufacturer ID code of device.
+*/
+struct onenand_manufacturers {
+	int id;
+	char *name;
+};
+
+#endif				/* __LINUX_MTD_ONENAND_H */
diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h
new file mode 100644
index 0000000..c8a9f3e
--- /dev/null
+++ b/include/linux/mtd/onenand_regs.h
@@ -0,0 +1,181 @@
+/*
+ *  linux/include/linux/mtd/onenand_regs.h
+ *
+ *  OneNAND Register header file
+ *
+ *  Copyright (C) 2005-2007 Samsung Electronics
+ *  Kyungmin Park <kyungmin.park at samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ONENAND_REG_H
+#define __ONENAND_REG_H
+
+/* Memory Address Map Translation (Word order) */
+#define ONENAND_MEMORY_MAP(x)		((x) << 1)
+
+/*
+ * External BufferRAM area
+ */
+#define	ONENAND_BOOTRAM			ONENAND_MEMORY_MAP(0x0000)
+#define	ONENAND_DATARAM			ONENAND_MEMORY_MAP(0x0200)
+#define	ONENAND_SPARERAM		ONENAND_MEMORY_MAP(0x8010)
+
+/*
+ * OneNAND Registers
+ */
+#define ONENAND_REG_MANUFACTURER_ID	ONENAND_MEMORY_MAP(0xF000)
+#define ONENAND_REG_DEVICE_ID		ONENAND_MEMORY_MAP(0xF001)
+#define ONENAND_REG_VERSION_ID		ONENAND_MEMORY_MAP(0xF002)
+#define ONENAND_REG_DATA_BUFFER_SIZE	ONENAND_MEMORY_MAP(0xF003)
+#define ONENAND_REG_BOOT_BUFFER_SIZE	ONENAND_MEMORY_MAP(0xF004)
+#define ONENAND_REG_NUM_BUFFERS		ONENAND_MEMORY_MAP(0xF005)
+#define ONENAND_REG_TECHNOLOGY		ONENAND_MEMORY_MAP(0xF006)
+
+#define ONENAND_REG_START_ADDRESS1	ONENAND_MEMORY_MAP(0xF100)
+#define ONENAND_REG_START_ADDRESS2	ONENAND_MEMORY_MAP(0xF101)
+#define ONENAND_REG_START_ADDRESS3	ONENAND_MEMORY_MAP(0xF102)
+#define ONENAND_REG_START_ADDRESS4	ONENAND_MEMORY_MAP(0xF103)
+#define ONENAND_REG_START_ADDRESS5	ONENAND_MEMORY_MAP(0xF104)
+#define ONENAND_REG_START_ADDRESS6	ONENAND_MEMORY_MAP(0xF105)
+#define ONENAND_REG_START_ADDRESS7	ONENAND_MEMORY_MAP(0xF106)
+#define ONENAND_REG_START_ADDRESS8	ONENAND_MEMORY_MAP(0xF107)
+
+#define ONENAND_REG_START_BUFFER	ONENAND_MEMORY_MAP(0xF200)
+#define ONENAND_REG_COMMAND		ONENAND_MEMORY_MAP(0xF220)
+#define ONENAND_REG_SYS_CFG1		ONENAND_MEMORY_MAP(0xF221)
+#define ONENAND_REG_SYS_CFG2		ONENAND_MEMORY_MAP(0xF222)
+#define ONENAND_REG_CTRL_STATUS		ONENAND_MEMORY_MAP(0xF240)
+#define ONENAND_REG_INTERRUPT		ONENAND_MEMORY_MAP(0xF241)
+#define ONENAND_REG_START_BLOCK_ADDRESS	ONENAND_MEMORY_MAP(0xF24C)
+#define ONENAND_REG_END_BLOCK_ADDRESS	ONENAND_MEMORY_MAP(0xF24D)
+#define ONENAND_REG_WP_STATUS		ONENAND_MEMORY_MAP(0xF24E)
+
+#define ONENAND_REG_ECC_STATUS		ONENAND_MEMORY_MAP(0xFF00)
+#define ONENAND_REG_ECC_M0		ONENAND_MEMORY_MAP(0xFF01)
+#define ONENAND_REG_ECC_S0		ONENAND_MEMORY_MAP(0xFF02)
+#define ONENAND_REG_ECC_M1		ONENAND_MEMORY_MAP(0xFF03)
+#define ONENAND_REG_ECC_S1		ONENAND_MEMORY_MAP(0xFF04)
+#define ONENAND_REG_ECC_M2		ONENAND_MEMORY_MAP(0xFF05)
+#define ONENAND_REG_ECC_S2		ONENAND_MEMORY_MAP(0xFF06)
+#define ONENAND_REG_ECC_M3		ONENAND_MEMORY_MAP(0xFF07)
+#define ONENAND_REG_ECC_S3		ONENAND_MEMORY_MAP(0xFF08)
+
+/*
+ * Device ID Register F001h (R)
+ */
+#define ONENAND_DEVICE_DENSITY_SHIFT	(4)
+#define ONENAND_DEVICE_IS_DDP		(1 << 3)
+#define ONENAND_DEVICE_IS_DEMUX		(1 << 2)
+#define ONENAND_DEVICE_VCC_MASK		(0x3)
+
+#define ONENAND_DEVICE_DENSITY_512Mb	(0x002)
+
+/*
+ * Version ID Register F002h (R)
+ */
+#define ONENAND_VERSION_PROCESS_SHIFT	(8)
+
+/*
+ * Start Address 1 F100h (R/W)
+ */
+#define ONENAND_DDP_SHIFT		(15)
+
+/*
+ * Start Address 8 F107h (R/W)
+ */
+#define ONENAND_FPA_MASK		(0x3f)
+#define ONENAND_FPA_SHIFT		(2)
+#define ONENAND_FSA_MASK		(0x03)
+
+/*
+ * Start Buffer Register F200h (R/W)
+ */
+#define ONENAND_BSA_MASK		(0x03)
+#define ONENAND_BSA_SHIFT		(8)
+#define ONENAND_BSA_BOOTRAM		(0 << 2)
+#define ONENAND_BSA_DATARAM0		(2 << 2)
+#define ONENAND_BSA_DATARAM1		(3 << 2)
+#define ONENAND_BSC_MASK		(0x03)
+
+/*
+ * Command Register F220h (R/W)
+ */
+#define ONENAND_CMD_READ		(0x00)
+#define ONENAND_CMD_READOOB		(0x13)
+#define ONENAND_CMD_PROG		(0x80)
+#define ONENAND_CMD_PROGOOB		(0x1A)
+#define ONENAND_CMD_UNLOCK		(0x23)
+#define ONENAND_CMD_LOCK		(0x2A)
+#define ONENAND_CMD_LOCK_TIGHT		(0x2C)
+#define ONENAND_CMD_ERASE		(0x94)
+#define ONENAND_CMD_RESET		(0xF0)
+#define ONENAND_CMD_READID		(0x90)
+
+/* NOTE: Those are not *REAL* commands */
+#define ONENAND_CMD_BUFFERRAM		(0x1978)
+
+/*
+ * System Configuration 1 Register F221h (R, R/W)
+ */
+#define ONENAND_SYS_CFG1_SYNC_READ	(1 << 15)
+#define ONENAND_SYS_CFG1_BRL_7		(7 << 12)
+#define ONENAND_SYS_CFG1_BRL_6		(6 << 12)
+#define ONENAND_SYS_CFG1_BRL_5		(5 << 12)
+#define ONENAND_SYS_CFG1_BRL_4		(4 << 12)
+#define ONENAND_SYS_CFG1_BRL_3		(3 << 12)
+#define ONENAND_SYS_CFG1_BRL_10		(2 << 12)
+#define ONENAND_SYS_CFG1_BRL_9		(1 << 12)
+#define ONENAND_SYS_CFG1_BRL_8		(0 << 12)
+#define ONENAND_SYS_CFG1_BRL_SHIFT	(12)
+#define ONENAND_SYS_CFG1_BL_32		(4 << 9)
+#define ONENAND_SYS_CFG1_BL_16		(3 << 9)
+#define ONENAND_SYS_CFG1_BL_8		(2 << 9)
+#define ONENAND_SYS_CFG1_BL_4		(1 << 9)
+#define ONENAND_SYS_CFG1_BL_CONT	(0 << 9)
+#define ONENAND_SYS_CFG1_BL_SHIFT	(9)
+#define ONENAND_SYS_CFG1_NO_ECC		(1 << 8)
+#define ONENAND_SYS_CFG1_RDY		(1 << 7)
+#define ONENAND_SYS_CFG1_INT		(1 << 6)
+#define ONENAND_SYS_CFG1_IOBE		(1 << 5)
+#define ONENAND_SYS_CFG1_RDY_CONF	(1 << 4)
+
+/*
+ * Controller Status Register F240h (R)
+ */
+#define ONENAND_CTRL_ONGO		(1 << 15)
+#define ONENAND_CTRL_LOCK		(1 << 14)
+#define ONENAND_CTRL_LOAD		(1 << 13)
+#define ONENAND_CTRL_PROGRAM		(1 << 12)
+#define ONENAND_CTRL_ERASE		(1 << 11)
+#define ONENAND_CTRL_ERROR		(1 << 10)
+#define ONENAND_CTRL_RSTB		(1 << 7)
+
+/*
+ * Interrupt Status Register F241h (R)
+ */
+#define ONENAND_INT_MASTER		(1 << 15)
+#define ONENAND_INT_READ		(1 << 7)
+#define ONENAND_INT_WRITE		(1 << 6)
+#define ONENAND_INT_ERASE		(1 << 5)
+#define ONENAND_INT_RESET		(1 << 4)
+#define ONENAND_INT_CLEAR		(0 << 0)
+
+/*
+ * NAND Flash Write Protection Status Register F24Eh (R)
+ */
+#define ONENAND_WP_US			(1 << 2)
+#define ONENAND_WP_LS			(1 << 1)
+#define ONENAND_WP_LTS			(1 << 0)
+
+/*
+ * ECC Status Reigser FF00h (R)
+ */
+#define ONENAND_ECC_1BIT		(1 << 0)
+#define ONENAND_ECC_2BIT		(1 << 1)
+#define ONENAND_ECC_2BIT_ALL		(0xAAAA)
+
+#endif				/* __ONENAND_REG_H */
diff --git a/include/onenand_uboot.h b/include/onenand_uboot.h
new file mode 100644
index 0000000..bd1831e
--- /dev/null
+++ b/include/onenand_uboot.h
@@ -0,0 +1,39 @@
+/*
+ *  Header file for OneNAND support for U-Boot
+ *
+ *  Adaptation from kernel to U-Boot
+ *
+ *  Copyright (C) 2005-2007 Samsung Electronics
+ *  Kyungmin Park <kyungmin.park at samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __UBOOT_ONENAND_H
+#define __UBOOT_ONENAND_H
+
+struct kvec {
+	void *iov_base;
+	size_t iov_len;
+};
+
+typedef int spinlock_t;
+typedef int wait_queue_head_t;
+
+/* Functions */
+extern void onenand_init(void);
+extern int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
+			size_t * retlen, u_char * buf);
+extern int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
+			    size_t * retlen, u_char * buf);
+extern int onenand_write(struct mtd_info *mtd, loff_t from, size_t len,
+			 size_t * retlen, const u_char * buf);
+extern int onenand_erase(struct mtd_info *mtd, struct erase_info *instr);
+
+extern int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len);
+
+extern void onenand_print_device_info(int device, int verbose);
+
+#endif /* __UBOOT_ONENAND_H */
diff --git a/lib_arm/board.c b/lib_arm/board.c
index d28afc5..634e4d9 100644
--- a/lib_arm/board.c
+++ b/lib_arm/board.c
@@ -58,6 +58,10 @@ DECLARE_GLOBAL_DATA_PTR;
 void nand_init (void);
 #endif
 
+#if defined(CONFIG_CMD_ONENAND)
+void onenand_init(void);
+#endif
+
 ulong monitor_flash_len;
 
 #ifdef CONFIG_HAS_DATAFLASH
@@ -301,6 +305,10 @@ void start_armboot (void)
 	nand_init();		/* go init the NAND */
 #endif
 
+#if defined(CONFIG_CMD_ONENAND)
+	onenand_init();
+#endif
+
 #ifdef CONFIG_HAS_DATAFLASH
 	AT91F_DataflashInit();
 	dataflash_print_info();




More information about the U-Boot mailing list