[U-Boot] [PATCH 0/4] Support NAND and OneNAND memories on the OMAP3 EVM

This patch series permits the OMAP3 EVM to select which set of NAND or OneNAND memory related commands to use, as a function of the detected bootstrap configuration.
In addition to the OMAP3-specific parts, it abstracts the selection of the environment's location so that the choice can be made at run-time, not just compile time. It also makes it possible to disable support for compiled-in u-boot commands.
In particular, the changes to memory types other than NAND and OneNAND will need some scrutiny, since I don't have a good way to test some of those systems, or even to compile them.
Josh Karabin (4): Support multiple CONFIG_ENV options in a single build. Support run-time disabling of NAND and OneNAND memories. Support run-time disabling of u-boot commands. Support NAND and OneNAND memories on the OMAP3 EVM.
board/omap3/evm/evm.c | 24 +++++++++++ board/omap3/evm/evm.h | 4 +- common/cmd_nvedit.c | 4 +- common/command.c | 43 +++++++++++-------- common/env_common.c | 64 ++++++++++++++++++++++++++--- common/env_dataflash.c | 25 ++++++++---- common/env_eeprom.c | 24 +++++++---- common/env_flash.c | 34 +++++++++++---- common/env_mgdisk.c | 23 +++++++---- common/env_nand.c | 61 ++++++++++++++++------------ common/env_nowhere.c | 20 +++++++-- common/env_nvram.c | 27 ++++++++---- common/env_onenand.c | 28 +++++++++---- common/env_sf.c | 21 ++++++--- cpu/arm_cortexa8/omap3/mem.c | 71 ++++++++++++++++++++------------ drivers/mtd/nand/nand.c | 10 ++++ drivers/mtd/onenand/onenand_uboot.c | 9 ++++ include/asm-arm/arch-omap3/sys_proto.h | 2 +- include/configs/omap3_evm.h | 4 ++ include/environment.h | 43 +++++++++++++++++++ include/nand.h | 1 + include/onenand_uboot.h | 1 + 22 files changed, 397 insertions(+), 146 deletions(-)

