From 2255b2d2044d434463eb2661e18018e50f1643d9 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 10 Oct 2006 12:36:02 +0200 Subject: * Several improvements to the new NAND subsystem: - JFFS2 related commands implemented in mtd-utils style - Support for bad blocks - Bad block testing commands - NAND lock commands Please take a look at doc/README.nand for more details Patch by Guido Classen, 10 Oct 2006 --- include/nand.h | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'include/nand.h') diff --git a/include/nand.h b/include/nand.h index 905115b3da..5c7311fd50 100644 --- a/include/nand.h +++ b/include/nand.h @@ -60,4 +60,61 @@ static inline int nand_erase(nand_info_t *info, ulong off, ulong size) return info->erase(info, &instr); } + +/***************************************************************************** + * declarations from nand_util.c + ****************************************************************************/ + +struct nand_write_options { + u_char *buffer; /* memory block containing image to write */ + ulong length; /* number of bytes to write */ + ulong offset; /* start address in NAND */ + int quiet; /* don't display progress messages */ + int autoplace; /* if true use auto oob layout */ + int forcejffs2; /* force jffs2 oob layout */ + int forceyaffs; /* force yaffs oob layout */ + int noecc; /* write without ecc */ + int writeoob; /* image contains oob data */ + int pad; /* pad to page size */ + int blockalign; /* 1|2|4 set multiple of eraseblocks + * to align to */ +}; + +typedef struct nand_write_options nand_write_options_t; + +struct nand_read_options { + u_char *buffer; /* memory block in which read image is written*/ + ulong length; /* number of bytes to read */ + ulong offset; /* start address in NAND */ + int quiet; /* don't display progress messages */ + int readoob; /* put oob data in image */ +}; + +typedef struct nand_read_options nand_read_options_t; + +struct nand_erase_options { + ulong length; /* number of bytes to erase */ + ulong offset; /* first address in NAND to erase */ + int quiet; /* don't display progress messages */ + int jffs2; /* if true: format for jffs2 usage + * (write appropriate cleanmarker blocks) */ + int scrub; /* if true, really clean NAND by erasing + * bad blocks (UNSAFE) */ +}; + +typedef struct nand_erase_options nand_erase_options_t; + +int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts); + +int nand_read_opts(nand_info_t *meminfo, const nand_read_options_t *opts); +int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts); + +#define NAND_LOCK_STATUS_TIGHT 0x01 +#define NAND_LOCK_STATUS_LOCK 0x02 +#define NAND_LOCK_STATUS_UNLOCK 0x04 + +int nand_lock( nand_info_t *meminfo, int tight ); +int nand_unlock( nand_info_t *meminfo, ulong start, ulong length ); +int nand_get_lock_status(nand_info_t *meminfo, ulong offset); + #endif -- cgit v1.2.3 From 43a2b0e76a56995f17e1b7628c192ebafe6051ee Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Fri, 20 Oct 2006 14:28:52 +0200 Subject: Add board/cpu specific NAND chip select function to 440 NDFC Based on idea and implementation from Jeff Mann Patch by Stefan Roese, 20 Oct 2006 --- CHANGELOG | 4 ++++ common/cmd_nand.c | 8 ++++++++ cpu/ppc4xx/ndfc.c | 39 ++++++++++++++++++++++++++------------- drivers/nand/nand.c | 9 ++++++++- include/configs/sequoia.h | 15 ++++++++------- include/nand.h | 4 ++++ 6 files changed, 58 insertions(+), 21 deletions(-) (limited to 'include/nand.h') diff --git a/CHANGELOG b/CHANGELOG index 71096e875f..6ff1f9b37e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -7,6 +7,10 @@ Changes since U-Boot 1.1.4: * Add (preliminary) support for V38B board +* Add board/cpu specific NAND chip select function to 440 NDFC + Based on idea and implementation from Jeff Mann + Patch by Stefan Roese, 20 Oct 2006 + * PPC405EP: Add support for board configuration of CPC0_PCI register This is needed to be able to configure PerWE*/PCI_INT* pin as PerWE* Patch by Tolunay Orkun, 07 Apr 2006 diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 7042a9c226..4fb3b65960 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -178,6 +178,14 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) printf("Device %d: %s", dev, nand_info[dev].name); puts("... is now current device\n"); nand_curr_device = dev; + +#ifdef CFG_NAND_SELECT_DEVICE + /* + * Select the chip in the board/cpu specific driver + */ + board_nand_select_device(nand_info[dev].priv, dev); +#endif + return 0; } diff --git a/cpu/ppc4xx/ndfc.c b/cpu/ppc4xx/ndfc.c index 183ab5ef16..2c44111da6 100644 --- a/cpu/ppc4xx/ndfc.c +++ b/cpu/ppc4xx/ndfc.c @@ -66,7 +66,7 @@ static void ndfc_hwcontrol(struct mtd_info *mtdinfo, int cmd) static void ndfc_write_byte(struct mtd_info *mtdinfo, u_char byte) { struct nand_chip *this = mtdinfo->priv; - ulong base = (ulong) this->IO_ADDR_W; + ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; if (hwctl & 0x1) out8(base + NDFC_CMD, byte); @@ -79,7 +79,7 @@ static void ndfc_write_byte(struct mtd_info *mtdinfo, u_char byte) static u_char ndfc_read_byte(struct mtd_info *mtdinfo) { struct nand_chip *this = mtdinfo->priv; - ulong base = (ulong) this->IO_ADDR_W; + ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; return (in8(base + NDFC_DATA)); } @@ -87,7 +87,7 @@ static u_char ndfc_read_byte(struct mtd_info *mtdinfo) static int ndfc_dev_ready(struct mtd_info *mtdinfo) { struct nand_chip *this = mtdinfo->priv; - ulong base = (ulong) this->IO_ADDR_W; + ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; while (!(in32(base + NDFC_STAT) & NDFC_STAT_IS_READY)) ; @@ -111,30 +111,30 @@ static int ndfc_dev_ready(struct mtd_info *mtdinfo) static void ndfc_read_buf(struct mtd_info *mtdinfo, uint8_t *buf, int len) { struct nand_chip *this = mtdinfo->priv; - ulong base = (ulong) this->IO_ADDR_W; + ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; uint32_t *p = (uint32_t *) buf; - for(;len > 0; len -= 4) + for (;len > 0; len -= 4) *p++ = in32(base + NDFC_DATA); } static void ndfc_write_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len) { struct nand_chip *this = mtdinfo->priv; - ulong base = (ulong) this->IO_ADDR_W; + ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; uint32_t *p = (uint32_t *) buf; - for(; len > 0; len -= 4) + for (; len > 0; len -= 4) out32(base + NDFC_DATA, *p++); } static int ndfc_verify_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len) { struct nand_chip *this = mtdinfo->priv; - ulong base = (ulong) this->IO_ADDR_W; + ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; uint32_t *p = (uint32_t *) buf; - for(; len > 0; len -= 4) + for (; len > 0; len -= 4) if (*p++ != in32(base + NDFC_DATA)) return -1; @@ -142,8 +142,20 @@ static int ndfc_verify_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len } #endif /* #ifndef CONFIG_NAND_SPL */ +void board_nand_select_device(struct nand_chip *nand, int chip) +{ + ulong base = (ulong)nand->IO_ADDR_W & 0xfffffffc; + + /* Set NandFlash Core Configuration Register */ + /* 1col x 2 rows */ + out32(base + NDFC_CCR, 0x00000000 | (chip << 24)); +} + void board_nand_init(struct nand_chip *nand) { + int chip = (ulong)nand->IO_ADDR_W & 0x00000003; + ulong base = (ulong)nand->IO_ADDR_W & 0xfffffffc; + nand->eccmode = NAND_ECC_SOFT; nand->hwcontrol = ndfc_hwcontrol; @@ -166,10 +178,11 @@ void board_nand_init(struct nand_chip *nand) mtebc(pb0ap, CFG_EBC_PB0AP); #endif - /* Set NandFlash Core Configuration Register */ - /* Chip select 3, 1col x 2 rows */ - out32(CFG_NAND_BASE + NDFC_CCR, 0x00000000 | (CFG_NAND_CS << 24)); - out32(CFG_NAND_BASE + NDFC_BCFG0 + (CFG_NAND_CS << 2), 0x80002222); + /* + * Select required NAND chip in NDFC + */ + board_nand_select_device(nand, chip); + out32(base + NDFC_BCFG0 + (chip << 2), 0x80002222); } #endif diff --git a/drivers/nand/nand.c b/drivers/nand/nand.c index e1781fcbbf..3899045a72 100644 --- a/drivers/nand/nand.c +++ b/drivers/nand/nand.c @@ -66,8 +66,15 @@ void nand_init(void) size += nand_info[i].size; if (nand_curr_device == -1) nand_curr_device = i; -} + } printf("%lu MiB\n", size / (1024 * 1024)); + +#ifdef CFG_NAND_SELECT_DEVICE + /* + * Select the chip in the board/cpu specific driver + */ + board_nand_select_device(nand_info[nand_curr_device].priv, nand_curr_device); +#endif } #endif diff --git a/include/configs/sequoia.h b/include/configs/sequoia.h index f67fd9163d..3a76315b44 100644 --- a/include/configs/sequoia.h +++ b/include/configs/sequoia.h @@ -134,13 +134,6 @@ #define CFG_ENV_SIZE_REDUND (CFG_ENV_SIZE) #endif -/*----------------------------------------------------------------------- - * NAND FLASH - *----------------------------------------------------------------------*/ -#define CFG_MAX_NAND_DEVICE 1 -#define NAND_MAX_CHIPS 1 -#define CFG_NAND_BASE CFG_NAND_ADDR - /* * IPL (Initial Program Loader, integrated inside CPU) * Will load first 4k from NAND (SPL) into cache and execute it from there. @@ -405,6 +398,14 @@ #define CFG_EBC_PB2AP 0x24814580 #define CFG_EBC_PB2CR (CFG_CPLD | 0x38000) +/*----------------------------------------------------------------------- + * NAND FLASH + *----------------------------------------------------------------------*/ +#define CFG_MAX_NAND_DEVICE 1 +#define NAND_MAX_CHIPS 1 +#define CFG_NAND_BASE (CFG_NAND_ADDR + CFG_NAND_CS) +#define CFG_NAND_SELECT_DEVICE 1 /* nand driver supports mutipl. chips */ + /*----------------------------------------------------------------------- * Cache Configuration *----------------------------------------------------------------------*/ diff --git a/include/nand.h b/include/nand.h index 5c7311fd50..23493f7e98 100644 --- a/include/nand.h +++ b/include/nand.h @@ -117,4 +117,8 @@ int nand_lock( nand_info_t *meminfo, int tight ); int nand_unlock( nand_info_t *meminfo, ulong start, ulong length ); int nand_get_lock_status(nand_info_t *meminfo, ulong offset); +#ifdef CFG_NAND_SELECT_DEVICE +void board_nand_select_device(struct nand_chip *nand, int chip); +#endif + #endif -- cgit v1.2.3