This is the mail archive of the
ecos-patches@sourceware.org
mailing list for the eCos project.
NAND Flash device driver
- From: Alexey Shusharin <mrfinch at mail dot ru>
- To: ecos-patches at ecos dot sourceware dot org
- Date: Mon, 10 Dec 2007 19:01:58 +0600
- Subject: NAND Flash device driver
Hi,
This patch adds a NAND Flash device driver to flash V1 branch.
Currently it supports 8-bit NAND flash with 256/512 page size and has
implemented software ECC and simple bad block management algorithms.
I've tested it with SAMSUNG K9F5608U0D.
Best regards
Alexey Shusharin
diff -bur -P /opt/ecos-repo/cvs/ecos/packages/devs/flash/nand/current/cdl/nand_flash.cdl ./devs/flash/nand/current/cdl/nand_flash.cdl
--- /opt/ecos-repo/cvs/ecos/packages/devs/flash/nand/current/cdl/nand_flash.cdl 1970-01-01 06:00:00.000000000 +0600
+++ ./devs/flash/nand/current/cdl/nand_flash.cdl 2007-12-10 18:31:58.000000000 +0600
@@ -0,0 +1,152 @@
+# ====================================================================
+#
+# nand_flash.cdl
+#
+# FLASH memory - Support for NAND flash
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+##
+## eCos 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 or (at your option) any later version.
+##
+## eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s): Alexey Shusharin <mrfinch@mail.ru>
+# Contributors:
+# Date: 2007-11-16
+# Description: Driver for NAND FLASH devices.
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_DEVS_FLASH_NAND {
+ display "NAND FLASH memory support"
+ description "NAND FLASH memory device support"
+ parent CYGPKG_IO_FLASH
+ active_if CYGPKG_IO_FLASH
+
+ requires { CYGSEM_IO_FLASH_READ_INDIRECT == 1 }
+ active_if CYGINT_DEVS_FLASH_NAND_REQUIRED
+
+ compile nand_flash.c
+
+ include_dir cyg/io
+
+ # Error checking and correction
+ cdl_component CYGPKG_DEVS_FLASH_NAND_ECC {
+ display "Error checking and correction (ECC)"
+ flavor none
+ description "
+ NAND devices are subject to data failures that occur during
+ device operation. To ensure data read/write integrity, system
+ error checking and correction (ECC) algorithms should be
+ implemented. This component defines the using of ECC."
+
+ cdl_interface CYGINT_DEVS_FLASH_NAND_ECC {
+ display "Number of ECC variants in this configuration"
+ no_define
+ requires 1 == CYGINT_DEVS_FLASH_NAND_ECC
+ }
+
+ cdl_option CYGSEM_DEVS_FLASH_NAND_ECC_OFF {
+ display "No ECC algorithm"
+ default_value 0
+ implements CYGINT_DEVS_FLASH_NAND_ECC
+ description "
+ Don't use error checking and correction algorithm."
+ }
+
+ cdl_option CYGSEM_DEVS_FLASH_NAND_ECC_SOFT {
+ display "Software ECC algorithm"
+ default_value 1
+ implements CYGINT_DEVS_FLASH_NAND_ECC
+ description "
+ Use software error checking and correction algorithm which is
+ capable of single bit error correction and 2-bit random detection."
+ }
+ }
+
+ # Bad block management
+ cdl_component CYGPKG_DEVS_FLASH_NAND_BLOCKMANAGE {
+ display "Bad block management"
+ flavor none
+ description "
+ The NAND Flash devices may contain bad blocks, that shouldn't be
+ used. Additional bad blocks may develop during the lifetime
+ of the device. These blocks need to be managed using bad blocks
+ management. This component defines bad block management algorithm."
+
+ cdl_interface CYGINT_DEVS_FLASH_NAND_BLOCKMANAGE {
+ display "Number of bad block management algorithms in this configuration"
+ no_define
+ requires 1 == CYGINT_DEVS_FLASH_NAND_BLOCKMANAGE
+ }
+
+ cdl_option CYGSEM_DEVS_FLASH_NAND_BBM_INIT {
+ display "Initial bad blocks management"
+ default_value 0
+ implements CYGINT_DEVS_FLASH_NAND_BLOCKMANAGE
+ description "
+ Check only manufacturer marked bad blocks. NAND driver will
+ return error if application try to read/write/erase these blocks."
+ }
+
+ cdl_component CYGSEM_DEVS_FLASH_NAND_BBM_REPAIR {
+ display "Bad blocks management with repair area"
+ default_value 1
+ implements CYGINT_DEVS_FLASH_NAND_BLOCKMANAGE
+ description "
+ Simple bad block management. NAND driver reserves repair
+ area at the end of the flash and replace bad blocks in main
+ area with blocks from it. New bad blocks will be also replaced.
+ Management information resides in last not bad block."
+
+ cdl_option CYGNUM_DEVS_FLASH_NAND_BBM_REPAIR_SIZE {
+ display "Repair area blocks count"
+ flavor data
+ default_value 32
+ description "
+ Number of blocks in repair area. Usually it's equal 3%
+ of whole flash."
+ }
+ }
+ }
+
+ cdl_option CYGNUM_DEVS_FLASH_NAND_BUFFER_SIZE {
+ display "Size of buffer"
+ flavor data
+ default_value 1024
+ description "
+ Size of statically linked buffer. It is used for page data and
+ spare area buffer, for bad block table and etc."
+ }
+}
+
+# EOF nand_flash.cdl
diff -bur -P /opt/ecos-repo/cvs/ecos/packages/devs/flash/nand/current/ChangeLog ./devs/flash/nand/current/ChangeLog
--- /opt/ecos-repo/cvs/ecos/packages/devs/flash/nand/current/ChangeLog 1970-01-01 06:00:00.000000000 +0600
+++ ./devs/flash/nand/current/ChangeLog 2007-12-10 16:59:41.000000000 +0600
@@ -0,0 +1,43 @@
+2007-12-10 Alexey Shusharin <mrfinch@mail.ru>
+
+ * NAND Flash driver package created
+ * cdl/nand_flash.cdl
+ * doc/nand_flash.sgml
+ * include/nand_flash.h
+ * src/nand_flash_parts.inl
+ * src/nand_flash.c
+
+//===========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//===========================================================================
diff -bur -P /opt/ecos-repo/cvs/ecos/packages/devs/flash/nand/current/doc/nand_flash.sgml ./devs/flash/nand/current/doc/nand_flash.sgml
--- /opt/ecos-repo/cvs/ecos/packages/devs/flash/nand/current/doc/nand_flash.sgml 1970-01-01 06:00:00.000000000 +0600
+++ ./devs/flash/nand/current/doc/nand_flash.sgml 2007-12-10 16:58:46.000000000 +0600
@@ -0,0 +1,297 @@
+<!-- {{{ Banner -->
+
+<!-- =============================================================== -->
+<!-- -->
+<!-- nand_flash.sgml -->
+<!-- -->
+<!-- NAND Flash driver documentation. -->
+<!-- -->
+<!-- =============================================================== -->
+<!-- ####COPYRIGHTBEGIN#### -->
+<!-- -->
+<!-- =============================================================== -->
+<!-- Copyright (C) 2004 eCosCentric Limited -->
+<!-- This material may be distributed only subject to the terms -->
+<!-- and conditions set forth in the Open Publication License, v1.0 -->
+<!-- or later (the latest version is presently available at -->
+<!-- http://www.opencontent.org/openpub/) -->
+<!-- Distribution of the work or derivative of the work in any -->
+<!-- standard (paper) book form is prohibited unless prior -->
+<!-- permission obtained from the copyright holder -->
+<!-- =============================================================== -->
+<!-- -->
+<!-- ####COPYRIGHTEND#### -->
+<!-- =============================================================== -->
+<!-- #####DESCRIPTIONBEGIN#### -->
+<!-- -->
+<!-- Author(s): Alexey Shusharin -->
+<!-- Date: 2007/12/10 -->
+<!-- -->
+<!-- ####DESCRIPTIONEND#### -->
+<!-- =============================================================== -->
+
+<!-- }}} -->
+
+<PART id="devs-flash-nand"><title>NAND Flash Device Driver</title>
+
+<CHAPTER id="devs-flash-nand-support">
+<TITLE>Generic NAND Flash Device Driver</TITLE>
+
+<SECTION id="devs-flash-nand-support-overview">
+<TITLE>Overview</TITLE>
+
+<PARA>
+Generic NAND Flash driver feature:
+
+<variablelist>
+ <varlistentry>
+ <listitem><para>
+ - 8-bit NAND Flash devices with 256/512 page size support;
+ </para></listitem>
+
+ <listitem><para>
+ - error checking and correction algorithm support;
+ </para></listitem>
+
+ <listitem><para>
+ - bad block management support.
+ </para></listitem>
+ </varlistentry>
+</variablelist>
+
+</PARA>
+
+<PARA>
+ This driver is not compatible with Linux NAND Flash driver.
+ So if you use RedBoot to load Linux kernel, you cannot share
+ NAND Flash device with Linux.
+</PARA>
+
+</SECTION>
+
+<SECTION id="devs-flash-nand-support-config">
+<TITLE>Configuration options</TITLE>
+
+<PARA>
+Generic NAND Flash Device Driver has a number of configuration options.
+</PARA>
+
+<SECTION>
+<TITLE>cdl_component CYGPKG_DEVS_FLASH_NAND_ECC</TITLE>
+
+<PARA>
+ NAND devices are subject to data failures that occur during
+ device operation. To ensure data read/write integrity, system
+ error checking and correction (ECC) algorithms should be
+ implemented. This component defines the using of ECC.
+</PARA>
+
+<variablelist>
+ <varlistentry>
+ <term><type>cdl_option CYGSEM_DEVS_FLASH_NAND_ECC_OFF</type></term>
+ <listitem><para>
+ Don't use error checking and correction algorithm.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><type>cdl_option CYGSEM_DEVS_FLASH_NAND_ECC_SOFT</type></term>
+ <listitem><para>
+ Use software error checking and correction algorithm which is
+ capable of single bit error correction and 2-bit random detection.
+ </para></listitem>
+ </varlistentry>
+</variablelist>
+
+</SECTION>
+
+<SECTION>
+<TITLE>cdl_component CYGPKG_DEVS_FLASH_NAND_BLOCKMANAGE</TITLE>
+
+<PARA>
+ The NAND Flash devices may contain bad blocks, that shouldn't be
+ used. Additional bad blocks may develop during the lifetime
+ of the device. These blocks need to be managed using bad blocks
+ management. This component defines bad block management algorithm.
+</PARA>
+
+<variablelist>
+ <varlistentry>
+ <term><type>cdl_option CYGSEM_DEVS_FLASH_NAND_BBM_INIT</type></term>
+ <listitem><para>
+ Check only manufacturer marked bad blocks. NAND driver will
+ return error if application try to read/write/erase these blocks.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><type>cdl_component CYGSEM_DEVS_FLASH_NAND_BBM_REPAIR</type></term>
+ <listitem><para>
+ Simple bad block management. NAND driver reserves repair
+ area at the end of the flash and replace bad blocks in main
+ area with blocks from it. New bad blocks will be also replaced.
+ Management information resides in last not bad block.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><type>cdl_option CYGNUM_DEVS_FLASH_NAND_BBM_REPAIR_SIZE</type></term>
+ <listitem><para>
+ Number of blocks in repair area. Usually it's equal 3%
+ of whole flash.
+ </para></listitem>
+ </varlistentry>
+</variablelist>
+
+</SECTION>
+</SECTION>
+
+<SECTION id="devs-flash-nand-support-platform">
+<TITLE>Platform driver template</TITLE>
+
+<PARA>
+NAND Flash support is specific to a platform. Hence you should create a
+package with platform specific code. This is a template of such package.
+</PARA>
+
+<SECTION>
+<TITLE>Configuration file</TITLE>
+
+<PROGRAMLISTING>
+cdl_package CYGPKG_DEVS_FLASH_YOUR_PLATFORM {
+ display "YOUR PLATFORM NAND FLASH memory support"
+ description "NAND FLASH memory device support for ..."
+
+ include_dir cyg/io
+
+ parent CYGPKG_IO_FLASH
+ active_if CYGPKG_IO_FLASH
+
+ define_proc {
+ puts $::cdl_system_header "#define CYGDAT_DEVS_FLASH_NAND_PLF_INL <cyg/io/devs_flash_your_platform.inl>"
+ }
+
+ cdl_interface CYGINT_DEVS_FLASH_NAND_REQUIRED {
+ display "NAND FLASH driver required"
+ }
+
+ implements CYGINT_DEVS_FLASH_NAND_REQUIRED
+ implements CYGHWR_IO_FLASH_DEVICE
+}
+</PROGRAMLISTING>
+
+</SECTION>
+
+
+<SECTION>
+<TITLE>Source code file</TITLE>
+
+<PROGRAMLISTING>
+#include <cyg/hal/your_platform_misc.h>
+
+//--------------------------------------------------------------------------
+// Platform specific access to control-lines
+//--------------------------------------------------------------------------
+
+#define CYGHWR_FLASH_NAND_PLF_INIT nand_plf_init
+#define CYGHWR_FLASH_NAND_PLF_CE nand_plf_ce
+#define CYGHWR_FLASH_NAND_PLF_WP nand_plf_wp
+#define CYGHWR_FLASH_NAND_PLF_CMD nand_plf_cmd
+#define CYGHWR_FLASH_NAND_PLF_ADDR nand_plf_addr
+#define CYGHWR_FLASH_NAND_PLF_WAIT nand_plf_wait
+
+//--------------------------------------------------------------------------
+// Global variables
+//--------------------------------------------------------------------------
+
+// The device-specific data
+static cyg_nand_dev nand_device =
+{
+ .flash_base = (void*) YOUR_PLATFORM_FLASHBASE,
+ .addr_r = (void*) YOUR_PLATFORM_DATABASE,
+ .addr_w = (void*) YOUR_PLATFORM_DATABASE,
+
+ .delay_cmd = 1,
+ .delay_rst = 500,
+};
+
+//--------------------------------------------------------------------------
+// Init platform nand
+//--------------------------------------------------------------------------
+
+static inline void nand_plf_init(void)
+{
+ // Init NAND Flash platform stuff
+}
+
+//--------------------------------------------------------------------------
+// Enable/disable nand chip
+//--------------------------------------------------------------------------
+
+static inline void nand_plf_ce(int state)
+{
+ if(state)
+ {
+ // Enable CE line
+ }
+ else
+ {
+ // Disable CE line
+ }
+}
+
+//--------------------------------------------------------------------------
+// Enable/disable write protect
+//--------------------------------------------------------------------------
+
+static inline void nand_plf_wp(int nowrite)
+{
+ if(nowrite)
+ {
+ // Enable WP
+ }
+ else
+ {
+ // Disable WP
+ }
+}
+
+//--------------------------------------------------------------------------
+// Write nand command
+//--------------------------------------------------------------------------
+
+static inline void nand_plf_cmd(int cmd)
+{
+ // Enable CLE line
+ // Write command
+ // Disable CLE line
+}
+
+//--------------------------------------------------------------------------
+// Write nand address
+//--------------------------------------------------------------------------
+
+static inline void nand_plf_addr(int addr)
+{
+ // Enable ALE line
+ // Write address
+ // Disable ALE line
+}
+
+//--------------------------------------------------------------------------
+// Wait device ready pin
+//--------------------------------------------------------------------------
+
+static inline void nand_plf_wait(void)
+{
+ // Wait while device is not ready
+}
+
+//--------------------------------------------------------------------------
+</PROGRAMLISTING>
+
+</SECTION>
+
+
+</SECTION>
+
+</CHAPTER>
+
+</PART>
diff -bur -P /opt/ecos-repo/cvs/ecos/packages/devs/flash/nand/current/include/nand_flash.h ./devs/flash/nand/current/include/nand_flash.h
--- /opt/ecos-repo/cvs/ecos/packages/devs/flash/nand/current/include/nand_flash.h 1970-01-01 06:00:00.000000000 +0600
+++ ./devs/flash/nand/current/include/nand_flash.h 2007-12-07 20:05:52.000000000 +0600
@@ -0,0 +1,147 @@
+#ifndef _CYGONCE_FLASH_NAND_H_
+#define _CYGONCE_FLASH_NAND_H_
+//==========================================================================
+//
+// nand_flash.h
+//
+// FLASH memory - Support for NAND flash
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Alexey Shusharin <mrfinch@mail.ru>
+// Contributors:
+// Date: 2007-11-16
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/io/flash.h>
+
+#ifdef _FLASH_PRIVATE_
+
+//--------------------------------------------------------------------------
+// Defines
+
+#define NAND_REPAIR_SIZE (CYGNUM_DEVS_FLASH_NAND_BBM_REPAIR_SIZE)
+
+//--------------------------------------------------------------------------
+// NAND flash commands
+
+typedef enum
+{
+ NAND_CMD_READ0 = 0x00,
+ NAND_CMD_READ1 = 0x01,
+ NAND_CMD_PAGEPROG = 0x10,
+ NAND_CMD_READSPARE = 0x50,
+ NAND_CMD_ERASE = 0x60,
+ NAND_CMD_STATUS = 0x70,
+ NAND_CMD_SEQIN = 0x80,
+ NAND_CMD_READID = 0x90,
+ NAND_CMD_ERASE2 = 0xD0,
+} cyg_nand_command;
+
+typedef enum
+{
+ NAND_STATUS_FAIL = 0x01,
+ NAND_STATUS_READY = 0x40,
+ NAND_STATUS_NOWP = 0x80
+} cyg_nand_status;
+
+//--------------------------------------------------------------------------
+//
+
+typedef struct cyg_nand_partinfo_st
+{
+ cyg_uint32 id; // Device ID
+
+ cyg_uint32 page_size; // Page size in bytes.
+
+ cyg_uint32 pages_count; // Pages count in one block.
+ cyg_uint32 blocks_count; // Blocks count in chip.
+
+ cyg_uint32 options; // Flash options
+
+} cyg_nand_partinfo;
+
+//--------------------------------------------------------------------------
+// The device-specific data
+
+typedef struct cyg_nand_dev_st
+{
+ void* flash_base; // Flash base address
+
+ void* addr_r; // Address to read data from flash
+ void* addr_w; // Address to write data to flash
+
+ cyg_int32 delay_cmd; // Delay after command or address (in micro-seconds)
+ cyg_int32 delay_rst; // Delay after reset (in micro-seconds)
+
+ //-------------------------------
+
+ cyg_uint32 id;
+
+ cyg_uint32 page_size;
+ cyg_uint32 spare_size;
+
+ cyg_int32 pages_count;
+ cyg_int32 blocks_count;
+
+ int page_shift;
+ int block_shift;
+
+ cyg_uint8* buf_data; // Pointer to a data buffer
+ cyg_uint8* buf_spare; // Pointer to a spare buffer
+ cyg_uint8* buf_bbt; // Pointer to a bad block table
+
+ cyg_int32 pageinbuf; // Buffered page number (-1 if buffer is empty)
+
+#if defined(CYGSEM_DEVS_FLASH_NAND_BBM_REPAIR)
+
+ cyg_uint32 bbm_info; // Number of block with bbm info
+ cyg_int32 bbm_remap[NAND_REPAIR_SIZE];
+
+#endif /*CYGSEM_DEVS_FLASH_NAND_BBM_REPAIR*/
+
+} cyg_nand_dev;
+
+#endif // _FLASH_PRIVATE_
+
+#endif // _CYGONCE_FLASH_NAND_H_
+//--------------------------------------------------------------------------
+// EOF nand_flash.h
diff -bur -P /opt/ecos-repo/cvs/ecos/packages/devs/flash/nand/current/src/nand_flash.c ./devs/flash/nand/current/src/nand_flash.c
--- /opt/ecos-repo/cvs/ecos/packages/devs/flash/nand/current/src/nand_flash.c 1970-01-01 06:00:00.000000000 +0600
+++ ./devs/flash/nand/current/src/nand_flash.c 2007-12-10 14:11:31.000000000 +0600
@@ -0,0 +1,1305 @@
+//==========================================================================
+//
+// nand_flash.c
+//
+// FLASH memory - Support for NAND flash
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Alexey Shusharin <mrfinch@mail.ru>
+// Contributors:
+// Date: 2007-11-16
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/hal.h>
+#include <pkgconf/io_flash.h>
+#include <pkgconf/devs_flash_nand.h>
+
+#include <cyg/infra/cyg_type.h>
+
+#include <cyg/hal/hal_if.h>
+#include <cyg/hal/hal_io.h>
+
+#include <cyg/infra/diag.h>
+
+#include <string.h>
+
+//--------------------------------------------------------------------------
+// Flash includes
+
+// This driver supports only one device and only 8-bit
+#define CYGNUM_FLASH_INTERLEAVE (1)
+#define CYGNUM_FLASH_WIDTH (8)
+#define CYGNUM_FLASH_BLANK (1)
+
+#define _FLASH_PRIVATE_
+#include <cyg/io/flash.h>
+#include <cyg/io/flash_dev.h>
+#include <cyg/io/nand_flash.h>
+
+//--------------------------------------------------------------------------
+// NAND driver debug level
+// 0 - no debug message
+// 1 - only error messages
+// 2 - command level messages
+// 3 - hardware level messages
+
+#define NAND_DEBUG_LEVEL 1
+
+#if NAND_DEBUG_LEVEL == 3
+# define DEBUG_PRINT_ERR flash_info.pf
+# define DEBUG_PRINT_CMD flash_info.pf
+# define DEBUG_PRINT_HDW flash_info.pf
+#elif NAND_DEBUG_LEVEL == 2
+# define DEBUG_PRINT_ERR flash_info.pf
+# define DEBUG_PRINT_CMD flash_info.pf
+# define DEBUG_PRINT_HDW(fmt, ...)
+#elif NAND_DEBUG_LEVEL == 1
+# define DEBUG_PRINT_ERR flash_info.pf
+# define DEBUG_PRINT_CMD(fmt, ...)
+# define DEBUG_PRINT_HDW(fmt, ...)
+#else
+# define DEBUG_PRINT_ERR(fmt, ...)
+# define DEBUG_PRINT_CMD(fmt, ...)
+# define DEBUG_PRINT_HDW(fmt, ...)
+#endif
+
+//--------------------------------------------------------------------------
+// NAND data buffer
+static cyg_uint8 nand_buffer[CYGNUM_DEVS_FLASH_NAND_BUFFER_SIZE];
+
+#ifdef CYGSEM_DEVS_FLASH_NAND_BBM_REPAIR
+// Repair managemment id string
+static const char nand_bbm_id[32] = "Repair management table v1.0";
+#endif
+
+//--------------------------------------------------------------------------
+// Include NAND FLASH parts
+#include "nand_flash_parts.inl"
+
+//--------------------------------------------------------------------------
+// Include platform NAND FLASH definitions
+#include CYGDAT_DEVS_FLASH_NAND_PLF_INL
+
+// These platform functions is not obligatory
+#ifndef CYGHWR_FLASH_NAND_PLF_INIT
+# define CYGHWR_FLASH_NAND_PLF_INIT()
+#endif
+#ifndef CYGHWR_FLASH_NAND_PLF_CE
+# define CYGHWR_FLASH_NAND_PLF_CE(state)
+#endif
+#ifndef CYGHWR_FLASH_NAND_PLF_WP
+# define CYGHWR_FLASH_NAND_PLF_WP(state)
+#endif
+
+//--------------------------------------------------------------------------
+// Auxiliary functions
+//--------------------------------------------------------------------------
+
+static int nand_ffs(cyg_uint32 data)
+{
+ int res = 1;
+
+ if(!data) return 0;
+
+ if(data > 0xFFFF) {res += 16; data >>= 16;}
+ if(data > 0xFF) {res += 8; data >>= 8;}
+ if(data > 0x0F) {res += 4; data >>= 4;}
+ if(data > 0x03) {res += 2; data >>= 2;}
+ if(data > 0x01) res += 1;
+
+ return res;
+}
+
+//--------------------------------------------------------------------------
+// Hardware dependent functions
+//--------------------------------------------------------------------------
+
+static inline cyg_uint8 nand_read_byte(void)
+{
+ cyg_uint8 res;
+
+ HAL_READ_UINT8(nand_device.addr_r, res);
+
+ return res;
+}
+
+static inline void nand_read_buf(cyg_uint8* buf, cyg_uint32 len)
+{
+ cyg_uint32 i;
+
+ for(i = 0; i < len; i++)
+ {
+ HAL_READ_UINT8(nand_device.addr_r, buf[i]);
+ }
+}
+
+static inline void nand_write_buf(cyg_uint8* buf, cyg_uint32 len)
+{
+ cyg_uint32 i;
+
+ for(i = 0; i < len; i++)
+ {
+ HAL_WRITE_UINT8(nand_device.addr_w, buf[i]);
+ }
+}
+
+//--------------------------------------------------------------------------
+// ECC functions
+//--------------------------------------------------------------------------
+
+#if defined(CYGSEM_DEVS_FLASH_NAND_ECC_SOFT)
+
+static inline int nand_get_parity(int val)
+{
+ // Calc byte parity
+ val ^= (val >> 4);
+ val ^= (val >> 2);
+ val ^= (val >> 1);
+
+ return val & 1;
+}
+
+static cyg_uint32 nand_calc_ecc(cyg_uint8* data)
+{
+ int p_col, p_8, p_16, p_32, p_hi, tmp, block;
+ cyg_uint32 ecc;
+ int i;
+
+ p_col = p_8 = p_16 = p_32 = p_hi = 0;
+
+ // Calc bits parity
+ for(i = 0; i < 32; i++)
+ {
+ block = *data++;
+ tmp = *data++; block ^= tmp; p_8 ^= tmp;
+ tmp = *data++; block ^= tmp; p_16 ^= tmp;
+ tmp = *data++; block ^= tmp; p_8 ^= tmp; p_16 ^= tmp;
+ tmp = *data++; block ^= tmp; p_32 ^= tmp;
+ tmp = *data++; block ^= tmp; p_8 ^= tmp; p_32 ^= tmp;
+ tmp = *data++; block ^= tmp; p_16 ^= tmp; p_32 ^= tmp;
+ tmp = *data++; block ^= tmp; p_8 ^= tmp; p_16 ^= tmp; p_32 ^= tmp;
+
+ p_col ^= block;
+ if(nand_get_parity(block)) p_hi ^= i;
+ }
+
+ // Get ecc from parity values
+ ecc = p_hi << 6; // p_64 - p_1024
+ ecc |= nand_get_parity(p_32) << 5; // p_32
+ ecc |= nand_get_parity(p_16) << 4; // p_16
+ ecc |= nand_get_parity(p_8) << 3; // p_8
+ ecc |= nand_get_parity(p_col & 0xF0) << 2; // p_4
+ ecc |= nand_get_parity(p_col & 0xCC) << 1; // p_2
+ ecc |= nand_get_parity(p_col & 0xAA); // p_1
+
+ // If parity of whole array is even, first and second ecc parts are equal
+ // If it's odd, second part is equal to inverse of first part
+ if(nand_get_parity(p_col)) ecc |= (ecc ^ 0x7FF) << 11;
+ else ecc |= ecc << 11;
+
+ return ecc;
+}
+
+static int nand_check_ecc(cyg_uint8* data, cyg_uint32 ecc)
+{
+ cyg_uint32 err;
+ int err_cnt = 0;
+
+ // Calc ecc and get error info
+ ecc = (ecc & 0x3FFFFF) ^ nand_calc_ecc(data);
+
+ // Count errors
+ for(err = ecc; err; err >>= 1) err_cnt += err & 1;
+
+ // Check errors
+ if(err_cnt < 2)
+ {
+ // No error or 1 bit error in ecc area => nothing to repair
+ return 1;
+ }
+ else if(err_cnt == 11)
+ {
+ // This is 1 bit error in data area => repair this bit
+ data[(ecc & 0x7FF) >> 3] ^= (1 << (ecc & 7));
+
+ return 1;
+ }
+
+ return 0;
+}
+
+#endif
+
+//--------------------------------------------------------------------------
+// NAND command
+//--------------------------------------------------------------------------
+
+static void nand_command(int cmd, cyg_int32 column, cyg_int32 page_addr)
+{
+ if(cmd == NAND_CMD_SEQIN)
+ {
+ // Set data pointer to page beginning
+ CYGHWR_FLASH_NAND_PLF_CMD(NAND_CMD_READ0);
+ }
+
+ // Write NAND command
+ CYGHWR_FLASH_NAND_PLF_CMD(cmd);
+
+ // Write column number if needed
+ if(column >= 0)
+ {
+ CYGHWR_FLASH_NAND_PLF_ADDR(column);
+ }
+
+ // Write page address if needed
+ if(page_addr >= 0)
+ {
+ CYGHWR_FLASH_NAND_PLF_ADDR(page_addr & 0xFF);
+ CYGHWR_FLASH_NAND_PLF_ADDR(page_addr >> 8);
+ }
+
+ if(cmd == NAND_CMD_ERASE)
+ {
+ CYGHWR_FLASH_NAND_PLF_CMD(NAND_CMD_ERASE2);
+ }
+
+ // Delay after command and address
+ CYGACC_CALL_IF_DELAY_US(nand_device.delay_cmd);
+}
+
+//--------------------------------------------------------------------------
+// NAND erase block
+//--------------------------------------------------------------------------
+
+static int nand_erase_block(cyg_int32 page_addr)
+{
+ int status, res = FLASH_ERR_OK;
+
+ DEBUG_PRINT_HDW("Erase block %p - ", page_addr);
+
+ CYGHWR_FLASH_NAND_PLF_CE(1);
+ CYGHWR_FLASH_NAND_PLF_WP(0);
+
+ // Erase block
+ nand_command(NAND_CMD_ERASE, -1, page_addr);
+ CYGHWR_FLASH_NAND_PLF_WAIT();
+
+ // Read operation status and check it
+ nand_command(NAND_CMD_STATUS, -1, -1);
+ status = nand_read_byte();
+
+ CYGHWR_FLASH_NAND_PLF_WP(1);
+ CYGHWR_FLASH_NAND_PLF_CE(0);
+
+ if(!(status & NAND_STATUS_READY)) res = FLASH_ERR_DRV_TIMEOUT;
+ else if(!(status & NAND_STATUS_NOWP)) res = FLASH_ERR_PROTECT;
+ else if(status & NAND_STATUS_FAIL) res = FLASH_ERR_ERASE;
+
+ if(res == FLASH_ERR_OK) DEBUG_PRINT_HDW("Succeed\n");
+ else DEBUG_PRINT_HDW("Failed (status = 0x%X)\n", status);
+
+ return res;
+}
+
+//--------------------------------------------------------------------------
+// NAND read page
+//--------------------------------------------------------------------------
+
+static int nand_read_page(cyg_int32 page_addr, cyg_uint8* data,
+ cyg_uint8* spare)
+{
+ cyg_nand_dev* dev = &nand_device;
+
+ DEBUG_PRINT_HDW("Read page %p - ", page_addr);
+
+ CYGHWR_FLASH_NAND_PLF_CE(1);
+
+ // Write Read0 command and address
+ nand_command(NAND_CMD_READ0, 0x00, page_addr);
+
+ // Wait device ready pin
+ CYGHWR_FLASH_NAND_PLF_WAIT();
+
+ // Read data and spare fields
+ nand_read_buf(data, dev->page_size);
+ nand_read_buf(spare, dev->spare_size);
+
+ CYGHWR_FLASH_NAND_PLF_CE(0);
+
+#if defined(CYGSEM_DEVS_FLASH_NAND_ECC_SOFT)
+
+ // Don't look at the result of nand_check_ecc(),
+ // we should read the page in any case
+ if(dev->page_size == 256)
+ {
+ nand_check_ecc(data, spare[0] | (spare[1] << 8) | (spare[2] << 16));
+ }
+ else if(dev->page_size == 512)
+ {
+ nand_check_ecc(data, spare[0] | (spare[1] << 8) | (spare[2] << 16));
+ nand_check_ecc(data + 256, spare[3] | (spare[6] << 8) | (spare[7] << 16));
+ }
+ else
+ {
+ DEBUG_PRINT_HDW("Unknown page size\n");
+ return FLASH_ERR_HWR;
+ }
+
+#endif
+
+ DEBUG_PRINT_HDW("Succeed\n");
+
+ return FLASH_ERR_OK;
+}
+
+//--------------------------------------------------------------------------
+// NAND write page
+//--------------------------------------------------------------------------
+
+static int nand_write_page(cyg_int32 page_addr, cyg_uint8* data,
+ cyg_uint8* spare)
+{
+ cyg_nand_dev* dev = &nand_device;
+ int status, res = FLASH_ERR_OK;
+
+#if defined(CYGSEM_DEVS_FLASH_NAND_ECC_SOFT)
+ cyg_uint32 ecc;
+#endif
+
+ DEBUG_PRINT_HDW("Program page %p - ", page_addr);
+
+ // Fill spare area
+ memset(spare, 0xFF, dev->spare_size);
+
+#if defined(CYGSEM_DEVS_FLASH_NAND_ECC_SOFT)
+
+ if(dev->page_size == 256)
+ {
+ ecc = nand_calc_ecc(data);
+ spare[0] = ecc & 0xFF;
+ spare[1] = (ecc >> 8) & 0xFF;
+ spare[2] = (ecc >> 16) & 0xFF;
+ }
+ else if(dev->page_size == 512)
+ {
+ ecc = nand_calc_ecc(data);
+ spare[0] = ecc & 0xFF;
+ spare[1] = (ecc >> 8) & 0xFF;
+ spare[2] = (ecc >> 16) & 0xFF;
+
+ ecc = nand_calc_ecc(data + 256);
+ spare[3] = ecc & 0xFF;
+ spare[6] = (ecc >> 8) & 0xFF;
+ spare[7] = (ecc >> 16) & 0xFF;
+ }
+ else
+ {
+ DEBUG_PRINT_HDW("Unknown page size\n");
+ return FLASH_ERR_HWR;
+ }
+
+#endif
+
+ CYGHWR_FLASH_NAND_PLF_CE(1);
+ CYGHWR_FLASH_NAND_PLF_WP(0);
+
+ // Write data and spare fields
+ nand_command(NAND_CMD_SEQIN, 0x00, page_addr);
+ nand_write_buf(data, dev->page_size);
+ nand_write_buf(spare, dev->spare_size);
+
+ // Programm page
+ nand_command(NAND_CMD_PAGEPROG, -1, -1);
+ CYGHWR_FLASH_NAND_PLF_WAIT();
+
+ // Read operation status and check it
+ nand_command(NAND_CMD_STATUS, -1, -1);
+ status = nand_read_byte();
+
+ CYGHWR_FLASH_NAND_PLF_WP(1);
+ CYGHWR_FLASH_NAND_PLF_CE(0);
+
+ if(!(status & NAND_STATUS_READY)) res = FLASH_ERR_DRV_TIMEOUT;
+ else if(!(status & NAND_STATUS_NOWP)) res = FLASH_ERR_PROTECT;
+ else if(status & NAND_STATUS_FAIL) res = FLASH_ERR_PROGRAM;
+
+ if(res == FLASH_ERR_OK) DEBUG_PRINT_HDW("Succeed\n");
+ else DEBUG_PRINT_HDW("Failed (status = 0x%X)\n", status);
+
+ return res;
+}
+
+//--------------------------------------------------------------------------
+// Check block
+//--------------------------------------------------------------------------
+
+static inline int nand_bbm_isbad(cyg_int32 block)
+{
+ return nand_device.buf_bbt[block >> 3] & (1 << (block & 0x07));
+}
+
+//--------------------------------------------------------------------------
+// Mark block as bad
+//--------------------------------------------------------------------------
+
+static inline void nand_bbm_markbad(cyg_int32 block)
+{
+ nand_device.buf_bbt[block >> 3] |= 1 << (block & 0x07);
+}
+
+//--------------------------------------------------------------------------
+// Check manufacturer bad block marker
+//--------------------------------------------------------------------------
+
+static int nand_bbm_checkmarker(cyg_int32 block)
+{
+ cyg_nand_dev* dev = &nand_device;
+ cyg_int32 page_addr;
+ int res = 0;
+
+ dev->pageinbuf = -1;
+ page_addr = block << dev->block_shift;
+
+ // Read first page spare area
+ CYGHWR_FLASH_NAND_PLF_CE(1);
+
+ nand_command(NAND_CMD_READSPARE, 0x00, page_addr);
+ CYGHWR_FLASH_NAND_PLF_WAIT();
+ nand_read_buf(dev->buf_spare, dev->spare_size);
+
+ CYGHWR_FLASH_NAND_PLF_CE(0);
+
+ if(dev->buf_spare[0x05] != 0xFF) res = 1;
+ else
+ {
+ // Read second page spare area
+ CYGHWR_FLASH_NAND_PLF_CE(1);
+
+ nand_command(NAND_CMD_READSPARE, 0x00, page_addr + 1);
+ CYGHWR_FLASH_NAND_PLF_WAIT();
+ nand_read_buf(dev->buf_spare, dev->spare_size);
+
+ CYGHWR_FLASH_NAND_PLF_CE(0);
+
+ if(dev->buf_spare[0x05] != 0xFF) res = 1;
+ }
+
+ return res;
+}
+
+//--------------------------------------------------------------------------
+// Load bad block management info
+// TODO: Work with different endian format
+//--------------------------------------------------------------------------
+
+#if defined(CYGSEM_DEVS_FLASH_NAND_BBM_REPAIR)
+
+static int nand_bbm_load(cyg_int32 block)
+{
+ cyg_nand_dev* dev = &nand_device;
+ cyg_int32 page_addr;
+ cyg_uint32 info[2];
+ cyg_uint32 i, len, size;
+ int res;
+
+ DEBUG_PRINT_CMD("Load bbm info from %d block\n", block);
+
+ dev->pageinbuf = -1;
+ page_addr = block << dev->block_shift;
+
+ // Read first page in this block
+ res = nand_read_page(page_addr++, dev->buf_data, dev->buf_spare);
+ if(res != FLASH_ERR_OK)
+ {
+ DEBUG_PRINT_CMD("Load bbm: Page read error\n");
+ return res;
+ }
+
+ memcpy(info, &dev->buf_data[sizeof(nand_bbm_id)], sizeof(info));
+
+ // Check id string, device id and repair area size
+ if(strncmp((char*) dev->buf_data, nand_bbm_id, sizeof(nand_bbm_id)) != 0 ||
+ info[0] != dev->id || info[1] != NAND_REPAIR_SIZE)
+ {
+ DEBUG_PRINT_CMD("Load bbm: This is not bbm info block\n");
+ return FLASH_ERR_HWR;
+ }
+
+ // We found management info => Read remap table (next pages)
+ i = 0; len = NAND_REPAIR_SIZE * sizeof(cyg_int32);
+ while(i < len)
+ {
+ size = len - i;
+ if(size > dev->page_size) size = dev->page_size;
+
+ res = nand_read_page(page_addr++, dev->buf_data, dev->buf_spare);
+ if(res != FLASH_ERR_OK)
+ {
+ DEBUG_PRINT_CMD("Load bbm: Page read error\n");
+ return res;
+ }
+
+ memcpy(((cyg_uint8*) dev->bbm_remap) + i, dev->buf_data, size);
+ i += size;
+ }
+
+ DEBUG_PRINT_CMD("Load bbm: Succeed\n");
+ return FLASH_ERR_OK;
+}
+
+#endif /*CYGSEM_DEVS_FLASH_NAND_BBM_REPAIR*/
+
+//--------------------------------------------------------------------------
+// Save bad block management info
+// TODO: Work with different endian format
+//--------------------------------------------------------------------------
+
+#if defined(CYGSEM_DEVS_FLASH_NAND_BBM_REPAIR)
+
+static int nand_bbm_save(cyg_int32 block)
+{
+ cyg_nand_dev* dev = &nand_device;
+ cyg_int32 page_addr;
+ cyg_uint32 info[2];
+ cyg_uint32 i, len, size;
+ int res;
+
+ DEBUG_PRINT_CMD("Save bbm info to %d block\n", block);
+
+ dev->pageinbuf = -1;
+ page_addr = block << dev->block_shift;
+
+ // Erase block
+ res = nand_erase_block(page_addr);
+ if(res != FLASH_ERR_OK)
+ {
+ DEBUG_PRINT_CMD("Save bbm: Erase error\n");
+ return res;
+ }
+
+ // Copy id string, device id and repair area size
+ info[0] = dev->id; info[1] = NAND_REPAIR_SIZE;
+ memcpy(&dev->buf_data[0], nand_bbm_id, sizeof(nand_bbm_id));
+ memcpy(&dev->buf_data[sizeof(nand_bbm_id)], info, sizeof(info));
+
+ res = nand_write_page(page_addr++, dev->buf_data, dev->buf_spare);
+ if(res != FLASH_ERR_OK)
+ {
+ DEBUG_PRINT_CMD("Save bbm: Page program error\n");
+ return res;
+ }
+
+ // Save remap table (next pages)
+ i = 0; len = NAND_REPAIR_SIZE * sizeof(cyg_int32);
+ while(i < len)
+ {
+ size = len - i;
+ if(size > dev->page_size) size = dev->page_size;
+
+ memcpy(dev->buf_data, ((cyg_uint8*) dev->bbm_remap) + i, size);
+ memset(&dev->buf_data[size], 0xFF, dev->page_size - size);
+
+ res = nand_write_page(page_addr++, dev->buf_data, dev->buf_spare);
+ if(res != FLASH_ERR_OK)
+ {
+ DEBUG_PRINT_CMD("Save bbm: Page program error\n");
+ return res;
+ }
+
+ i += size;
+ }
+
+ DEBUG_PRINT_CMD("Save bbm: Succeed\n");
+ return FLASH_ERR_OK;
+}
+
+#endif /*CYGSEM_DEVS_FLASH_NAND_BBM_REPAIR*/
+
+//--------------------------------------------------------------------------
+// Remap bad block
+//--------------------------------------------------------------------------
+
+#if defined(CYGSEM_DEVS_FLASH_NAND_BBM_REPAIR)
+
+static cyg_int32 nand_bbm_remap(cyg_int32 block)
+{
+ cyg_nand_dev* dev = &nand_device;
+ cyg_int32 first, virtual;
+ int i;
+
+ DEBUG_PRINT_CMD("Remap %d block\n", block);
+
+ // Mark block as bad in bad block table
+ nand_bbm_markbad(block);
+
+ // Number of first block in repair area
+ first = dev->blocks_count - NAND_REPAIR_SIZE;
+
+ // Bad block in repair area?
+ if(block >= first)
+ {
+ // Get virtual block number and mark block as bad in remap table
+ virtual = dev->bbm_remap[block - first];
+ dev->bbm_remap[block - first] = block;
+ }
+ else virtual = block;
+
+ // Find free block in remap area
+ for(i = 0; i < NAND_REPAIR_SIZE; i++)
+ if(dev->bbm_remap[i] < 0) break;
+
+ if(i >= NAND_REPAIR_SIZE)
+ {
+ DEBUG_PRINT_CMD("Remap: No free blocks in repair area\n");
+ return -1;
+ }
+
+ // Remap bad block
+ dev->bbm_remap[i] = virtual;
+
+ // Return repair block number
+ block = first + i;
+
+ DEBUG_PRINT_CMD("Remap: Remapped to %d block\n", block);
+ return block;
+}
+
+#endif /*CYGSEM_DEVS_FLASH_NAND_BBM_REPAIR*/
+
+//--------------------------------------------------------------------------
+// Init bad block management data
+//--------------------------------------------------------------------------
+
+static int nand_bbm_init(void)
+{
+ cyg_nand_dev* dev = &nand_device;
+
+#if defined(CYGSEM_DEVS_FLASH_NAND_BBM_INIT)
+
+ cyg_int32 block;
+ int bbcount = 0;
+
+ DEBUG_PRINT_CMD("Scan manufacture marked bad blocks\n");
+
+ // Mark all blocks as good
+ memset(dev->buf_bbt, 0x00, dev->blocks_count / 8);
+
+ // Scan manufacture marked bad blocks
+ for(block = 0; block < dev->blocks_count; block++)
+ if(nand_bbm_checkmarker(block))
+ {
+ nand_bbm_markbad(block);
+ bbcount++;
+ }
+
+ DEBUG_PRINT_CMD("Scan: found %d bad blocks\n", bbcount);
+
+ return FLASH_ERR_OK;
+
+#elif defined(CYGSEM_DEVS_FLASH_NAND_BBM_REPAIR)
+
+ cyg_int32 block, first;
+ int i, res;
+
+ DEBUG_PRINT_CMD("Init bbm info\n");
+
+ // Mark all blocks as good
+ memset(dev->buf_bbt, 0x00, dev->blocks_count / 8);
+
+ // Find last not bad block in the flash
+ dev->bbm_info = dev->blocks_count - 1;
+ for(i = 0; i < NAND_REPAIR_SIZE; i++, dev->bbm_info--)
+ if(!nand_bbm_checkmarker(dev->bbm_info)) break;
+
+ // If there are no good blocks => return false
+ if(i >= NAND_REPAIR_SIZE)
+ {
+ DEBUG_PRINT_CMD("Init bbm: No good blocks in repair area\n");
+ return FLASH_ERR_HWR;
+ }
+
+ first = dev->blocks_count - NAND_REPAIR_SIZE;
+
+ // Try to load bad block management info
+ if(nand_bbm_load(dev->bbm_info) == FLASH_ERR_OK)
+ {
+ // Restore bad block table from remap table:
+ // If block in remap area is free, it is less than 0
+ // else it contains bad block number which it remaps
+ // If this block is bad, it contains its own number
+ for(i = 0; i < NAND_REPAIR_SIZE; i++)
+ if(dev->bbm_remap[i] >= 0)
+ {
+ DEBUG_PRINT_CMD("Remap table: Block %d is remapped to %d\n",
+ dev->bbm_remap[i], first + i);
+ nand_bbm_markbad(dev->bbm_remap[i]);
+ }
+
+ DEBUG_PRINT_CMD("Init bbm: Succeed\n");
+ return FLASH_ERR_OK;
+ }
+
+ // Load failed, try to create bad block management info
+ DEBUG_PRINT_CMD("Init bbm: Load failed. Try to create bbm info.\n");
+
+ // Check blocks in repair area
+ block = first;
+ for(i = 0; i < NAND_REPAIR_SIZE; i++, block++)
+ {
+ if(!nand_bbm_checkmarker(block)) dev->bbm_remap[i] = -1;
+ else dev->bbm_remap[i] = block;
+ }
+
+ // Mark block with management info as bad
+ dev->bbm_remap[dev->bbm_info - first] = dev->bbm_info;
+
+ // Scan bad blocks and remap its
+ for(block = 0; block < first; block++)
+ if(nand_bbm_checkmarker(block))
+ if(nand_bbm_remap(block) < 0)
+ {
+ DEBUG_PRINT_CMD("Init bbm: Repair area is too small\n");
+ return FLASH_ERR_HWR;
+ }
+
+ // Save bad block management info
+ res = nand_bbm_save(dev->bbm_info);
+
+ if(res == FLASH_ERR_OK) DEBUG_PRINT_CMD("Init bbm: Succeed\n");
+ else DEBUG_PRINT_CMD("Init bbm: Cannot save bbm info\n");
+
+ return res;
+
+#else
+ #error Unknown bad block management type
+#endif
+}
+
+//--------------------------------------------------------------------------
+// Get real page number (or return -1 if there are no such page)
+//--------------------------------------------------------------------------
+
+static cyg_int32 nand_bbm_getpage(cyg_int32 page_addr)
+{
+ cyg_nand_dev* dev = &nand_device;
+
+#if defined(CYGSEM_DEVS_FLASH_NAND_BBM_INIT)
+
+ cyg_int32 block;
+
+ // If there are no such block or it's bad => return -1
+ block = page_addr >> dev->block_shift;
+ if((block >= dev->blocks_count) || nand_bbm_isbad(block)) return -1;
+
+ return page_addr;
+
+#elif defined(CYGSEM_DEVS_FLASH_NAND_BBM_REPAIR)
+
+ int i;
+ cyg_int32 block, first;
+
+ // First block in repair area
+ first = dev->blocks_count - NAND_REPAIR_SIZE;
+
+ // If there are no such block => return -1
+ block = page_addr >> dev->block_shift;
+ if(block >= first) return -1;
+
+ // If block is not bad return initial page address
+ if(!nand_bbm_isbad(block)) return page_addr;
+
+ // Block is bad => look up to remap table
+ for(i = 0; i < NAND_REPAIR_SIZE; i++)
+ if(dev->bbm_remap[i] == block)
+ return ((first + i) << dev->block_shift) |
+ (page_addr & (dev->pages_count - 1));
+
+ // This bad block is not remapped
+ return -1;
+
+#else
+ #error Unknown bad block management type
+#endif
+}
+
+//--------------------------------------------------------------------------
+// Erase failed handler
+//--------------------------------------------------------------------------
+
+static cyg_int32 nand_bbm_erasefailed(cyg_int32 page_addr)
+{
+ cyg_nand_dev* dev = &nand_device;
+
+#if defined(CYGSEM_DEVS_FLASH_NAND_BBM_INIT)
+
+ DEBUG_PRINT_CMD("Erase fail handler\n");
+
+ // Mark this block as bad
+ nand_bbm_markbad(page_addr >> dev->block_shift);
+ return -1;
+
+#elif defined(CYGSEM_DEVS_FLASH_NAND_BBM_REPAIR)
+
+ cyg_int32 bad, replacer;
+ int res;
+
+ DEBUG_PRINT_CMD("Erase fail handler\n");
+
+ // Get bad block
+ replacer = bad = page_addr >> dev->block_shift;
+
+ // Do while there are blocks in repair area
+ while((replacer = nand_bbm_remap(replacer)) >= 0)
+ {
+ // Try to erase gotten block
+ res = nand_erase_block(replacer << dev->block_shift);
+ if(res == FLASH_ERR_ERASE) continue;
+ else if(res != FLASH_ERR_OK) return -1;
+
+ // Save changed bad block managenent info
+ nand_bbm_save(dev->bbm_info);
+
+ // Return new page address
+ return (replacer << dev->block_shift) |
+ (page_addr & (dev->pages_count - 1));
+ }
+
+ // There are no blocks in repair area
+ // Don't save bbm info, because it could be caused from hardware error
+ return -1;
+
+#else
+ #error Unknown bad block management type
+#endif
+}
+
+//--------------------------------------------------------------------------
+// Program failed handler
+//--------------------------------------------------------------------------
+
+static cyg_int32 nand_bbm_progfailed(cyg_int32 page_addr)
+{
+ cyg_nand_dev* dev = &nand_device;
+
+#if defined(CYGSEM_DEVS_FLASH_NAND_BBM_INIT)
+
+ DEBUG_PRINT_CMD("Program fail handler\n");
+
+ // Mark this block as bad
+ nand_bbm_markbad(page_addr >> dev->block_shift);
+ return -1;
+
+#elif defined(CYGSEM_DEVS_FLASH_NAND_BBM_REPAIR)
+
+ cyg_int32 bad, replacer;
+ cyg_int32 page_err, page_i;
+ cyg_uint32 i;
+ int res;
+
+ DEBUG_PRINT_CMD("Program fail handler\n");
+
+ // Get bad block
+ replacer = bad = page_addr >> dev->block_shift;
+
+ // Do while there are blocks in repair area
+ while((replacer = nand_bbm_remap(replacer)) >= 0)
+ {
+ // Try to erase gotten block
+ res = nand_erase_block(replacer << dev->block_shift);
+ if(res == FLASH_ERR_ERASE) continue;
+ else if(res != FLASH_ERR_OK) return -1;
+
+ // Reset page buffer
+ dev->pageinbuf = -1;
+
+ // Try to copy all not 0xFF pages to gotten block
+ page_err = page_addr & (dev->pages_count - 1);
+ for(page_i = 0; page_i < dev->pages_count; page_i++)
+ {
+ // Don't copy error page
+ if(page_i == page_err) continue;
+
+ // Read next page from bad block. If error => skip the page
+ res = nand_read_page((bad << dev->block_shift) | page_i,
+ dev->buf_data, dev->buf_spare);
+ if(res != FLASH_ERR_OK) continue;
+
+ // Check page content. If all bytes are 0xFF => skip the page
+ for(i = 0; i < dev->page_size; i++)
+ if(dev->buf_data[i] != 0xFF) break;
+
+ if(i >= dev->page_size) continue;
+
+ // Write page to replace block. If error => return error
+ res = nand_write_page((replacer << dev->block_shift) | page_i,
+ dev->buf_data, dev->buf_spare);
+ if(res != FLASH_ERR_OK) return -1;
+ }
+
+ // Save changed bad block managenent info
+ nand_bbm_save(dev->bbm_info);
+
+ // Return new page address
+ return (replacer << dev->block_shift) | page_err;
+ }
+
+ // There are no blocks in repair area
+ // Don't save bbm info, because it could be caused from hardware error
+ return -1;
+
+#else
+ #error Unknown bad block management type
+#endif
+}
+
+//--------------------------------------------------------------------------
+// Flash Query
+//--------------------------------------------------------------------------
+
+void flash_query(void* data)
+{
+ cyg_uint32* ids = (cyg_uint32*) data;
+
+ DEBUG_PRINT_CMD("Query NAND flash ids\n");
+
+ CYGHWR_FLASH_NAND_PLF_CE(1);
+
+ // TODO: Reset flash
+
+
+ // Get manuf and device ids
+ nand_command(NAND_CMD_READID, 0x00, -1);
+ ids[0] = nand_read_byte();
+ ids[1] = nand_read_byte();
+
+ CYGHWR_FLASH_NAND_PLF_CE(0);
+
+ DEBUG_PRINT_CMD("Query: Manuf ID = 0x%X, Device ID = 0x%X\n", ids[0], ids[1]);
+}
+
+//--------------------------------------------------------------------------
+// Initialize driver
+//--------------------------------------------------------------------------
+
+int flash_hwr_init(void)
+{
+ cyg_nand_dev* dev = &nand_device;
+ int i, buflen, total;
+ cyg_uint32 ids[2];
+
+ DEBUG_PRINT_CMD("Initialize NAND flash\n");
+
+ // Call platform nand init function
+ CYGHWR_FLASH_NAND_PLF_INIT();
+
+ // Get flash ids
+ flash_query((void*) ids);
+
+ // Look up supported device
+ for(i = 0; i < NAND_SUPPORTED_COUNT; i++)
+ if(nand_supported[i].id == ids[1]) break;
+
+ // if we didn't find the device return error
+ if(i >= NAND_SUPPORTED_COUNT)
+ {
+ DEBUG_PRINT_ERR("NAND_ERR: driver doesn't support "
+ "0x%X device ID\n", ids[1]);
+ return FLASH_ERR_DRV_WRONG_PART;
+ }
+
+ // Copy device info
+ dev->id = ids[1];
+ dev->page_size = nand_supported[i].page_size;
+ dev->spare_size = dev->page_size / 32;
+ dev->pages_count = nand_supported[i].pages_count;
+ dev->blocks_count = nand_supported[i].blocks_count;
+
+ dev->page_shift = nand_ffs(dev->page_size - 1);
+ dev->block_shift = nand_ffs(dev->pages_count - 1);
+
+ // Check data buffer length
+ buflen = dev->page_size + dev->spare_size + dev->blocks_count / 8;
+ if(buflen > sizeof(nand_buffer))
+ {
+ DEBUG_PRINT_ERR("NAND_ERR: driver doesn't have enough buffer. "
+ "This flash needs at least %d bytes buffer\n", buflen);
+ return FLASH_ERR_DRV_WRONG_PART;
+ }
+
+ // Allocate buffers
+ dev->buf_data = &nand_buffer[0];
+ dev->buf_spare = &nand_buffer[dev->page_size];
+ dev->buf_bbt = &nand_buffer[dev->page_size + dev->spare_size];
+
+ // No page in buffer
+ dev->pageinbuf = -1;
+
+ // Fill in device details
+#if defined(CYGSEM_DEVS_FLASH_NAND_BBM_INIT)
+ flash_info.blocks = dev->blocks_count;
+#elif defined(CYGSEM_DEVS_FLASH_NAND_BBM_REPAIR)
+ flash_info.blocks = dev->blocks_count - NAND_REPAIR_SIZE;
+#else
+ #error Unknown bad block management type
+#endif
+
+ flash_info.block_size = dev->page_size * dev->pages_count;
+ total = flash_info.block_size * flash_info.blocks;
+ flash_info.start = dev->flash_base;
+ flash_info.end = (void *)(((unsigned int) dev->flash_base) + total);
+
+ // Init bad block management
+ if(nand_bbm_init() != FLASH_ERR_OK)
+ {
+ DEBUG_PRINT_ERR("NAND_ERR: Bad block management "
+ "initialisation is failed\n");
+ return FLASH_ERR_HWR;
+ }
+
+ DEBUG_PRINT_CMD("Init NAND: Succeed (found %dMB flash)\n",
+ flash_info.block_size * dev->blocks_count / 0x100000);
+ return FLASH_ERR_OK;
+}
+
+//--------------------------------------------------------------------------
+// Erase Block
+//--------------------------------------------------------------------------
+
+int flash_erase_block(void* block, unsigned int size)
+{
+ cyg_nand_dev* dev = &nand_device;
+ cyg_int32 flash_addr, page_addr;
+ int res;
+
+ DEBUG_PRINT_CMD("Erase %d bytes from %p\n", size, block);
+
+ // Get flash addresses
+ flash_addr = (unsigned int) block - (unsigned int) dev->flash_base;
+ page_addr = nand_bbm_getpage(flash_addr >> dev->page_shift);
+ if(page_addr < 0) return FLASH_ERR_INVALID;
+
+ res = nand_erase_block(page_addr);
+ if(res != FLASH_ERR_ERASE) return res;
+
+ // Handle bad block error
+ if(nand_bbm_erasefailed(page_addr) < 0) return res;
+
+ return FLASH_ERR_OK;
+}
+
+//--------------------------------------------------------------------------
+// Program Buffer
+//--------------------------------------------------------------------------
+
+int flash_program_buf(void* addr, void* data, int len)
+{
+ cyg_nand_dev* dev = &nand_device;
+ cyg_int32 flash_addr, column, page_addr;
+ int count, res;
+
+ DEBUG_PRINT_CMD("Program %d bytes to %p\n", len, addr);
+
+ // Get flash addresses
+ flash_addr = (unsigned int) addr - (unsigned int) dev->flash_base;
+ column = flash_addr & (dev->page_size - 1);
+ page_addr = nand_bbm_getpage(flash_addr >> dev->page_shift);
+ if(page_addr < 0) return FLASH_ERR_INVALID;
+
+ while(len > 0)
+ {
+ // Should we program the whole page?
+ if(column == 0 && len >= dev->page_size)
+ {
+ // Reset buffer if we program the same page
+ if(page_addr == dev->pageinbuf) dev->pageinbuf = -1;
+
+ // Write from user buffer, skip unnecessary copying
+ // It is useful then we are writing a large block of data
+ count = dev->page_size;
+ res = nand_write_page(page_addr, data, dev->buf_spare);
+ }
+ else
+ {
+ // Reset buffer
+ dev->pageinbuf = -1;
+
+ count = dev->page_size - column;
+ if(count > len) count = len;
+
+ // Copy data to the device buffer
+ memset(dev->buf_data, 0xFF, dev->page_size);
+ memcpy(&dev->buf_data[column], data, count);
+
+ // Write page
+ res = nand_write_page(page_addr, dev->buf_data, dev->buf_spare);
+ }
+
+ // Check program result
+ if(res == FLASH_ERR_PROGRAM)
+ {
+ // Handle bad block error
+ page_addr = nand_bbm_progfailed(page_addr);
+ if(page_addr < 0) return FLASH_ERR_PROGRAM;
+
+ // Try program this data to new page
+ // Other pages in the block has been copied by nand_bbm_progfailed()
+ continue;
+ }
+ else if(res != FLASH_ERR_OK) return res;
+
+ // Next page
+ len -= count; page_addr++; column = 0;
+ data = (void*) ((cyg_uint8*) data + count);
+ }
+
+ return FLASH_ERR_OK;
+}
+
+//--------------------------------------------------------------------------
+// Read data into buffer
+//--------------------------------------------------------------------------
+
+int flash_read_buf(void* addr, void* data, int len)
+{
+ cyg_nand_dev* dev = &nand_device;
+ cyg_int32 flash_addr, column, page_addr;
+ int count, res;
+
+ DEBUG_PRINT_CMD("Read %d bytes from %p\n", len, addr);
+
+ // Get flash addresses
+ flash_addr = (unsigned int) addr - (unsigned int) dev->flash_base;
+ column = flash_addr & (dev->page_size - 1);
+ page_addr = nand_bbm_getpage(flash_addr >> dev->page_shift);
+ if(page_addr < 0) return FLASH_ERR_INVALID;
+
+ while(len > 0)
+ {
+ if(page_addr != dev->pageinbuf && column == 0 && len >= dev->page_size)
+ {
+ // We should read the whole page not from buffer
+ // Read to user buffer, skip unnecessary copying
+ // It is useful then we are reading a large block of data
+ res = nand_read_page(page_addr, data, dev->buf_spare);
+ if(res != FLASH_ERR_OK) return res;
+
+ count = dev->page_size;
+ }
+ else
+ {
+ if(page_addr != dev->pageinbuf)
+ {
+ // Read page to the device buffer
+ res = nand_read_page(page_addr, dev->buf_data, dev->buf_spare);
+ if(res != FLASH_ERR_OK) return res;
+
+ dev->pageinbuf = page_addr;
+ }
+
+ count = dev->page_size - column;
+ if(count > len) count = len;
+
+ // Copy data from device buffer to user buffer
+ memcpy(data, &dev->buf_data[column], count);
+
+ // Next read operation start in beginning of page
+ column = 0;
+ }
+
+ len -= count; page_addr++;
+ data = (void*) ((cyg_uint8*) data + count);
+ }
+
+ return FLASH_ERR_OK;
+}
+
+//--------------------------------------------------------------------------
+// Format flash
+//--------------------------------------------------------------------------
+
+int flash_format(int all)
+{
+ cyg_nand_dev* dev = &nand_device;
+ cyg_int32 i;
+
+ if(all)
+ {
+ DEBUG_PRINT_CMD("Format NAND Flash. Erase all blocks.\n");
+
+ // Erase all blocks except manufacture marked bad blocks
+ for(i = 0; i < dev->blocks_count; i++)
+ if(!nand_bbm_checkmarker(i))
+ nand_erase_block(i << dev->block_shift);
+ }
+#if defined(CYGSEM_DEVS_FLASH_NAND_BBM_REPAIR)
+ else
+ {
+ DEBUG_PRINT_CMD("Format NAND Flash. Erase only bbm info block.\n");
+
+ // Erase only bbm info block
+ nand_erase_block(dev->bbm_info << dev->block_shift);
+ }
+#endif
+
+ // Init bbm info
+ return nand_bbm_init();
+}
+
+//--------------------------------------------------------------------------
+// Map a hardware status to a package error
+//--------------------------------------------------------------------------
+
+int flash_hwr_map_error(int e)
+{
+ return e;
+}
+
+//--------------------------------------------------------------------------
+// See if a range of FLASH addresses overlaps currently running code
+//--------------------------------------------------------------------------
+
+bool flash_code_overlaps(void *start, void *end)
+{
+ // Currently running code cannot be in NAND FLASH
+ return 0;
+}
+
+//--------------------------------------------------------------------------
+// EOF nand_flash.c
diff -bur -P /opt/ecos-repo/cvs/ecos/packages/devs/flash/nand/current/src/nand_flash_parts.inl ./devs/flash/nand/current/src/nand_flash_parts.inl
--- /opt/ecos-repo/cvs/ecos/packages/devs/flash/nand/current/src/nand_flash_parts.inl 1970-01-01 06:00:00.000000000 +0600
+++ ./devs/flash/nand/current/src/nand_flash_parts.inl 2007-12-05 16:51:22.000000000 +0600
@@ -0,0 +1,84 @@
+#ifndef _CYGONCE_FLASH_NAND_PARTS_INL_
+#define _CYGONCE_FLASH_NAND_PARTS_INL_
+//==========================================================================
+//
+// nand_flash_parts.inl
+//
+// FLASH memory - NAND flash parts descriptions
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Alexey Shusharin <mrfinch@mail.ru>
+// Contributors:
+// Date: 2007-11-16
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+static const cyg_nand_partinfo nand_supported[] =
+{
+ // Device ID Page size Pages count Blocks count Options
+ { 0x6E, 256, 16, 256, 0 }, //1MB
+ { 0x64, 256, 16, 512, 0 }, //2MB
+ { 0x6B, 512, 16, 512, 0 }, //4MB
+ { 0xE8, 256, 16, 256, 0 }, //1MB
+ { 0xEC, 256, 16, 256, 0 }, //1MB
+ { 0xEA, 256, 16, 512, 0 }, //2MB
+ { 0xD5, 512, 16, 512, 0 }, //4MB
+ { 0xE3, 512, 16, 512, 0 }, //4MB
+ { 0xE5, 512, 16, 512, 0 }, //4MB
+ { 0xD6, 512, 16, 1024, 0 }, //8MB
+ { 0x39, 512, 16, 1024, 0 }, //8MB
+ { 0xE6, 512, 16, 1024, 0 }, //8MB
+ { 0x33, 512, 32, 1024, 0 }, //16MB
+ { 0x73, 512, 32, 1024, 0 }, //16MB
+ { 0x35, 512, 32, 2048, 0 }, //32MB
+ { 0x75, 512, 32, 2048, 0 }, //32MB
+ { 0x36, 512, 32, 4096, 0 }, //64MB
+ { 0x76, 512, 32, 4096, 0 }, //64MB
+ { 0x78, 512, 32, 8192, 0 }, //128MB
+ { 0x39, 512, 32, 8192, 0 }, //128MB
+ { 0x79, 512, 32, 8192, 0 }, //128MB
+ { 0x71, 512, 32, 16384, 0 }, //256MB
+};
+
+#define NAND_SUPPORTED_COUNT (sizeof(nand_supported) / sizeof(cyg_nand_partinfo))
+
+#endif // _CYGONCE_FLASH_NAND_PARTS_INL_
+//--------------------------------------------------------------------------
+// EOF nand_flash_parts.inl
diff -bur -P /opt/ecos-repo/cvs/ecos/packages/ecos.db ./ecos.db
--- /opt/ecos-repo/cvs/ecos/packages/ecos.db 2007-12-10 18:07:53.000000000 +0600
+++ ./ecos.db 2007-12-10 18:10:10.000000000 +0600
@@ -6372,4 +6372,12 @@
description "Another Tiny HTTP server."
}
+package CYGPKG_DEVS_FLASH_NAND {
+ alias { "NAND FLASH memory support" nand_flash }
+ directory devs/flash/nand
+ script nand_flash.cdl
+ hardware
+ description "
+ This package provides a NAND FLASH memory device support."
+}