omap3: single binary supporting all flash types
Subsystems (2)
Hi there!
currently it is not possible to build single working OMAP3 binary which enables more than one of these:CONFIG_NORCONFIG_NANDCONFIG_CMD_ONENAND
first problem lies in gpmc_init which configures CS[0] to one flash type determined at compile time. Another is that identify_nand_chip hang when trying to indentify chip which is not present. The same issue is with OneNAND mtd driver. And finally omap_gpmc:board_nand_init() searches for NAND specific configuration in gpmc config1 register - but that value is forced earlier from gpmc_init, making test completely pointless. Most of these issues are fixed with patches sent as reply to this message, but:
As we might want to use single binary also to boot from MMC or other sources, we cannot use boot_device to get a glue about used flash type. Also U-Boot should not count on being loaded by its own SPL. So, to make things easier to begin with, do we all agree that omap_gpmc:board_nand_init as well as its OneNAND counterpart should expect gpmc config1 register properly set and fail if something unexpected is found? That basically means if we should rely on CS0 config provided by first stage loader or try to rediscover flash devices (this problem does not exist when flash itself is boot source)
Thank you for your attention,
ladis
PATCH 1/1 armv7: add reset timeout to identify_nand_chip
identify_nand_chip hangs forever in loop when NAND is not present. As IGEPv2 comes either with NAND or OneNAND flash, add reset timeout to let function fail gracefully allowing caller to know NAND is not present. On NAND equipped board, reset succeeds on first read, so 1000 loops seems to be a safe timeout.
--- arch/arm/cpu/armv7/omap3/spl_id_nand.c | 32 +++++++++++++---------------- arch/arm/include/asm/arch-omap3/sys_proto.h | 2 +- 2 files changed, 15 insertions(+), 19 deletions(-)
arch/arm/cpu/armv7/omap3/spl_id_nand.c +14 -18
@@ -20,29 +20,16 @@static struct gpmc *gpmc_config = (struct gpmc *)GPMC_BASE ; -/* nand_command: Send a flash command to the flash chip */ -static void nand_command (u8 command) -{ -writeb (command, &gpmc_config->cs[0 ].nand_cmd); - -if (command ==NAND_CMD_RESET ) { -unsigned char ret_val; -writeb (NAND_CMD_STATUS , &gpmc_config->cs[0 ].nand_cmd); -do { -/* Wait until ready */ - ret_val =readl (&gpmc_config->cs[0 ].nand_dat); - }while ((ret_val &NAND_STATUS_READY ) !=NAND_STATUS_READY ); - } -} -/* * Many boards will want to know the results of the NAND_CMD_READID command * in order to decide what to do about DDR initialization. This function * allows us to do that very early and to pass those results back to the * board so it can make whatever decisions need to be made. */ -void identify_nand_chip (int *mfr,int *id) +int identify_nand_chip (int *mfr,int *id) { +int loops =1000 ; +/* Make sure that we have setup GPMC for NAND correctly. */ writel (M_NAND_GPMC_CONFIG1 , &gpmc_config->cs[0 ].config1);writel (M_NAND_GPMC_CONFIG2 , &gpmc_config->cs[0 ].config2);
@@ -62,8 +49,15 @@ void identify_nand_chip(int *mfr, int *id)sdelay (2000 );/* Issue a RESET and then READID */ -nand_command (NAND_CMD_RESET ); -nand_command (NAND_CMD_READID ); +writeb (NAND_CMD_RESET , &gpmc_config->cs[0 ].nand_cmd); +writeb (NAND_CMD_STATUS , &gpmc_config->cs[0 ].nand_cmd); +while ((readl (&gpmc_config->cs[0 ].nand_dat) &NAND_STATUS_READY ) + !=NAND_STATUS_READY ) { +sdelay (100 ); +if (--loops ==0 ) +return 1 ; + } +writeb (NAND_CMD_READID , &gpmc_config->cs[0 ].nand_cmd);/* Set the address to read to 0x0 */ writeb (0x0 , &gpmc_config->cs[0 ].nand_adr);
@@ -71,4 +65,6 @@ void identify_nand_chip(int *mfr, int *id)/* Read off the manufacturer and device id. */ *mfr =readb (&gpmc_config->cs[0 ].nand_dat); *id =readb (&gpmc_config->cs[0 ].nand_dat); + +return 0 ; }
arch/arm/include/asm/arch-omap3/sys_proto.h +1 -1
@@ -40,7 +40,7 @@ void sdrc_init(void);void do_sdrc_init (u32 ,u32 );void get_board_mem_timings (struct board_sdrc_timings *timings); -void identify_nand_chip (int *mfr,int *id); +int identify_nand_chip (int *mfr,int *id);void emif4_init (void );void gpmc_init (void ); void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base,
Signature · 1 line
2.1.4
PATCH 1/1 armv7: make gpmc_cfg const
In reply to Ladislav Michl--- arch/arm/cpu/armv7/omap-common/mem-common.c | 8 +++----- arch/arm/include/asm/arch-omap3/sys_proto.h | 4 ++-- include/linux/mtd/omap_gpmc.h | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-)
arch/arm/cpu/armv7/omap-common/mem-common.c +3 -5
@@ -21,7 +21,7 @@#include <command.h> #include <linux/mtd/omap_gpmc.h> -struct gpmc *gpmc_cfg; +const struct gpmc *gpmc_cfg = (struct gpmc *)GPMC_BASE ;#if defined(CONFIG_OMAP34XX )/********************************************************
@@ -50,8 +50,8 @@ u32 mem_ok(u32 cs) }#endif -void enable_gpmc_cs_config (const u32 *gpmc_config,struct gpmc_cs *cs,u32 base, -u32 size) +void enable_gpmc_cs_config (const u32 *gpmc_config,const struct gpmc_cs *cs, +u32 base,u32 size) {writel (0 , &cs->config7);sdelay (1000 );
@@ -75,8 +75,6 @@ void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base,*****************************************************/ void gpmc_init (void ) { -/* putting a blanket check on GPMC based on ZeBu for now */ - gpmc_cfg = (struct gpmc *)GPMC_BASE ;#if defined(CONFIG_NOR )/* configure GPMC for NOR */ const u32 gpmc_regs[GPMC_MAX_REG] = { STNOR_GPMC_CONFIG1,
arch/arm/include/asm/arch-omap3/sys_proto.h +2 -2
@@ -43,8 +43,8 @@ void get_board_mem_timings(struct board_sdrc_timings *timings);int identify_nand_chip (int *mfr,int *id);void emif4_init (void );void gpmc_init (void ); -void enable_gpmc_cs_config (const u32 *gpmc_config,struct gpmc_cs *cs,u32 base, -u32 size); +void enable_gpmc_cs_config (const u32 *gpmc_config,const struct gpmc_cs *cs, +u32 base,u32 size);void watchdog_init (void );void set_muxconf_regs (void );
include/linux/mtd/omap_gpmc.h +1 -1
@@ -92,6 +92,6 @@ struct gpmc { };/* Used for board specific gpmc initialization */ -extern struct gpmc *gpmc_cfg; +extern const struct gpmc *gpmc_cfg;#endif /* __ASM_OMAP_GPMC_H */
Signature · 1 line
2.1.4
RFC 1/1 armv7: Introduce enable_gpmc_cs_config
In reply to Ladislav Michlfor now gpmc_init keeps original init logic... Also see FIXME and TODO below
--- arch/arm/cpu/armv7/omap-common/mem-common.c | 134 +++++++++++++++++----------- arch/arm/include/asm/arch-omap3/sys_proto.h | 1 + 2 files changed, 84 insertions(+), 51 deletions(-)
arch/arm/cpu/armv7/omap-common/mem-common.c +83 -51
@@ -68,6 +68,79 @@ void enable_gpmc_cs_config(const u32 *gpmc_config, const struct gpmc_cs *cs,sdelay (2000 ); } +/* TODO: reuse MTD_DEV_TYPE_ from <jffs2/load_kernel.h> ? */ +void set_gpmc_cs0 (int flash_type) +{ +const u32 *gpmc_regs; +u32 base, size; +#if defined(CONFIG_NOR ) +const u32 gpmc_regs_nor[GPMC_MAX_REG ] = { +STNOR_GPMC_CONFIG1 , +STNOR_GPMC_CONFIG2 , +STNOR_GPMC_CONFIG3 , +STNOR_GPMC_CONFIG4 , +STNOR_GPMC_CONFIG5 , +STNOR_GPMC_CONFIG6 , +STNOR_GPMC_CONFIG7 + }; +#endif +#if defined(CONFIG_NAND ) || defined(CONFIG_CMD_NAND ) +const u32 gpmc_regs_nand[GPMC_MAX_REG ] = { +M_NAND_GPMC_CONFIG1 , +M_NAND_GPMC_CONFIG2 , +M_NAND_GPMC_CONFIG3 , +M_NAND_GPMC_CONFIG4 , +M_NAND_GPMC_CONFIG5 , +M_NAND_GPMC_CONFIG6 , +0 + }; +#endif +#if defined(CONFIG_CMD_ONENAND ) +const u32 gpmc_regs_onenand[GPMC_MAX_REG ] = { +ONENAND_GPMC_CONFIG1 , +ONENAND_GPMC_CONFIG2 , +ONENAND_GPMC_CONFIG3 , +ONENAND_GPMC_CONFIG4 , +ONENAND_GPMC_CONFIG5 , +ONENAND_GPMC_CONFIG6 , +0 + }; +#endif + +switch (flash_type) { +#if defined(CONFIG_NOR ) +case 0 : + gpmc_regs = gpmc_regs_nor; + base =CONFIG_SYS_FLASH_BASE ; + size = (CONFIG_SYS_FLASH_SIZE >0x08000000 ) ?GPMC_SIZE_256M : + ((CONFIG_SYS_FLASH_SIZE >0x04000000 ) ?GPMC_SIZE_128M : + ((CONFIG_SYS_FLASH_SIZE >0x02000000 ) ?GPMC_SIZE_64M : + ((CONFIG_SYS_FLASH_SIZE >0x01000000 ) ?GPMC_SIZE_32M : +GPMC_SIZE_16M ))); +break ; +#endif +#if defined(CONFIG_NAND ) || defined(CONFIG_CMD_NAND ) +case 1 : + gpmc_regs = gpmc_regs_nand; + base =CONFIG_SYS_NAND_BASE ; + size =GPMC_SIZE_16M ; +break ; +#endif +#if defined(CONFIG_CMD_ONENAND ) +case 2 : + gpmc_regs = gpmc_regs_onenand; + base =CONFIG_SYS_ONENAND_BASE ; + size =GPMC_SIZE_128M ; +break ; +#endif +default : +return ; + } + +/* enable chip-select specific configurations */ +enable_gpmc_cs_config (gpmc_regs, &gpmc_cfg->cs[0 ], base, size); +} +/***************************************************** * gpmc_init(): init gpmc bus * Init GPMC for x16, MuxMode (SDRAM in x32).
@@ -75,51 +148,6 @@ void enable_gpmc_cs_config(const u32 *gpmc_config, const struct gpmc_cs *cs,*****************************************************/ void gpmc_init (void ) { -#if defined(CONFIG_NOR ) -/* configure GPMC for NOR */ -const u32 gpmc_regs[GPMC_MAX_REG ] = {STNOR_GPMC_CONFIG1 , -STNOR_GPMC_CONFIG2 , -STNOR_GPMC_CONFIG3 , -STNOR_GPMC_CONFIG4 , -STNOR_GPMC_CONFIG5 , -STNOR_GPMC_CONFIG6 , -STNOR_GPMC_CONFIG7 - }; -u32 base =CONFIG_SYS_FLASH_BASE ; -u32 size = (CONFIG_SYS_FLASH_SIZE >0x08000000 ) ?GPMC_SIZE_256M : -/* > 64MB */ ((CONFIG_SYS_FLASH_SIZE >0x04000000 ) ?GPMC_SIZE_128M : -/* > 32MB */ ((CONFIG_SYS_FLASH_SIZE >0x02000000 ) ?GPMC_SIZE_64M : -/* > 16MB */ ((CONFIG_SYS_FLASH_SIZE >0x01000000 ) ?GPMC_SIZE_32M : -/* min 16MB */ GPMC_SIZE_16M ))); -#elif defined(CONFIG_NAND ) || defined(CONFIG_CMD_NAND ) -/* configure GPMC for NAND */ -const u32 gpmc_regs[GPMC_MAX_REG ] = {M_NAND_GPMC_CONFIG1 , -M_NAND_GPMC_CONFIG2 , -M_NAND_GPMC_CONFIG3 , -M_NAND_GPMC_CONFIG4 , -M_NAND_GPMC_CONFIG5 , -M_NAND_GPMC_CONFIG6 , -0 - }; -u32 base =CONFIG_SYS_NAND_BASE ; -u32 size =GPMC_SIZE_16M ; - -#elif defined(CONFIG_CMD_ONENAND ) -const u32 gpmc_regs[GPMC_MAX_REG ] = {ONENAND_GPMC_CONFIG1 , -ONENAND_GPMC_CONFIG2 , -ONENAND_GPMC_CONFIG3 , -ONENAND_GPMC_CONFIG4 , -ONENAND_GPMC_CONFIG5 , -ONENAND_GPMC_CONFIG6 , -0 - }; -u32 size =GPMC_SIZE_128M ; -u32 base =CONFIG_SYS_ONENAND_BASE ; -#else -const u32 gpmc_regs[GPMC_MAX_REG ] = {0 ,0 ,0 ,0 ,0 ,0 ,0 }; -u32 size =0 ; -u32 base =0 ; -#endif /* global settings */ writel (0x00000008 , &gpmc_cfg->sysconfig);writel (0x00000000 , &gpmc_cfg->irqstatus);
@@ -131,12 +159,16 @@ void gpmc_init(void)#else writel (0x00000012 , &gpmc_cfg->config);#endif -/* -* Disable the GPMC0 config set by ROM code -*/ +/* disable the GPMC0 config set by ROM code */ writel (0 , &gpmc_cfg->cs[0 ].config7);sdelay (1000 ); -/* enable chip-select specific configurations */ -if (base !=0 ) -enable_gpmc_cs_config (gpmc_regs, &gpmc_cfg->cs[0 ], base, size); + +/* FIXME !!! */ +#if defined(CONFIG_NOR ) +set_gpmc_cs0 (0 ); +#elif defined(CONFIG_NAND ) || defined(CONFIG_CMD_NAND ) +set_gpmc_cs0 (1 ); +#elif defined(CONFIG_CMD_ONENAND ) +set_gpmc_cs0 (2 ); +#endif }
arch/arm/include/asm/arch-omap3/sys_proto.h +1 -0
@@ -45,6 +45,7 @@ void emif4_init(void);void gpmc_init (void );void enable_gpmc_cs_config (const u32 *gpmc_config,const struct gpmc_cs *cs,u32 base,u32 size); +void set_gpmc_cs0 (int flash_type);void watchdog_init (void );void set_muxconf_regs (void );
Signature · 1 line
2.1.4
[U-Boot] (no subject)
In reply to Ladislav MichlUse newly introduced function. As it depends on previous RFC, lets turn in into proper patch once beforementioned problems are solved
--- arch/arm/cpu/armv7/omap3/spl_id_nand.c | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-)
arch/arm/cpu/armv7/omap3/spl_id_nand.c +10 -23
@@ -18,7 +18,7 @@#include <asm/arch/sys_proto.h> #include <asm/arch/mem.h> -static struct gpmc *gpmc_config = (struct gpmc *)GPMC_BASE ; +extern const struct gpmc *gpmc_cfg;/* * Many boards will want to know the results of the NAND_CMD_READID command
@@ -31,40 +31,27 @@ int identify_nand_chip(int *mfr, int *id)int loops =1000 ;/* Make sure that we have setup GPMC for NAND correctly. */ -writel (M_NAND_GPMC_CONFIG1 , &gpmc_config->cs[0 ].config1); -writel (M_NAND_GPMC_CONFIG2 , &gpmc_config->cs[0 ].config2); -writel (M_NAND_GPMC_CONFIG3 , &gpmc_config->cs[0 ].config3); -writel (M_NAND_GPMC_CONFIG4 , &gpmc_config->cs[0 ].config4); -writel (M_NAND_GPMC_CONFIG5 , &gpmc_config->cs[0 ].config5); -writel (M_NAND_GPMC_CONFIG6 , &gpmc_config->cs[0 ].config6); - -/* -* Enable the config. The CS size goes in bits 11:8. We set -* bit 6 to enable the CS and the base address goes into bits 5:0. -*/ -writel ((GPMC_SIZE_128M <<8 ) | (GPMC_CS_ENABLE <<6 ) | - ((NAND_BASE >>24 ) &GPMC_BASEADDR_MASK ), - &gpmc_config->cs[0 ].config7); +set_gpmc_cs0 (1 );sdelay (2000 );/* Issue a RESET and then READID */ -writeb (NAND_CMD_RESET , &gpmc_config->cs[0 ].nand_cmd); -writeb (NAND_CMD_STATUS , &gpmc_config->cs[0 ].nand_cmd); -while ((readl (&gpmc_config->cs[0 ].nand_dat) &NAND_STATUS_READY ) - !=NAND_STATUS_READY ) { +writeb (NAND_CMD_RESET , &gpmc_cfg->cs[0 ].nand_cmd); +writeb (NAND_CMD_STATUS , &gpmc_cfg->cs[0 ].nand_cmd); +while ((readl (&gpmc_cfg->cs[0 ].nand_dat) &NAND_STATUS_READY ) + !=NAND_STATUS_READY ) {sdelay (100 );if (--loops ==0 )return 1 ; } -writeb (NAND_CMD_READID , &gpmc_config->cs[0 ].nand_cmd); +writeb (NAND_CMD_READID , &gpmc_cfg->cs[0 ].nand_cmd);/* Set the address to read to 0x0 */ -writeb (0x0 , &gpmc_config->cs[0 ].nand_adr); +writeb (0x0 , &gpmc_cfg->cs[0 ].nand_adr);/* Read off the manufacturer and device id. */ - *mfr =readb (&gpmc_config->cs[0 ].nand_dat); - *id =readb (&gpmc_config->cs[0 ].nand_dat); + *mfr =readb (&gpmc_cfg->cs[0 ].nand_dat); + *id =readb (&gpmc_cfg->cs[0 ].nand_dat);return 0 ; }
Signature · 1 line
2.1.4
[U-Boot] (no subject)
In reply to Ladislav MichlAdd timeout to onenand_wait ready loop as it hangs here indefinitely when chip not present. Once there, do the same for onenand_bbt_wait as well (note: recent Linux driver code does the same)
--- drivers/mtd/onenand/onenand_base.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-)
drivers/mtd/onenand/onenand_base.c +19 -11
@@ -20,6 +20,7 @@*/ #include <common.h> +#include <watchdog.h> #include <linux/compat.h> #include <linux/mtd/mtd.h> #include "linux/mtd/flashchip.h"
@@ -467,15 +468,18 @@ static int onenand_read_ecc(struct onenand_chip *this)static int onenand_wait (struct mtd_info *mtd,int state) {struct onenand_chip *this = mtd->priv; -unsigned int flags =ONENAND_INT_MASTER ;unsigned int interrupt =0 ;unsigned int ctrl; -while (1 ) { +/* Wait at most 20ms ... */ +u32 timeo = (CONFIG_SYS_HZ *20 ) /1000 ; +u32 time_start =get_timer (0 ); +do { +WATCHDOG_RESET (); +if (get_timer (time_start) > timeo) +return -EIO ; interrupt = this->read_word (this->base +ONENAND_REG_INTERRUPT ); -if (interrupt & flags) -break ; - } + }while ((interrupt &ONENAND_INT_MASTER ) ==0 ); ctrl = this->read_word (this->base +ONENAND_REG_CTRL_STATUS );
@@ -1154,15 +1158,18 @@ int onenand_read_oob(struct mtd_info *mtd, loff_t from,static int onenand_bbt_wait (struct mtd_info *mtd,int state) {struct onenand_chip *this = mtd->priv; -unsigned int flags =ONENAND_INT_MASTER ;unsigned int interrupt;unsigned int ctrl; -while (1 ) { +/* Wait at most 20ms ... */ +u32 timeo = (CONFIG_SYS_HZ *20 ) /1000 ; +u32 time_start =get_timer (0 ); +do { +WATCHDOG_RESET (); +if (get_timer (time_start) > timeo) +return ONENAND_BBT_READ_FATAL_ERROR ; interrupt = this->read_word (this->base +ONENAND_REG_INTERRUPT ); -if (interrupt & flags) -break ; - } + }while ((interrupt &ONENAND_INT_MASTER ) ==0 );/* To get correct interrupt status in timeout case */ interrupt = this->read_word (this->base +ONENAND_REG_INTERRUPT );
@@ -2536,7 +2543,8 @@ static int onenand_chip_probe(struct mtd_info *mtd) this->write_word (ONENAND_CMD_RESET , this->base +ONENAND_BOOTRAM );/* Wait reset */ - this->wait (mtd,FL_RESETING ); +if (this->wait (mtd,FL_RESETING )) +return -ENXIO ;/* Restore system configuration 1 */ this->write_word (syscfg, this->base +ONENAND_REG_SYS_CFG1 );
Signature · 1 line
2.1.4
PATCH 1/1 mtd: OneNAND: allow board init function fail
In reply to Ladislav Michl--- board/micronas/vct/ebi_onenand.c | 4 +++- board/samsung/goni/onenand.c | 4 +++- board/samsung/smdkc100/onenand.c | 4 +++- board/samsung/universal_c210/onenand.c | 4 +++- drivers/mtd/onenand/onenand_uboot.c | 30 +++++++++++++++--------------- include/onenand_uboot.h | 2 +- 6 files changed, 28 insertions(+), 20 deletions(-)
board/micronas/vct/ebi_onenand.c +3 -1
@@ -169,7 +169,7 @@ static int ebi_write_bufferram(struct mtd_info *mtd, loff_t addr, int area,return 0 ; } -void onenand_board_init (struct mtd_info *mtd) +int onenand_board_init (struct mtd_info *mtd) {struct onenand_chip *chip = mtd->priv;
@@ -181,4 +181,6 @@ void onenand_board_init(struct mtd_info *mtd) chip->read_bufferram = ebi_read_bufferram; chip->write_bufferram = ebi_write_bufferram; + +return 0 ; }
board/samsung/goni/onenand.c +3 -1
@@ -11,11 +11,13 @@#include <linux/mtd/samsung_onenand.h> #include <onenand_uboot.h> -void onenand_board_init (struct mtd_info *mtd) +int onenand_board_init (struct mtd_info *mtd) {struct onenand_chip *this = mtd->priv; this->base = (void *)CONFIG_SYS_ONENAND_BASE ; this->options |=ONENAND_RUNTIME_BADBLOCK_CHECK ; this->chip_probe = s5pc110_chip_probe; + +return 0 ; }
board/samsung/smdkc100/onenand.c +3 -1
@@ -16,7 +16,7 @@#include <asm/io.h> #include <asm/arch/clock.h> -void onenand_board_init (struct mtd_info *mtd) +int onenand_board_init (struct mtd_info *mtd) {struct onenand_chip *this = mtd->priv; struct s5pc100_clock *clk =
@@ -65,4 +65,6 @@ void onenand_board_init(struct mtd_info *mtd)writel (value, &onenand->int_err_mask);s3c_onenand_init (mtd); + +return 0 ; }
board/samsung/universal_c210/onenand.c +3 -1
@@ -10,11 +10,13 @@#include <linux/mtd/onenand.h> #include <linux/mtd/samsung_onenand.h> -void onenand_board_init (struct mtd_info *mtd) +int onenand_board_init (struct mtd_info *mtd) {struct onenand_chip *this = mtd->priv; this->base = (void *)CONFIG_SYS_ONENAND_BASE ; this->options |=ONENAND_RUNTIME_BADBLOCK_CHECK ; this->chip_probe = s5pc210_chip_probe; + +return 0 ; }
drivers/mtd/onenand/onenand_uboot.c +15 -15
@@ -24,33 +24,33 @@ static __attribute__((unused)) char dev_name[] = "onenand0";void onenand_init (void ) { +int err =0 ;memset (&onenand_mtd,0 ,sizeof (struct mtd_info ));memset (&onenand_chip,0 ,sizeof (struct onenand_chip )); onenand_mtd.priv = &onenand_chip;#ifdef CONFIG_USE_ONENAND_BOARD_INIT -/* -* It's used for some board init required -*/ -onenand_board_init (&onenand_mtd); +/* It's used for some board init required */ + err =onenand_board_init (&onenand_mtd);#else onenand_chip.base = (void *)CONFIG_SYS_ONENAND_BASE ;#endif -onenand_scan (&onenand_mtd,1 ); +if (!err && !(onenand_scan (&onenand_mtd,1 ))) { -if (onenand_chip.device_id &DEVICE_IS_FLEXONENAND ) -puts ("Flex-" ); -puts ("OneNAND: " ); -print_size (onenand_chip.chipsize,"\n" ); +if (onenand_chip.device_id &DEVICE_IS_FLEXONENAND ) +puts ("Flex-" ); +puts ("OneNAND: " );#ifdef CONFIG_MTD_DEVICE -/* -* Add MTD device so that we can reference it later -* via the mtdcore infrastructure (e.g. ubi). -*/ - onenand_mtd.name = dev_name; -add_mtd_device (&onenand_mtd); +/* +* Add MTD device so that we can reference it later +* via the mtdcore infrastructure (e.g. ubi). +*/ + onenand_mtd.name = dev_name; +add_mtd_device (&onenand_mtd);#endif + } +print_size (onenand_chip.chipsize,"\n" ); }
include/onenand_uboot.h +1 -1
@@ -26,7 +26,7 @@ extern struct mtd_info onenand_mtd;extern struct onenand_chip onenand_chip;/* board */ -extern void onenand_board_init (struct mtd_info *); +extern int onenand_board_init (struct mtd_info *);/* Functions */ extern void onenand_init (void );
Signature · 1 line
2.1.4
On Fri, Jun 17, 2016 at 12:00:13PM +0200, Ladislav Michl wrote:
[snip]
Quoted 9 lines
As we might want to use single binary also to boot from MMC or other sources, we cannot use
boot_deviceto get a glue about used flash type. Also U-Boot should not count on being loaded by its own SPL. So, to make things easier to begin with, do we all agree that omap_gpmc:board_nand_init as well as its OneNAND counterpart should expect gpmc config1 register properly set and fail if something unexpected is found? That basically means if we should rely on CS0 config provided by first stage loader or try to rediscover flash devices (this problem does not exist when flash itself is boot source)
Lets overcome this limitation by introducing omap specific global gpmc_cs0_flash holding detected flash type. Single U-Boot and SPL binary is now running on all variants of IGEPv2 board. Modified patches previously sent as RFC are following this mail, but as they are based ot top of other fixes and cleanups I sent earlier they probably won't apply until someone takes some action (yes, NACK is also an action ;-))
regards,
ladis
PATCH 1/1 armv7: introduce set_gpmc_cs0
Allow boards to runtime detect flash type.
--- arch/arm/cpu/armv7/omap-common/mem-common.c | 148 +++++++++++++++++----------- arch/arm/include/asm/arch-omap3/sys_proto.h | 1 + include/linux/mtd/omap_gpmc.h | 1 + 3 files changed, 92 insertions(+), 58 deletions(-)
arch/arm/cpu/armv7/omap-common/mem-common.c +90 -58
@@ -20,9 +20,20 @@#include <asm/arch/sys_proto.h> #include <command.h> #include <linux/mtd/omap_gpmc.h> +#include <jffs2/load_kernel.h> const struct gpmc *gpmc_cfg = (struct gpmc *)GPMC_BASE ; +#if defined(CONFIG_NOR ) +char gpmc_cs0_flash =MTD_DEV_TYPE_NOR ; +#elif defined(CONFIG_NAND ) || defined(CONFIG_CMD_NAND ) +char gpmc_cs0_flash =MTD_DEV_TYPE_NAND ; +#elif defined(CONFIG_CMD_ONENAND ) +char gpmc_cs0_flash =MTD_DEV_TYPE_ONENAND ; +#else +char gpmc_cs0_flash =-1 ; +#endif +#if defined(CONFIG_OMAP34XX )/******************************************************** * mem_ok() - test used to see if timings are correct
@@ -68,6 +79,81 @@ void enable_gpmc_cs_config(const u32 *gpmc_config, const struct gpmc_cs *cs,sdelay (2000 ); } +void set_gpmc_cs0 (int flash_type) +{ +const u32 *gpmc_regs; +u32 base, size; +#if defined(CONFIG_NOR ) +const u32 gpmc_regs_nor[GPMC_MAX_REG ] = { +STNOR_GPMC_CONFIG1 , +STNOR_GPMC_CONFIG2 , +STNOR_GPMC_CONFIG3 , +STNOR_GPMC_CONFIG4 , +STNOR_GPMC_CONFIG5 , +STNOR_GPMC_CONFIG6 , +STNOR_GPMC_CONFIG7 + }; +#endif +#if defined(CONFIG_NAND ) || defined(CONFIG_CMD_NAND ) +const u32 gpmc_regs_nand[GPMC_MAX_REG ] = { +M_NAND_GPMC_CONFIG1 , +M_NAND_GPMC_CONFIG2 , +M_NAND_GPMC_CONFIG3 , +M_NAND_GPMC_CONFIG4 , +M_NAND_GPMC_CONFIG5 , +M_NAND_GPMC_CONFIG6 , +0 + }; +#endif +#if defined(CONFIG_CMD_ONENAND ) +const u32 gpmc_regs_onenand[GPMC_MAX_REG ] = { +ONENAND_GPMC_CONFIG1 , +ONENAND_GPMC_CONFIG2 , +ONENAND_GPMC_CONFIG3 , +ONENAND_GPMC_CONFIG4 , +ONENAND_GPMC_CONFIG5 , +ONENAND_GPMC_CONFIG6 , +0 + }; +#endif + +switch (flash_type) { +#if defined(CONFIG_NOR ) +case MTD_DEV_TYPE_NOR : + gpmc_regs = gpmc_regs_nor; + base =CONFIG_SYS_FLASH_BASE ; + size = (CONFIG_SYS_FLASH_SIZE >0x08000000 ) ?GPMC_SIZE_256M : + ((CONFIG_SYS_FLASH_SIZE >0x04000000 ) ?GPMC_SIZE_128M : + ((CONFIG_SYS_FLASH_SIZE >0x02000000 ) ?GPMC_SIZE_64M : + ((CONFIG_SYS_FLASH_SIZE >0x01000000 ) ?GPMC_SIZE_32M : +GPMC_SIZE_16M ))); +break ; +#endif +#if defined(CONFIG_NAND ) || defined(CONFIG_CMD_NAND ) +case MTD_DEV_TYPE_NAND : + gpmc_regs = gpmc_regs_nand; + base =CONFIG_SYS_NAND_BASE ; + size =GPMC_SIZE_16M ; +break ; +#endif +#if defined(CONFIG_CMD_ONENAND ) +case MTD_DEV_TYPE_ONENAND : + gpmc_regs = gpmc_regs_onenand; + base =CONFIG_SYS_ONENAND_BASE ; + size =GPMC_SIZE_128M ; +break ; +#endif +default : +/* disable the GPMC0 config set by ROM code */ +writel (0 , &gpmc_cfg->cs[0 ].config7); +sdelay (1000 ); +return ; + } + +/* enable chip-select specific configurations */ +enable_gpmc_cs_config (gpmc_regs, &gpmc_cfg->cs[0 ], base, size); +} +/***************************************************** * gpmc_init(): init gpmc bus * Init GPMC for x16, MuxMode (SDRAM in x32).
@@ -75,68 +161,14 @@ void enable_gpmc_cs_config(const u32 *gpmc_config, const struct gpmc_cs *cs,*****************************************************/ void gpmc_init (void ) { -#if defined(CONFIG_NOR ) -/* configure GPMC for NOR */ -const u32 gpmc_regs[GPMC_MAX_REG ] = {STNOR_GPMC_CONFIG1 , -STNOR_GPMC_CONFIG2 , -STNOR_GPMC_CONFIG3 , -STNOR_GPMC_CONFIG4 , -STNOR_GPMC_CONFIG5 , -STNOR_GPMC_CONFIG6 , -STNOR_GPMC_CONFIG7 - }; -u32 base =CONFIG_SYS_FLASH_BASE ; -u32 size = (CONFIG_SYS_FLASH_SIZE >0x08000000 ) ?GPMC_SIZE_256M : -/* > 64MB */ ((CONFIG_SYS_FLASH_SIZE >0x04000000 ) ?GPMC_SIZE_128M : -/* > 32MB */ ((CONFIG_SYS_FLASH_SIZE >0x02000000 ) ?GPMC_SIZE_64M : -/* > 16MB */ ((CONFIG_SYS_FLASH_SIZE >0x01000000 ) ?GPMC_SIZE_32M : -/* min 16MB */ GPMC_SIZE_16M ))); -#elif defined(CONFIG_NAND ) || defined(CONFIG_CMD_NAND ) -/* configure GPMC for NAND */ -const u32 gpmc_regs[GPMC_MAX_REG ] = {M_NAND_GPMC_CONFIG1 , -M_NAND_GPMC_CONFIG2 , -M_NAND_GPMC_CONFIG3 , -M_NAND_GPMC_CONFIG4 , -M_NAND_GPMC_CONFIG5 , -M_NAND_GPMC_CONFIG6 , -0 - }; -u32 base =CONFIG_SYS_NAND_BASE ; -u32 size =GPMC_SIZE_16M ; - -#elif defined(CONFIG_CMD_ONENAND ) -const u32 gpmc_regs[GPMC_MAX_REG ] = {ONENAND_GPMC_CONFIG1 , -ONENAND_GPMC_CONFIG2 , -ONENAND_GPMC_CONFIG3 , -ONENAND_GPMC_CONFIG4 , -ONENAND_GPMC_CONFIG5 , -ONENAND_GPMC_CONFIG6 , -0 - }; -u32 size =GPMC_SIZE_128M ; -u32 base =CONFIG_SYS_ONENAND_BASE ; -#else -const u32 gpmc_regs[GPMC_MAX_REG ] = {0 ,0 ,0 ,0 ,0 ,0 ,0 }; -u32 size =0 ; -u32 base =0 ; -#endif /* global settings */ writel (0x00000008 , &gpmc_cfg->sysconfig);writel (0x00000000 , &gpmc_cfg->irqstatus);writel (0x00000000 , &gpmc_cfg->irqenable);/* disable timeout, set a safe reset value */ writel (0x00001ff0 , &gpmc_cfg->timeout_control); -#ifdef CONFIG_NOR -writel (0x00000200 , &gpmc_cfg->config); -#else -writel (0x00000012 , &gpmc_cfg->config); -#endif -/* -* Disable the GPMC0 config set by ROM code -*/ -writel (0 , &gpmc_cfg->cs[0 ].config7); -sdelay (1000 ); -/* enable chip-select specific configurations */ -if (base !=0 ) -enable_gpmc_cs_config (gpmc_regs, &gpmc_cfg->cs[0 ], base, size); +writel (gpmc_cs0_flash ==MTD_DEV_TYPE_NOR ? +0x00000200 :0x00000012 , &gpmc_cfg->config); + +set_gpmc_cs0 (gpmc_cs0_flash); }
arch/arm/include/asm/arch-omap3/sys_proto.h +1 -0
@@ -45,6 +45,7 @@ void emif4_init(void);void gpmc_init (void );void enable_gpmc_cs_config (const u32 *gpmc_config,const struct gpmc_cs *cs,u32 base,u32 size); +void set_gpmc_cs0 (int flash_type);void watchdog_init (void );void set_muxconf_regs (void );
include/linux/mtd/omap_gpmc.h +1 -0
@@ -93,5 +93,6 @@ struct gpmc {/* Used for board specific gpmc initialization */ extern const struct gpmc *gpmc_cfg; +extern char gpmc_cs0_flash;#endif /* __ASM_OMAP_GPMC_H */
Signature · 1 line
2.1.4
PATCH 1/1 igep00x0: runtime flash detection
In reply to Ladislav Michl--- board/isee/igep00x0/igep00x0.c | 71 +++++++++++++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 18 deletions(-)
board/isee/igep00x0/igep00x0.c +53 -18
@@ -17,6 +17,10 @@#include <asm/arch/mux.h> #include <asm/arch/sys_proto.h> #include <asm/mach-types.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/onenand.h> +#include <jffs2/load_kernel.h> #include "igep00x0.h" DECLARE_GLOBAL_DATA_PTR ;
@@ -56,7 +60,25 @@ U_BOOT_DEVICE(igep_uart) = {*/ int board_init (void ) { -gpmc_init ();/* in SRAM or SDRAM, finish GPMC */ +int loops =100 ; + +/* find out flash memory type, assume NAND first */ + gpmc_cs0_flash =MTD_DEV_TYPE_NAND ; +gpmc_init (); + +/* Issue a RESET and then READID */ +writeb (NAND_CMD_RESET , &gpmc_cfg->cs[0 ].nand_cmd); +writeb (NAND_CMD_STATUS , &gpmc_cfg->cs[0 ].nand_cmd); +while ((readl (&gpmc_cfg->cs[0 ].nand_dat) &NAND_STATUS_READY ) + !=NAND_STATUS_READY ) { +udelay (1 ); +if (--loops ==0 ) { + gpmc_cs0_flash =MTD_DEV_TYPE_ONENAND ; +gpmc_init ();/* reinitialize for OneNAND */ +break ; + } + } +/* boot param addr */ gd->bd->bi_boot_params = (OMAP34XX_SDRC_CS0 +0x100 );
@@ -75,29 +97,42 @@ int board_init(void)*/ void get_board_mem_timings (struct board_sdrc_timings *timings) { - timings->mr =MICRON_V_MR_165 ; -#ifdef CONFIG_BOOT_NAND - timings->mcfg =MICRON_V_MCFG_200 (256 <<20 ); - timings->ctrla =MICRON_V_ACTIMA_200 ; - timings->ctrlb =MICRON_V_ACTIMB_200 ; - timings->rfr_ctrl = SDP_3430_SDRC_RFR_CTRL_200MHz; -#else -if (get_cpu_family () ==CPU_OMAP34XX ) { - timings->mcfg =NUMONYX_V_MCFG_165 (256 <<20 ); - timings->ctrla =NUMONYX_V_ACTIMA_165 ; - timings->ctrlb =NUMONYX_V_ACTIMB_165 ; - timings->rfr_ctrl = SDP_3430_SDRC_RFR_CTRL_165MHz; +int mfr, id, err =identify_nand_chip (&mfr, &id); - }else { - timings->mcfg =NUMONYX_V_MCFG_200 (256 <<20 ); - timings->ctrla =NUMONYX_V_ACTIMA_200 ; - timings->ctrlb =NUMONYX_V_ACTIMB_200 ; + timings->mr =MICRON_V_MR_165 ; +if (!err && mfr ==NAND_MFR_MICRON ) { + timings->mcfg =MICRON_V_MCFG_200 (256 <<20 ); + timings->ctrla =MICRON_V_ACTIMA_200 ; + timings->ctrlb =MICRON_V_ACTIMB_200 ; timings->rfr_ctrl = SDP_3430_SDRC_RFR_CTRL_200MHz; + gpmc_cs0_flash =MTD_DEV_TYPE_NAND ; + }else { +if (get_cpu_family () ==CPU_OMAP34XX ) { + timings->mcfg =NUMONYX_V_MCFG_165 (256 <<20 ); + timings->ctrla =NUMONYX_V_ACTIMA_165 ; + timings->ctrlb =NUMONYX_V_ACTIMB_165 ; + timings->rfr_ctrl = SDP_3430_SDRC_RFR_CTRL_165MHz; + }else { + timings->mcfg =NUMONYX_V_MCFG_200 (256 <<20 ); + timings->ctrla =NUMONYX_V_ACTIMA_200 ; + timings->ctrlb =NUMONYX_V_ACTIMB_200 ; + timings->rfr_ctrl = SDP_3430_SDRC_RFR_CTRL_200MHz; + } + gpmc_cs0_flash =MTD_DEV_TYPE_ONENAND ; } -#endif }#endif +int onenand_board_init (struct mtd_info *mtd) +{ +if (gpmc_cs0_flash ==MTD_DEV_TYPE_ONENAND ) { +struct onenand_chip *this = mtd->priv; + this->base = (void *)CONFIG_SYS_ONENAND_BASE ; +return 0 ; + } +return 1 ; +} +#if defined(CONFIG_CMD_NET )static void reset_net_chip (int gpio) {
Signature · 1 line
2.1.4