If only a single CONFIG_ENV constant is defined at build time, the location of the environment will correspond to that environment.
If multiple CONFIG_ENV constants are defined at build time, the environment will default to one of the locations, but the particular location is not defined. Mechanisms for selection will be provided in later patches.
Tested on an OMAP3 EVM with OneNAND memory. Review and testing is particularly needed for the remainder of the persistent memory types.
Signed-off-by: Josh Karabin gkarabin@vocollect.com --- common/cmd_nvedit.c | 4 +-- common/env_common.c | 64 +++++++++++++++++++++++++++++++++++++++++++---- common/env_dataflash.c | 25 ++++++++++++------ common/env_eeprom.c | 24 ++++++++++++------ common/env_flash.c | 34 ++++++++++++++++++------- common/env_mgdisk.c | 23 +++++++++++------ common/env_nand.c | 61 ++++++++++++++++++++++++++------------------- common/env_nowhere.c | 20 +++++++++++--- common/env_nvram.c | 27 ++++++++++++------- common/env_onenand.c | 28 +++++++++++++++------ common/env_sf.c | 21 ++++++++++----- include/environment.h | 43 ++++++++++++++++++++++++++++++++ 12 files changed, 275 insertions(+), 99 deletions(-)
diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index 3ee971a..bdb2013 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -543,9 +543,7 @@ int getenv_r (char *name, char *buf, unsigned len)
int do_saveenv (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { - extern char * env_name_spec; - - printf ("Saving Environment to %s...\n", env_name_spec); + printf ("Saving Environment to %s...\n", env_object_ptr->name_spec);
return (saveenv() ? 1 : 0); } diff --git a/common/env_common.c b/common/env_common.c index 6be3bb0..1c890cf 100644 --- a/common/env_common.c +++ b/common/env_common.c @@ -44,13 +44,17 @@ DECLARE_GLOBAL_DATA_PTR; #define DEBUGF(fmt,args...) #endif
-extern env_t *env_ptr; - -extern void env_relocate_spec (void); -extern uchar env_get_char_spec(int); +env_object_t *env_object_ptr = NULL;
static uchar env_get_char_init (int index);
+#ifdef ENV_IS_EMBEDDED +extern uchar environment[]; +env_t *env_ptr = (env_t *) (&environment[0]); +#else /* ! ENV_IS_EMBEDDED */ +env_t *env_ptr = 0; +#endif /* ENV_IS_EMBEDDED */ + /************************************************************************ * Default settings to be used when no valid environment is found */ @@ -156,7 +160,7 @@ static uchar env_get_char_init (int index) /* if crc was bad, use the default environment */ if (gd->env_valid) { - c = env_get_char_spec(index); + c = env_object_ptr->get_char_spec(index); } else { c = default_environment[index]; } @@ -261,7 +265,7 @@ void env_relocate (void) set_default_env(); } else { - env_relocate_spec (); + env_object_ptr->relocate_spec (); } gd->env_addr = (ulong)&(env_ptr->data);
@@ -310,3 +314,51 @@ int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf) return found; } #endif + +static void env_object_ptr_init(void) +{ + if (env_object_ptr) + return; + +#if defined(CONFIG_ENV_IS_IN_DATAFLASH) + env_object_ptr = &env_object_dataflash; +#elif defined(CONFIG_ENV_IS_IN_EEPROM) + env_object_ptr = &env_object_eeprom; +#elif defined(CONFIG_ENV_IS_IN_FLASH) + env_object_ptr = &env_object_flash; +#elif defined(CONFIG_ENV_IS_IN_MG_DISK) + env_object_ptr = &env_object_mgdisk; +#elif defined(CONFIG_ENV_IS_IN_NAND) + env_object_ptr = &env_object_nand; +#elif defined(CONFIG_ENV_IS_NOWHERE) + env_object_ptr = &env_object_nowhere; +#elif defined(CONFIG_ENV_IS_IN_NVRAM) + env_object_ptr = &env_object_nvram; +#elif defined(CONFIG_ENV_IS_IN_ONENAND) + env_object_ptr = &env_object_onenand; +#elif defined(CONFIG_ENV_IS_IN_SPI_FLASH) + env_object_ptr = &env_object_sf; +#else +#error "No environment object specified!" +#endif +} + +int env_init(void) +{ + env_object_ptr_init(); + + if (env_object_ptr) + return env_object_ptr->init(); + else + return 1; +} + +#ifdef CONFIG_CMD_SAVEENV +int saveenv(void) +{ + if (env_object_ptr) + return env_object_ptr->saveenv(); + else + return 1; +} +#endif diff --git a/common/env_dataflash.c b/common/env_dataflash.c index fed919e..d065358 100644 --- a/common/env_dataflash.c +++ b/common/env_dataflash.c @@ -25,10 +25,6 @@
DECLARE_GLOBAL_DATA_PTR;
-env_t *env_ptr = NULL; - -char * env_name_spec = "dataflash"; - extern int read_dataflash (unsigned long addr, unsigned long size, char *result); extern int write_dataflash (unsigned long addr_dest, unsigned long addr_src, @@ -38,7 +34,7 @@ extern uchar default_environment[]; /* extern int default_environment_size; */
-uchar env_get_char_spec (int index) +static uchar get_char_spec_dataflash (int index) { uchar c; read_dataflash(CONFIG_ENV_ADDR + index + offsetof(env_t,data), @@ -46,12 +42,12 @@ uchar env_get_char_spec (int index) return (c); }
-void env_relocate_spec (void) +static void relocate_spec_dataflash (void) { read_dataflash(CONFIG_ENV_ADDR, CONFIG_ENV_SIZE, (char *)env_ptr); }
-int saveenv(void) +static int saveenv_dataflash(void) { /* env must be copied to do not alter env structure in memory*/ unsigned char temp[CONFIG_ENV_SIZE]; @@ -65,11 +61,14 @@ int saveenv(void) * We are still running from ROM, so data use is limited * Use a (moderately small) buffer on the stack */ -int env_init(void) +static int init_dataflash(void) { ulong crc, len, new; unsigned off; uchar buf[64]; + + env_ptr = NULL; + if (gd->env_valid == 0){ AT91F_DataflashInit(); /* prepare for DATAFLASH read/write */
@@ -97,3 +96,13 @@ int env_init(void)
return (0); } + +env_object_t env_object_dataflash = { + "dataflash", + init_dataflash, + relocate_spec_dataflash, + get_char_spec_dataflash, +#if defined(CONFIG_CMD_SAVENV) + saveenv_dataflash, +#endif +}; diff --git a/common/env_eeprom.c b/common/env_eeprom.c index 1578d61..89fa801 100644 --- a/common/env_eeprom.c +++ b/common/env_eeprom.c @@ -31,11 +31,7 @@
DECLARE_GLOBAL_DATA_PTR;
-env_t *env_ptr = NULL; - -char * env_name_spec = "EEPROM"; - -uchar env_get_char_spec (int index) +static uchar get_char_spec_eeprom (int index) { uchar c;
@@ -46,7 +42,7 @@ uchar env_get_char_spec (int index) return (c); }
-void env_relocate_spec (void) +static void relocate_spec_eeprom (void) { eeprom_read (CONFIG_SYS_DEF_EEPROM_ADDR, CONFIG_ENV_OFFSET, @@ -54,7 +50,7 @@ void env_relocate_spec (void) CONFIG_ENV_SIZE); }
-int saveenv(void) +static int saveenv_eeprom(void) { return eeprom_write (CONFIG_SYS_DEF_EEPROM_ADDR, CONFIG_ENV_OFFSET, @@ -68,12 +64,14 @@ int saveenv(void) * We are still running from ROM, so data use is limited * Use a (moderately small) buffer on the stack */ -int env_init(void) +static int init_eeprom(void) { ulong crc, len, new; unsigned off; uchar buf[64];
+ env_ptr = NULL; + eeprom_init (); /* prepare for EEPROM read/write */
/* read old CRC */ @@ -103,3 +101,13 @@ int env_init(void)
return (0); } + +env_object_t env_object_eeprom = { + "EEPROM", + init_eeprom, + relocate_spec_eeprom, + get_char_spec_eeprom, +#if defined(CONFIG_CMD_SAVENV) + saveenv_eeprom, +#endif +}; diff --git a/common/env_flash.c b/common/env_flash.c index 00792cd..7233dcb 100644 --- a/common/env_flash.c +++ b/common/env_flash.c @@ -50,12 +50,9 @@ DECLARE_GLOBAL_DATA_PTR; # endif #endif
-char * env_name_spec = "Flash"; - #ifdef ENV_IS_EMBEDDED
extern uchar environment[]; -env_t *env_ptr = (env_t *)(&environment[0]);
#ifdef CMD_SAVEENV /* static env_t *flash_addr = (env_t *)(&environment[0]);-broken on ARM-wd-*/ @@ -64,7 +61,6 @@ static env_t *flash_addr = (env_t *)CONFIG_ENV_ADDR;
#else /* ! ENV_IS_EMBEDDED */
-env_t *env_ptr = (env_t *)CONFIG_ENV_ADDR; #ifdef CMD_SAVEENV static env_t *flash_addr = (env_t *)CONFIG_ENV_ADDR; #endif @@ -86,14 +82,14 @@ extern uchar default_environment[]; extern int default_environment_size;
-uchar env_get_char_spec (int index) +static uchar get_char_spec_flash (int index) { return ( *((uchar *)(gd->env_addr + index)) ); }
#ifdef CONFIG_ENV_ADDR_REDUND
-int env_init(void) +static int init_flash(void) { int crc1_ok = 0, crc2_ok = 0;
@@ -104,6 +100,12 @@ int env_init(void) ulong addr1 = (ulong)&(flash_addr->data); ulong addr2 = (ulong)&(flash_addr_new->data);
+#ifdef ENV_IS_EMBEDDED + env_ptr = (env_t *)(&environment[0]); +#else + env_ptr = (env_t *)CONFIG_ENV_ADDR; +#endif + crc1_ok = (crc32(0, flash_addr->data, ENV_SIZE) == flash_addr->crc); crc2_ok = (crc32(0, flash_addr_new->data, ENV_SIZE) == flash_addr_new->crc);
@@ -137,7 +139,7 @@ int env_init(void) }
#ifdef CMD_SAVEENV -int saveenv(void) +static int saveenv_flash(void) { char *saved_data = NULL; int rc = 1; @@ -244,7 +246,7 @@ Done:
#else /* ! CONFIG_ENV_ADDR_REDUND */
-int env_init(void) +static int init_flash(void) { if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) { gd->env_addr = (ulong)&(env_ptr->data); @@ -259,7 +261,7 @@ int env_init(void)
#ifdef CMD_SAVEENV
-int saveenv(void) +static int saveenv_flash(void) { int len, rc; ulong end_addr; @@ -331,7 +333,7 @@ int saveenv(void)
#endif /* CONFIG_ENV_ADDR_REDUND */
-void env_relocate_spec (void) +static void relocate_spec_flash (void) { #if !defined(ENV_IS_EMBEDDED) || defined(CONFIG_ENV_ADDR_REDUND) #ifdef CONFIG_ENV_ADDR_REDUND @@ -380,3 +382,15 @@ void env_relocate_spec (void) #endif #endif /* ! ENV_IS_EMBEDDED || CONFIG_ENV_ADDR_REDUND */ } + +env_object_t env_object_flash = { + "Flash", + init_flash, + relocate_spec_flash, + get_char_spec_flash, +#if defined(CMD_SAVEENV) + saveenv_flash +#elif defined(CONFIG_CMD_SAVENV) + NULL +#endif +}; diff --git a/common/env_mgdisk.c b/common/env_mgdisk.c index 363ee68..3a2e55f 100644 --- a/common/env_mgdisk.c +++ b/common/env_mgdisk.c @@ -31,18 +31,14 @@ extern uchar default_environment[]; extern int default_environment_size;
-char * env_name_spec = "MG_DISK"; - -env_t *env_ptr = 0; - DECLARE_GLOBAL_DATA_PTR;
-uchar env_get_char_spec(int index) +static uchar get_char_spec_mgdisk(int index) { return (*((uchar *) (gd->env_addr + index))); }
-void env_relocate_spec(void) +static void relocate_spec_mgdisk(void) { unsigned int err;
@@ -69,7 +65,7 @@ OUT: set_default_env(); }
-int saveenv(void) +static int saveenv_mgdisk(void) { unsigned int err;
@@ -82,11 +78,22 @@ int saveenv(void) return err; }
-int env_init(void) +static int init_mgdisk(void) { + env_ptr = 0; /* use default */ gd->env_addr = (ulong) & default_environment[0]; gd->env_valid = 1;
return 0; } + +env_object_t env_object_mgdisk = { + "MG_DISK", + init_mgdisk, + relocate_spec_mgdisk, + get_char_spec_mgdisk, +#if defined(CONFIG_CMD_SAVENV) + saveenv_mgdisk, +#endif +}; diff --git a/common/env_nand.c b/common/env_nand.c index 76569da..1ea0e77 100644 --- a/common/env_nand.c +++ b/common/env_nand.c @@ -65,25 +65,18 @@ int nand_legacy_rw (struct nand_chip* nand, int cmd, 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; #endif /* ENV_IS_EMBEDDED */
- /* local functions */ #if !defined(ENV_IS_EMBEDDED) -static void use_default(void); +static void use_default_nand(void); #endif
DECLARE_GLOBAL_DATA_PTR;
-uchar env_get_char_spec (int index) +static uchar get_char_spec_nand (int index) { return ( *((uchar *)(gd->env_addr + index)) ); } @@ -100,13 +93,15 @@ uchar env_get_char_spec (int index) * the SPL loads not only the U-Boot image from NAND but also the * environment. */ -int env_init(void) +static int init_nand(void) { #if defined(ENV_IS_EMBEDDED) size_t total; int crc1_ok = 0, crc2_ok = 0; env_t *tmp_env1, *tmp_env2;
+ env_ptr = (env_t *)(&environment[0]); + total = CONFIG_ENV_SIZE;
tmp_env1 = env_ptr; @@ -140,6 +135,7 @@ int env_init(void) else if (gd->env_valid == 2) env_ptr = tmp_env2; #else /* ENV_IS_EMBEDDED */ + env_ptr = 0; gd->env_addr = (ulong)&default_environment[0]; gd->env_valid = 1; #endif /* ENV_IS_EMBEDDED */ @@ -152,7 +148,7 @@ int env_init(void) * The legacy NAND code saved the environment in the first NAND device i.e., * nand_dev_desc + 0. This is also the behaviour using the new NAND code. */ -int writeenv(size_t offset, u_char *buf) +static int writeenv_nand(size_t offset, u_char *buf) { size_t end = offset + CONFIG_ENV_RANGE; size_t amount_saved = 0; @@ -181,7 +177,7 @@ int writeenv(size_t offset, u_char *buf) return 0; } #ifdef CONFIG_ENV_OFFSET_REDUND -int saveenv(void) +static int saveenv_nand(void) { size_t total; int ret = 0; @@ -204,7 +200,8 @@ int saveenv(void) return 1;
puts ("Writing to redundant Nand... "); - ret = writeenv(CONFIG_ENV_OFFSET_REDUND, (u_char *) env_ptr); + ret = writeenv_nand(CONFIG_ENV_OFFSET_REDUND, + (u_char *) env_ptr); } else { puts ("Erasing Nand...\n"); nand_erase_options.offset = CONFIG_ENV_OFFSET; @@ -212,7 +209,7 @@ int saveenv(void) return 1;
puts ("Writing to Nand... "); - ret = writeenv(CONFIG_ENV_OFFSET, (u_char *) env_ptr); + ret = writeenv_nand(CONFIG_ENV_OFFSET, (u_char *) env_ptr); } if (ret) { puts("FAILED!\n"); @@ -224,7 +221,7 @@ int saveenv(void) return ret; } #else /* ! CONFIG_ENV_OFFSET_REDUND */ -int saveenv(void) +static int saveenv_nand (void) { size_t total; int ret = 0; @@ -244,7 +241,7 @@ int saveenv(void)
puts ("Writing to Nand... "); total = CONFIG_ENV_SIZE; - if (writeenv(CONFIG_ENV_OFFSET, (u_char *) env_ptr)) { + if (writeenv_nand(CONFIG_ENV_OFFSET, (u_char *) env_ptr)) { puts("FAILED!\n"); return 1; } @@ -255,7 +252,7 @@ int saveenv(void) #endif /* CONFIG_ENV_OFFSET_REDUND */ #endif /* CMD_SAVEENV */
-int readenv (size_t offset, u_char * buf) +static int readenv_nand (size_t offset, u_char * buf) { size_t end = offset + CONFIG_ENV_RANGE; size_t amount_loaded = 0; @@ -284,7 +281,7 @@ int readenv (size_t offset, u_char * buf) }
#ifdef CONFIG_ENV_OFFSET_REDUND -void env_relocate_spec (void) +static void relocate_spec_nand (void) { #if !defined(ENV_IS_EMBEDDED) size_t total; @@ -296,9 +293,9 @@ void env_relocate_spec (void) tmp_env1 = (env_t *) malloc(CONFIG_ENV_SIZE); tmp_env2 = (env_t *) malloc(CONFIG_ENV_SIZE);
- if (readenv(CONFIG_ENV_OFFSET, (u_char *) tmp_env1)) + if (readenv_nand(CONFIG_ENV_OFFSET, (u_char *) tmp_env1)) puts("No Valid Environment Area Found\n"); - if (readenv(CONFIG_ENV_OFFSET_REDUND, (u_char *) tmp_env2)) + if (readenv_nand(CONFIG_ENV_OFFSET_REDUND, (u_char *) tmp_env2)) puts("No Valid Reundant Environment Area Found\n");
crc1_ok = (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc); @@ -307,7 +304,7 @@ void env_relocate_spec (void) if(!crc1_ok && !crc2_ok) { free(tmp_env1); free(tmp_env2); - return use_default(); + return use_default_nand(); } else if(crc1_ok && !crc2_ok) gd->env_valid = 1; else if(!crc1_ok && crc2_ok) @@ -343,25 +340,37 @@ void env_relocate_spec (void) * The legacy NAND code saved the environment in the first NAND device i.e., * nand_dev_desc + 0. This is also the behaviour using the new NAND code. */ -void env_relocate_spec (void) +static void relocate_spec_nand (void) { #if !defined(ENV_IS_EMBEDDED) int ret;
- ret = readenv(CONFIG_ENV_OFFSET, (u_char *) env_ptr); + ret = readenv_nand(CONFIG_ENV_OFFSET, (u_char *) env_ptr); if (ret) - return use_default(); + return use_default_nand();
if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc) - return use_default(); + return use_default_nand(); #endif /* ! ENV_IS_EMBEDDED */ } #endif /* CONFIG_ENV_OFFSET_REDUND */
#if !defined(ENV_IS_EMBEDDED) -static void use_default() +static void use_default_nand() { puts ("*** Warning - bad CRC or NAND, using default environment\n\n"); set_default_env(); } #endif + +env_object_t env_object_nand = { + "NAND", + init_nand, + relocate_spec_nand, + get_char_spec_nand, +#if defined(CMD_SAVEENV) + saveenv_nand, +#elif defined(CONFIG_CMD_SAVENV) + NULL, +#endif +}; diff --git a/common/env_nowhere.c b/common/env_nowhere.c index 78e8f8e..7df6570 100644 --- a/common/env_nowhere.c +++ b/common/env_nowhere.c @@ -31,17 +31,15 @@
DECLARE_GLOBAL_DATA_PTR;
-env_t *env_ptr = NULL; - extern uchar default_environment[]; extern int default_environment_size;
-void env_relocate_spec (void) +static void relocate_spec_nowhere (void) { }
-uchar env_get_char_spec (int index) +static uchar get_char_spec_nowhere (int index) { return ( *((uchar *)(gd->env_addr + index)) ); } @@ -51,10 +49,22 @@ uchar env_get_char_spec (int index) * * We are still running from ROM, so data use is limited */ -int env_init(void) +static int init_nowhere(void) { + env_ptr = NULL; + gd->env_addr = (ulong)&default_environment[0]; gd->env_valid = 0;
return (0); } + +env_object_t env_object_nowhere = { + NULL, + init_nowhere, + relocate_spec_nowhere, + get_char_spec_nowhere, +#if defined(CONFIG_CMD_SAVENV) + NULL, +#endif +}; diff --git a/common/env_nvram.c b/common/env_nvram.c index 562edd0..051fe49 100644 --- a/common/env_nvram.c +++ b/common/env_nvram.c @@ -50,18 +50,13 @@ DECLARE_GLOBAL_DATA_PTR; #ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE extern void *nvram_read(void *dest, const long src, size_t count); extern void nvram_write(long dest, const void *src, size_t count); -env_t *env_ptr = NULL; -#else -env_t *env_ptr = (env_t *)CONFIG_ENV_ADDR; #endif
-char * env_name_spec = "NVRAM"; - extern uchar default_environment[]; extern int default_environment_size;
#ifdef CONFIG_AMIGAONEG3SE -uchar env_get_char_spec (int index) +static uchar get_char_spec_nvram (int index) { #ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE uchar c; @@ -78,7 +73,7 @@ uchar env_get_char_spec (int index) #endif } #else -uchar env_get_char_spec (int index) +static uchar get_char_spec_nvram (int index) { #ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE uchar c; @@ -92,7 +87,7 @@ uchar env_get_char_spec (int index) } #endif
-void env_relocate_spec (void) +static void relocate_spec_nvram (void) { #if defined(CONFIG_SYS_NVRAM_ACCESS_ROUTINE) nvram_read(env_ptr, CONFIG_ENV_ADDR, CONFIG_ENV_SIZE); @@ -101,7 +96,7 @@ void env_relocate_spec (void) #endif }
-int saveenv (void) +static int saveenv_nvram (void) { int rcode = 0; #ifdef CONFIG_AMIGAONEG3SE @@ -126,7 +121,7 @@ int saveenv (void) * * We are still running from ROM, so data use is limited */ -int env_init (void) +static int init_nvram (void) { #ifdef CONFIG_AMIGAONEG3SE enable_nvram(); @@ -134,12 +129,14 @@ int env_init (void) #if defined(CONFIG_SYS_NVRAM_ACCESS_ROUTINE) ulong crc; uchar data[ENV_SIZE]; + env_ptr = NULL; nvram_read (&crc, CONFIG_ENV_ADDR, sizeof(ulong)); nvram_read (data, CONFIG_ENV_ADDR+sizeof(ulong), ENV_SIZE);
if (crc32(0, data, ENV_SIZE) == crc) { gd->env_addr = (ulong)CONFIG_ENV_ADDR + sizeof(long); #else + env_ptr = (env_t *)CONFIG_ENV_ADDR; if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) { gd->env_addr = (ulong)&(env_ptr->data); #endif @@ -153,3 +150,13 @@ int env_init (void) #endif return (0); } + +env_object_t env_object_nvram = { + "NVRAM", + init_nvram, + relocate_spec_nvram, + get_char_spec_nvram, +#if defined(CONFIG_CMD_SAVENV) + saveenv_nvram, +#endif +}; diff --git a/common/env_onenand.c b/common/env_onenand.c index dbccc79..867f345 100644 --- a/common/env_onenand.c +++ b/common/env_onenand.c @@ -39,24 +39,20 @@ extern uchar default_environment[];
#define ONENAND_ENV_SIZE(mtd) (mtd.writesize - 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 */
DECLARE_GLOBAL_DATA_PTR;
-uchar env_get_char_spec(int index) +static uchar get_char_spec_onenand(int index) { return (*((uchar *) (gd->env_addr + index))); }
-void env_relocate_spec(void) +static void relocate_spec_onenand(void) { unsigned long env_addr; int use_default = 0; @@ -87,7 +83,7 @@ void env_relocate_spec(void) gd->env_valid = 1; }
-int saveenv(void) +static int saveenv_onenand(void) { unsigned long env_addr = CONFIG_ENV_ADDR; struct erase_info instr = { @@ -116,11 +112,27 @@ int saveenv(void) return 0; }
-int env_init(void) +static int init_onenand(void) { +#ifdef ENV_IS_EMBEDDED + env_ptr = (env_t *) (&environment[0]); +#else /* ! ENV_IS_EMBEDDED */ + env_ptr = (env_t *) onenand_env; +#endif /* ENV_IS_EMBEDDED */ + /* use default */ gd->env_addr = (ulong) & default_environment[0]; gd->env_valid = 1;
return 0; } + +env_object_t env_object_onenand = { + "OneNAND", + init_onenand, + relocate_spec_onenand, + get_char_spec_onenand, +#ifdef CONFIG_CMD_SAVEENV + saveenv_onenand +#endif +}; diff --git a/common/env_sf.c b/common/env_sf.c index 2f52e25..fa7b8f2 100644 --- a/common/env_sf.c +++ b/common/env_sf.c @@ -49,17 +49,14 @@ DECLARE_GLOBAL_DATA_PTR; extern uchar default_environment[]; extern int default_environment_size;
-char * env_name_spec = "SPI Flash"; -env_t *env_ptr; - static struct spi_flash *env_flash;
-uchar env_get_char_spec(int index) +static uchar get_char_spec_sf(int index) { return *((uchar *)(gd->env_addr + index)); }
-int saveenv(void) +static int saveenv_sf(void) { u32 saved_size, saved_offset; char *saved_buffer = NULL; @@ -116,7 +113,7 @@ int saveenv(void) return ret; }
-void env_relocate_spec(void) +static void relocate_spec_sf(void) { int ret;
@@ -155,7 +152,7 @@ err_crc: gd->env_valid = 1; }
-int env_init(void) +static int init_sf(void) { /* SPI flash isn't usable before relocation */ gd->env_addr = (ulong)&default_environment[0]; @@ -163,3 +160,13 @@ int env_init(void)
return 0; } + +env_object_t env_object_sf = { + "SPI Flash", + init_sf, + relocate_spec_sf, + get_char_spec_sf, +#if defined(CONFIG_CMD_SAVENV) + saveenv_sf, +#endif +}; diff --git a/include/environment.h b/include/environment.h index 507e832..d9bf6be 100644 --- a/include/environment.h +++ b/include/environment.h @@ -119,6 +119,8 @@ typedef struct environment_s { unsigned char data[ENV_SIZE]; /* Environment data */ } env_t;
+extern env_t *env_ptr; + /* Function that returns a character from the environment */ unsigned char env_get_char (int);
@@ -132,4 +134,45 @@ void env_crc_update (void); /* [re]set to the default environment */ void set_default_env(void);
+/* Interface for implementing an environment */ +typedef struct environment_object { + char *name_spec; + int (*init)(void); + void (*relocate_spec)(void); + unsigned char (*get_char_spec)(int); +#ifdef CONFIG_CMD_SAVEENV + int (*saveenv)(void); +#endif +} env_object_t; + +extern env_object_t *env_object_ptr; + +#if defined(CONFIG_ENV_IS_IN_DATAFLASH) +extern env_object_t env_object_dataflash; +#endif +#if defined(CONFIG_ENV_IS_IN_EEPROM) +extern env_object_t env_object_eeprom; +#endif +#if defined(CONFIG_ENV_IS_IN_FLASH) +extern env_object_t env_object_flash; +#endif +#if defined(CONFIG_ENV_IS_IN_MG_DISK) +extern env_object_t env_object_mgdisk; +#endif +#if defined(CONFIG_ENV_IS_IN_NAND) +extern env_object_t env_object_nand; +#endif +#if defined(CONFIG_ENV_IS_NOWHERE) +extern env_object_t env_object_nowhere; +#endif +#if defined(CONFIG_ENV_IS_IN_NVRAM) +extern env_object_t env_object_nvram; +#endif +#if defined(CONFIG_ENV_IS_IN_ONENAND) +extern env_object_t env_object_onenand; +#endif +#if defined(CONFIG_ENV_IS_IN_SPI_FLASH) +extern env_object_t env_object_sf; +#endif + #endif /* _ENVIRONMENT_H_ */

Add "disable" functions that will prevent the initialization function of nand and onenand interfaces from completing.
These functions are intended to be called on boards that can be populated with one of multiple persistent memory types. Board initialization code must ensure that only the correct memory type is used by called the disable function(s) of memory types that are supported at run time, but aren't present on the board.
Signed-off-by: Josh Karabin gkarabin@vocollect.com --- drivers/mtd/nand/nand.c | 10 ++++++++++ drivers/mtd/onenand/onenand_uboot.c | 9 +++++++++ include/nand.h | 1 + include/onenand_uboot.h | 1 + 4 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/drivers/mtd/nand/nand.c b/drivers/mtd/nand/nand.c index d369115..59ba140 100644 --- a/drivers/mtd/nand/nand.c +++ b/drivers/mtd/nand/nand.c @@ -38,6 +38,7 @@ static ulong base_address[CONFIG_SYS_MAX_NAND_DEVICE] = CONFIG_SYS_NAND_BASE_LIS
static const char default_nand_name[] = "nand"; static __attribute__((unused)) char dev_name[CONFIG_SYS_MAX_NAND_DEVICE][8]; +static int nand_disabled = 0;
static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand, ulong base_addr) @@ -75,10 +76,19 @@ static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand,
}
+void nand_disable_init(void) +{ + nand_disabled = 1; +} + void nand_init(void) { int i; unsigned int size = 0; + + if (nand_disabled) + return; + for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) { nand_init_chip(&nand_info[i], &nand_chip[i], base_address[i]); size += nand_info[i].size / 1024; diff --git a/drivers/mtd/onenand/onenand_uboot.c b/drivers/mtd/onenand/onenand_uboot.c index a95b922..17bcd51 100644 --- a/drivers/mtd/onenand/onenand_uboot.c +++ b/drivers/mtd/onenand/onenand_uboot.c @@ -21,9 +21,18 @@ struct mtd_info onenand_mtd; struct onenand_chip onenand_chip; static __attribute__((unused)) char dev_name[] = "onenand0"; +static int onenand_disabled = 0; + +void onenand_disable_init(void) +{ + onenand_disabled = 1; +}
void onenand_init(void) { + if (onenand_disabled) + return; + memset(&onenand_mtd, 0, sizeof(struct mtd_info)); memset(&onenand_chip, 0, sizeof(struct onenand_chip));
diff --git a/include/nand.h b/include/nand.h index 065a42c..e8e21ef 100644 --- a/include/nand.h +++ b/include/nand.h @@ -24,6 +24,7 @@ #ifndef _NAND_H_ #define _NAND_H_
+extern void nand_disable_init(void); extern void nand_init(void);
#ifndef CONFIG_NAND_LEGACY diff --git a/include/onenand_uboot.h b/include/onenand_uboot.h index 49da9d0..a82213d 100644 --- a/include/onenand_uboot.h +++ b/include/onenand_uboot.h @@ -28,6 +28,7 @@ extern struct mtd_info onenand_mtd; extern void onenand_board_init(struct mtd_info *);
/* Functions */ +extern void onenand_disable_init(void); 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);

Change the command parsing code to ignore command table entries with NULL names. This makes it possible to disable a command (say, for a supported but not connected memory) at run time.
Signed-off-by: Josh Karabin gkarabin@vocollect.com --- common/command.c | 43 +++++++++++++++++++++++++------------------ 1 files changed, 25 insertions(+), 18 deletions(-)
diff --git a/common/command.c b/common/command.c index c9a3f5b..ef2cbfc 100644 --- a/common/command.c +++ b/common/command.c @@ -243,15 +243,19 @@ int _do_help (cmd_tbl_t *cmd_start, int cmd_items, cmd_tbl_t * cmdtp, int if (argc == 1) { /*show list of commands */ cmd_tbl_t *cmd_array[cmd_items]; int i, j, swaps; + int cmd_array_items;
/* Make array of commands from .uboot_cmd section */ cmdtp = cmd_start; - for (i = 0; i < cmd_items; i++) { - cmd_array[i] = cmdtp++; + for (i = 0, cmd_array_items = 0; i < cmd_items; i++) { + if (cmdtp->name) { + cmd_array[i] = cmdtp++; + cmd_array_items++; + } }
/* Sort command list (trivial bubble sort) */ - for (i = cmd_items - 1; i > 0; --i) { + for (i = cmd_array_items - 1; i > 0; --i) { swaps = 0; for (j = 0; j < i; ++j) { if (strcmp (cmd_array[j]->name, @@ -268,7 +272,7 @@ int _do_help (cmd_tbl_t *cmd_start, int cmd_items, cmd_tbl_t * cmdtp, int }
/* print short help (usage) */ - for (i = 0; i < cmd_items; i++) { + for (i = 0; i < cmd_array_items; i++) { const char *usage = cmd_array[i]->usage;
/* allow user abort */ @@ -298,7 +302,7 @@ int _do_help (cmd_tbl_t *cmd_start, int cmd_items, cmd_tbl_t * cmdtp, int } putc ('\n'); #else /* no long help available */ - if (cmdtp->usage) + if (cmdtp->name && cmdtp->usage) printf ("%s - %s\n", cmdtp->name, cmdtp->usage); #endif /* CONFIG_SYS_LONGHELP */ } else { @@ -365,7 +369,7 @@ cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len) for (cmdtp = table; cmdtp != table + table_len; cmdtp++) { - if (strncmp (cmd, cmdtp->name, len) == 0) { + if (cmdtp->name && (strncmp (cmd, cmdtp->name, len) == 0)) { if (len == strlen (cmdtp->name)) return cmdtp; /* full match */
@@ -453,7 +457,8 @@ static int complete_cmdv(int argc, char *argv[], char last_char, int maxv, char cmdv[n_found++] = "..."; break; } - cmdv[n_found++] = cmdtp->name; + if (cmdtp->name) + cmdv[n_found++] = cmdtp->name; } cmdv[n_found] = NULL; return n_found; @@ -483,20 +488,22 @@ static int complete_cmdv(int argc, char *argv[], char last_char, int maxv, char /* return the partial matches */ for (cmdtp = &__u_boot_cmd_start; cmdtp != &__u_boot_cmd_end; cmdtp++) {
- clen = strlen(cmdtp->name); - if (clen < len) - continue; + if (cmdtp->name) { + clen = strlen(cmdtp->name); + if (clen < len) + continue;
- if (memcmp(cmd, cmdtp->name, len) != 0) - continue; + if (memcmp(cmd, cmdtp->name, len) != 0) + continue;
- /* too many! */ - if (n_found >= maxv - 2) { - cmdv[n_found++] = "..."; - break; - } + /* too many! */ + if (n_found >= maxv - 2) { + cmdv[n_found++] = "..."; + break; + }
- cmdv[n_found++] = cmdtp->name; + cmdv[n_found++] = cmdtp->name; + } }
cmdv[n_found] = NULL;

This change detects the boot configuration of an OMAP3 device, and uses that information on OMAP3 EVM builds to support NAND or OneNAND.
Signed-off-by: Josh Karabin gkarabin@vocollect.com --- board/omap3/evm/evm.c | 24 +++++++++++ board/omap3/evm/evm.h | 4 +- cpu/arm_cortexa8/omap3/mem.c | 71 ++++++++++++++++++++------------ include/asm-arm/arch-omap3/sys_proto.h | 2 +- include/configs/omap3_evm.h | 4 ++ 5 files changed, 76 insertions(+), 29 deletions(-)
diff --git a/board/omap3/evm/evm.c b/board/omap3/evm/evm.c index c008c2e..e30e83f 100644 --- a/board/omap3/evm/evm.c +++ b/board/omap3/evm/evm.c @@ -34,6 +34,8 @@ #include <asm/arch/sys_proto.h> #include <i2c.h> #include <asm/mach-types.h> +#include <environment.h> +#include <command.h> #include "evm.h"
/* @@ -43,8 +45,30 @@ int board_init(void) { DECLARE_GLOBAL_DATA_PTR; +#if defined(CONFIG_ENV_IS_IN_ONENAND) && defined(CONFIG_ENV_IS_IN_NAND) + int flash_type; + cmd_tbl_t *cmdtp;
+ flash_type = gpmc_init(); /* in SRAM or SDRAM, finish GPMC */ + + switch (flash_type) { + case PISMO1_NAND: + env_object_ptr = &env_object_nand; + onenand_disable_init(); + cmdtp = find_cmd("onenand"); + cmdtp->name = NULL; + break; + case PISMO1_ONENAND: + env_object_ptr = &env_object_onenand; + nand_disable_init(); + cmdtp = find_cmd("nand"); + cmdtp->name = NULL; + break; + } +#else gpmc_init(); /* in SRAM or SDRAM, finish GPMC */ +#endif + /* board id for Linux */ gd->bd->bi_arch_number = MACH_TYPE_OMAP3EVM; /* boot param addr */ diff --git a/board/omap3/evm/evm.h b/board/omap3/evm/evm.h index 4a82a7f..938cdbf 100644 --- a/board/omap3/evm/evm.h +++ b/board/omap3/evm/evm.h @@ -26,7 +26,9 @@ const omap3_sysinfo sysinfo = { DDR_DISCRETE, "OMAP3 EVM board", -#if defined(CONFIG_ENV_IS_IN_ONENAND) +#if defined(CONFIG_ENV_IS_IN_ONENAND) && defined(CONFIG_ENV_IS_IN_NAND) + "OneNAND or NAND" +#elif defined(CONFIG_ENV_IS_IN_ONENAND) "OneNAND", #else "NAND", diff --git a/cpu/arm_cortexa8/omap3/mem.c b/cpu/arm_cortexa8/omap3/mem.c index 3cc22c4..004088d 100644 --- a/cpu/arm_cortexa8/omap3/mem.c +++ b/cpu/arm_cortexa8/omap3/mem.c @@ -30,6 +30,8 @@ #include <asm/arch/mem.h> #include <asm/arch/sys_proto.h> #include <command.h> +#include <onenand_uboot.h> +#include <nand.h>
/* * Only One NAND allowed on board at a time. @@ -218,7 +220,7 @@ void enable_gpmc_config(u32 *gpmc_config, gpmc_csx_t *gpmc_cs_base, u32 base, * Init GPMC for x16, MuxMode (SDRAM in x32). * This code can only be executed from SRAM or SDRAM. *****************************************************/ -void gpmc_init(void) +u32 gpmc_init(void) { /* putting a blanket check on GPMC based on ZeBu for now */ u32 *gpmc_config = NULL; @@ -229,6 +231,7 @@ void gpmc_init(void) u32 f_off = CONFIG_SYS_MONITOR_LEN; u32 f_sec = 0; u32 config = 0; + u32 b_type = 0;
/* global settings */ writel(0, &gpmc_base->irqenable); /* isr's sources masked */ @@ -245,40 +248,54 @@ void gpmc_init(void) writel(0, &gpmc_cs_base->config7); sdelay(1000);
+#if defined(CONFIG_CMD_NAND) || defined(CONFIG_CMD_ONENAND) + b_type = get_boot_type(); +#endif + #if defined(CONFIG_CMD_NAND) /* CS 0 */ - gpmc_config = gpmc_m_nand; - gpmc_cfg_base = gpmc_base; - nand_cs_base = (gpmc_csx_t *)(GPMC_CONFIG_CS0_BASE + + if (b_type == 0x1 || b_type == 0xc || b_type == 0xf || + b_type == 0x15 || b_type == 0x1b) { + gpmc_config = gpmc_m_nand; + gpmc_cfg_base = gpmc_base; + nand_cs_base = (gpmc_csx_t *)(GPMC_CONFIG_CS0_BASE + (GPMC_CS * GPMC_CONFIG_WIDTH)); - base = PISMO1_NAND_BASE; - size = PISMO1_NAND_SIZE; - enable_gpmc_config(gpmc_config, nand_cs_base, base, size); + base = PISMO1_NAND_BASE; + size = PISMO1_NAND_SIZE; + enable_gpmc_config(gpmc_config, nand_cs_base, base, size); #if defined(CONFIG_ENV_IS_IN_NAND) - f_off = SMNAND_ENV_OFFSET; - f_sec = SZ_128K; - /* env setup */ - boot_flash_base = base; - boot_flash_off = f_off; - boot_flash_sec = f_sec; - boot_flash_env_addr = f_off; + f_off = SMNAND_ENV_OFFSET; + f_sec = SZ_128K; + /* env setup */ + boot_flash_base = base; + boot_flash_off = f_off; + boot_flash_sec = f_sec; + boot_flash_env_addr = f_off; + + return PISMO1_NAND; + } #endif #endif
#if defined(CONFIG_CMD_ONENAND) - gpmc_config = gpmc_onenand; - onenand_cs_base = (gpmc_csx_t *)(GPMC_CONFIG_CS0_BASE + - (GPMC_CS * GPMC_CONFIG_WIDTH)); - base = PISMO1_ONEN_BASE; - size = PISMO1_ONEN_SIZE; - enable_gpmc_config(gpmc_config, onenand_cs_base, base, size); + if (b_type == 0x0 || b_type == 0x2 || b_type == 0x4 || b_type == 0x10 || + b_type == 0x16) { + gpmc_config = gpmc_onenand; + onenand_cs_base = (gpmc_csx_t *)(GPMC_CONFIG_CS0_BASE + + (GPMC_CS * GPMC_CONFIG_WIDTH)); + base = PISMO1_ONEN_BASE; + size = PISMO1_ONEN_SIZE; + enable_gpmc_config(gpmc_config, onenand_cs_base, base, size); #if defined(CONFIG_ENV_IS_IN_ONENAND) - f_off = ONENAND_ENV_OFFSET; - f_sec = SZ_128K; - /* env setup */ - boot_flash_base = base; - boot_flash_off = f_off; - boot_flash_sec = f_sec; - boot_flash_env_addr = f_off; + f_off = ONENAND_ENV_OFFSET; + f_sec = SZ_128K; + /* env setup */ + boot_flash_base = base; + boot_flash_off = f_off; + boot_flash_sec = f_sec; + boot_flash_env_addr = f_off; + + return PISMO1_ONENAND; + } #endif #endif } diff --git a/include/asm-arm/arch-omap3/sys_proto.h b/include/asm-arm/arch-omap3/sys_proto.h index 7361d08..63fb98e 100644 --- a/include/asm-arm/arch-omap3/sys_proto.h +++ b/include/asm-arm/arch-omap3/sys_proto.h @@ -33,7 +33,7 @@ void per_clocks_enable(void); void memif_init(void); void sdrc_init(void); void do_sdrc_init(u32, u32); -void gpmc_init(void); +u32 gpmc_init(void);
void watchdog_init(void); void set_muxconf_regs(void); diff --git a/include/configs/omap3_evm.h b/include/configs/omap3_evm.h index e205c01..b649808 100644 --- a/include/configs/omap3_evm.h +++ b/include/configs/omap3_evm.h @@ -112,6 +112,7 @@ #define CONFIG_CMD_I2C /* I2C serial bus support */ #define CONFIG_CMD_MMC /* MMC support */ #define CONFIG_CMD_ONENAND /* ONENAND support */ +#define CONFIG_CMD_NAND /* NAND support */ #define CONFIG_CMD_DHCP #define CONFIG_CMD_PING
@@ -130,12 +131,14 @@ /* * Board NAND Info. */ +#define CONFIG_NAND_OMAP_GPMC #define CONFIG_SYS_NAND_ADDR NAND_BASE /* physical address */ /* to access nand */ #define CONFIG_SYS_NAND_BASE NAND_BASE /* physical address */ /* to access */ /* nand at CS0 */
+#define GPMC_NAND_ECC_LP_x16_LAYOUT 1 #define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of */ /* NAND devices */
@@ -262,6 +265,7 @@ #define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_FLASH_BASE #define CONFIG_SYS_ONENAND_BASE ONENAND_MAP
+#define CONFIG_ENV_IS_IN_NAND 1 #define CONFIG_ENV_IS_IN_ONENAND 1 #define ONENAND_ENV_OFFSET 0x260000 /* environment starts here */ #define SMNAND_ENV_OFFSET 0x260000 /* environment starts here */
participants (1)
-
Josh Karabin