OneNAND support (take #2)
authorKyungmin Park <kmpark@infradead.org>
Mon, 10 Sep 2007 08:15:14 +0000 (17:15 +0900)
committerStefan Roese <sr@denx.de>
Mon, 17 Sep 2007 06:19:08 +0000 (08:19 +0200)
[PATCH 3/3] OneNAND support (take #2)

OneNAND support at U-Boot

Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Makefile
common/Makefile
common/cmd_nvedit.c
common/cmd_onenand.c [new file with mode: 0644]
common/env_onenand.c [new file with mode: 0644]
include/config_cmd_all.h
include/linux/mtd/bbm.h [new file with mode: 0644]
include/linux/mtd/onenand.h [new file with mode: 0644]
include/linux/mtd/onenand_regs.h [new file with mode: 0644]
include/onenand_uboot.h [new file with mode: 0644]
lib_arm/board.c

index 85885b166a6eab9d8efeefcb347d32b327761ee9..c35f0223382d8e076522b684e858dfb5a662ee2f 100644 (file)
--- 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
index ef7d09707898c87d5cc451a80d310fe7d0f566e0..fde5ad903d63dddd7d2950168f483ecd7c228180 100644 (file)
@@ -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 \
index 1db0fc3c03b14c4a3fb0761b2cc77bc4b562e7ed..67704088104696424fffc97c20d16b6e238729a8 100644 (file)
@@ -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 (file)
index 0000000..dcda099
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ *  U-Boot command for OneNAND support
+ *
+ *  Copyright (C) 2005-2007 Samsung Electronics
+ *  Kyungmin Park <kyungmin.park@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 (file)
index 0000000..66107f9
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * (C) Copyright 2005-2007 Samsung Electronics
+ * Kyungmin Park <kyungmin.park@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 */
index 3d91e99b97f17e58c91ccb24930134489ec1c627..f8eca87a844f0275487b02d27a6f7b66414a1559 100644 (file)
@@ -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 (file)
index 0000000..f194cf1
--- /dev/null
@@ -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@samsung.com>
+ *
+ *  Copyright (c) 2000-2005
+ *  Thomas Gleixner <tglx@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 (file)
index 0000000..4b0c2df
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ *  linux/include/linux/mtd/onenand.h
+ *
+ *  Copyright (C) 2005-2007 Samsung Electronics
+ *  Kyungmin Park <kyungmin.park@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 (file)
index 0000000..c8a9f3e
--- /dev/null
@@ -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@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 (file)
index 0000000..bd1831e
--- /dev/null
@@ -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@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 */
index d28afc52f9f492ec2a5c3f8de193fedfec5614fe..634e4d9438343243fcbf1131ac0bbbe945cdbc7d 100644 (file)
@@ -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();