From 13a5695b7c454d5a2a5a885002cfe0e18536dad9 Mon Sep 17 00:00:00 2001 From: wdenk Date: Wed, 9 Jun 2004 14:58:14 +0000 Subject: [PATCH] Patch by Jian Zhang, 20 May 2004: add support for environment in NAND flash --- CHANGELOG | 3 + README | 10 +++ common/Makefile | 2 +- common/cmd_nand.c | 8 +-- common/cmd_nvedit.c | 1 + common/env_common.c | 3 + common/env_nand.c | 171 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 193 insertions(+), 5 deletions(-) create mode 100644 common/env_nand.c diff --git a/CHANGELOG b/CHANGELOG index b1bed0f90c..8dcf6bed99 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,9 @@ Changes since U-Boot 1.1.1: ====================================================================== +* Patch by Jian Zhang, 20 May 2004: + add support for environment in NAND flash + * Patch by Yuli Barcohen, 20 May 2004: Add support for Interphase iSPAN boards. diff --git a/README b/README index 21c7a5ce31..b197b1d57c 100644 --- a/README +++ b/README @@ -1827,6 +1827,16 @@ to save the current settings. environment area within the total memory of your DataFlash placed at the specified address. +- CFG_ENV_IS_IN_NAND: + + Define this if you have a NAND device which you want to use + for the environment. + + - CFG_ENV_OFFSET: + - CFG_ENV_SIZE: + + These two #defines specify the offset and size of the environment + area within the first NAND device. - CFG_SPI_INIT_OFFSET diff --git a/common/Makefile b/common/Makefile index 41ebabc2ed..4a36673b44 100644 --- a/common/Makefile +++ b/common/Makefile @@ -42,7 +42,7 @@ COBJS = main.o ACEX1K.o altera.o bedbug.o \ cmd_reginfo.o cmd_reiser.o cmd_scsi.o cmd_spi.o cmd_usb.o cmd_vfd.o \ command.o console.o devices.o dlmalloc.o docecc.o \ environment.o env_common.o \ - env_dataflash.o env_flash.o env_eeprom.o env_nvram.o env_nowhere.o exports.o \ + env_nand.o env_dataflash.o env_flash.o env_eeprom.o env_nvram.o env_nowhere.o exports.o \ flash.o fpga.o \ hush.o kgdb.o lists.o lynxkdi.o memsize.o miiphybb.o miiphyutil.o \ s_record.o soft_i2c.o soft_spi.o spartan2.o \ diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 4b693a999a..8d115eb267 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -70,10 +70,10 @@ struct nand_oob_config { * Function Prototypes */ static void nand_print(struct nand_chip *nand); -static int nand_rw (struct nand_chip* nand, int cmd, +int nand_rw (struct nand_chip* nand, int cmd, size_t start, size_t len, size_t * retlen, u_char * buf); -static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean); +int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean); static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len, size_t * retlen, u_char *buf, u_char *ecc_code); static int nand_write_ecc (struct nand_chip* nand, size_t to, size_t len, @@ -429,7 +429,7 @@ static void nand_print_bad(struct nand_chip* nand) * 3: NANDRW_READ | NANDRW_JFFS2 read, data all 0xff for bad blocks * 7: NANDRW_READ | NANDRW_JFFS2 | NANDRW_JFFS2_SKIP read, skip bad blocks */ -static int nand_rw (struct nand_chip* nand, int cmd, +int nand_rw (struct nand_chip* nand, int cmd, size_t start, size_t len, size_t * retlen, u_char * buf) { @@ -1304,7 +1304,7 @@ static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len, } -static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean) +int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean) { /* This is defined as a structure so it will work on any system * using native endian jffs2 (the default). diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index a3898dda0f..aaf6de902b 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -53,6 +53,7 @@ !defined(CFG_ENV_IS_IN_EEPROM) && \ !defined(CFG_ENV_IS_IN_FLASH) && \ !defined(CFG_ENV_IS_IN_DATAFLASH) && \ + !defined(CFG_ENV_IS_IN_NAND) && \ !defined(CFG_ENV_IS_NOWHERE) # error Define one of CFG_ENV_IS_IN_{NVRAM|EEPROM|FLASH|DATAFLASH|NOWHERE} #endif diff --git a/common/env_common.c b/common/env_common.c index 4aa043ef33..9be4cc1dbf 100644 --- a/common/env_common.c +++ b/common/env_common.c @@ -139,6 +139,9 @@ uchar default_environment[] = { "\0" }; +#if defined(CFG_ENV_IS_IN_NAND) /* Environment is in Nand Flash */ +int default_environment_size = sizeof(default_environment); +#endif void env_crc_update (void) { diff --git a/common/env_nand.c b/common/env_nand.c new file mode 100644 index 0000000000..2412b109d7 --- /dev/null +++ b/common/env_nand.c @@ -0,0 +1,171 @@ +/* + * (C) Copyright 2004 + * Jian Zhang, Texas Instruments, jzhang@ti.com. + + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH + * Andreas Heppel + + * 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 + */ + +/* #define DEBUG */ + +#include + +#if defined(CFG_ENV_IS_IN_NAND) /* Environment is in Nand Flash */ + +#include +#include +#include +#include +#include + +#if ((CONFIG_COMMANDS&(CFG_CMD_ENV|CFG_CMD_NAND)) == (CFG_CMD_ENV|CFG_CMD_NAND)) +#define CMD_SAVEENV +#endif + +#if defined(CFG_ENV_SIZE_REDUND) +#error CFG_ENV_SIZE_REDUND not supported yet +#endif + +#if defined(CFG_ENV_ADDR_REDUND) +#error CFG_ENV_ADDR_REDUND and CFG_ENV_IS_IN_NAND not supported yet +#endif + + +#ifdef CONFIG_INFERNO +#error CONFIG_INFERNO not supported yet +#endif + +/* references to names in cmd_nand.c */ +#define NANDRW_READ 0x01 +#define NANDRW_WRITE 0x00 +#define NANDRW_JFFS2 0x02 +extern struct nand_chip nand_dev_desc[]; +int nand_rw (struct nand_chip* nand, int cmd, + size_t start, size_t len, + size_t * retlen, u_char * buf); +int nand_erase(struct nand_chip* nand, size_t ofs, + size_t len, int clean); + +/* references to names in env_common.c */ +extern uchar default_environment[]; +extern int default_environment_size; + +char * env_name_spec = "NAND"; + + +#ifdef ENV_IS_EMBEDDED +extern uchar environment[]; +env_t *env_ptr = (env_t *)(&environment[0]); +#else /* ! ENV_IS_EMBEDDED */ +env_t *env_ptr = 0; //(env_t *)CFG_ENV_ADDR; +#endif /* ENV_IS_EMBEDDED */ + + +/* local functions */ +static void use_default(void); + + +uchar env_get_char_spec (int index) +{ + DECLARE_GLOBAL_DATA_PTR; + + return ( *((uchar *)(gd->env_addr + index)) ); +} + + +/* this is called before nand_init() + * so we can't read Nand to validate env data. + * Mark it OK for now. env_relocate() in env_common.c + * will call our relocate function which will does + * the real validation. + */ +int env_init(void) +{ + DECLARE_GLOBAL_DATA_PTR; + + gd->env_addr = (ulong)&default_environment[0]; + gd->env_valid = 1; + + return (0); +} + +#ifdef CMD_SAVEENV +int saveenv(void) +{ + int total, ret = 0; + puts ("Erasing Nand..."); + if (nand_erase(nand_dev_desc + 0, CFG_ENV_OFFSET, CFG_ENV_SIZE, 0)) + return 1; + + puts ("Writing to Nand... "); + ret = nand_rw(nand_dev_desc + 0, + NANDRW_WRITE | NANDRW_JFFS2, CFG_ENV_OFFSET, CFG_ENV_SIZE, + &total, (u_char*)env_ptr); + if (ret || total != CFG_ENV_SIZE) + return 1; + + puts ("done\n"); + return ret; +} +#endif /* CMD_SAVEENV */ + + +void env_relocate_spec (void) +{ +#if !defined(ENV_IS_EMBEDDED) + int ret, total; + + ret = nand_rw(nand_dev_desc + 0, + NANDRW_READ | NANDRW_JFFS2, CFG_ENV_OFFSET, CFG_ENV_SIZE, + &total, (u_char*)env_ptr); + if (ret || total != CFG_ENV_SIZE) + return use_default(); + + if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc) + return use_default(); +#endif /* ! ENV_IS_EMBEDDED */ + +} + +static void use_default() +{ + DECLARE_GLOBAL_DATA_PTR; + + puts ("*** Warning - bad CRC or NAND, using default environment\n\n"); + + if (default_environment_size > CFG_ENV_SIZE){ + puts ("*** Error - default environment is too large\n\n"); + return; + } + + memset (env_ptr, 0, sizeof(env_t)); + memcpy (env_ptr->data, + default_environment, + default_environment_size); + env_ptr->crc = crc32(0, env_ptr->data, ENV_SIZE); + gd->env_valid = 1; + +} + +#endif /* CFG_ENV_IS_IN_NAND */