diff options
author | wdenk <wdenk> | 2003-07-27 00:21:01 +0000 |
---|---|---|
committer | wdenk <wdenk> | 2003-07-27 00:21:01 +0000 |
commit | 1f4bb37d6bcae59b18a2438f3cdca6545a831ab5 (patch) | |
tree | 7497d21e26ef058a329444c5703317148d7f9d69 /common/cmd_nand.c | |
parent | 7784674852c66b0924bdc79062bd208aa51fd0a9 (diff) | |
download | u-boot-imx-1f4bb37d6bcae59b18a2438f3cdca6545a831ab5.zip u-boot-imx-1f4bb37d6bcae59b18a2438f3cdca6545a831ab5.tar.gz u-boot-imx-1f4bb37d6bcae59b18a2438f3cdca6545a831ab5.tar.bz2 |
* Patch by Scott McNutt, 21 Jul 2003:
Add support for LynuxWorks Kernel Downloadable Images (KDIs).
Both LynxOS and BlueCat linux KDIs are supported.
* Patch by Richard Woodruff, 25 Jul 2003:
use more reliable reset for OMAP/925T
* Patch by Nye Liu, 25 Jul 2003:
fix typo in mpc8xx.h
* Patch by Richard Woodruff, 24 Jul 2003:
Fixes for cmd_nand.c:
- Fixed null dereferece which could result in incorrect ECC values.
- Added support for devices with no Ready/Busy signal hooked up.
- Added OMAP1510 read/write protect handling.
- Fixed nand.h's ECCPOS. A conflict existed with POS5 and badblock
for non-JFFS2.
- Switched default ECC to be JFFS2.
Diffstat (limited to 'common/cmd_nand.c')
-rw-r--r-- | common/cmd_nand.c | 114 |
1 files changed, 83 insertions, 31 deletions
diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 137f34f..ec76aa3 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -3,7 +3,6 @@ * borrowed heavily from: * (c) 1999 Machine Vision Holdings, Inc. * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org> - * */ #include <common.h> @@ -24,6 +23,12 @@ #include <linux/mtd/nand_ids.h> #include <jffs2/jffs2.h> +#ifdef CONFIG_OMAP1510 +void archflashwp(void *archdata, int wp); +#endif + +#define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) + /* * Definition of the out of band configuration structure */ @@ -52,7 +57,7 @@ struct nand_oob_config { #define ALLOW_ERASE_BAD_DEBUG 0 #define CONFIG_MTD_NAND_ECC /* enable ECC */ -/* #define CONFIG_MTD_NAND_ECC_JFFS2 */ +#define CONFIG_MTD_NAND_ECC_JFFS2 /* bits for nand_rw() `cmd'; or together as needed */ #define NANDRW_READ 0x01 @@ -76,6 +81,7 @@ static int nand_read_oob(struct nand_chip* nand, size_t ofs, size_t len, size_t * retlen, u_char * buf); static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len, size_t * retlen, const u_char * buf); +static int NanD_WaitReady(struct nand_chip *nand, int ale_wait); #ifdef CONFIG_MTD_NAND_ECC static int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc); static void nand_calculate_ecc (const u_char *dat, u_char *ecc_code); @@ -218,7 +224,7 @@ int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) ret = nand_rw(nand_dev_desc + curr_device, cmd, off, size, &total, (u_char*)addr); - printf ("%d bytes %s: %s\n", total, + printf (" %d bytes %s: %s\n", total, (cmd & NANDRW_READ) ? "read" : "write", ret ? "ERROR" : "OK"); @@ -419,7 +425,7 @@ static int nand_rw (struct nand_chip* nand, int cmd, size_t start, size_t len, size_t * retlen, u_char * buf) { - int noecc, ret = 0, n, total = 0; + int ret = 0, n, total = 0; char eccbuf[6]; /* eblk (once set) is the start of the erase block containing the * data being processed. @@ -457,17 +463,18 @@ static int nand_rw (struct nand_chip* nand, int cmd, } /* The ECC will not be calculated correctly if less than 512 is written or read */ - noecc = (start != (start | 0x1ff) + 1) || (len < 0x200); + /* Is request at least 512 bytes AND it starts on a proper boundry */ + if((start != ROUND_DOWN(start, 0x200)) || (len < 0x200)) + printf("Warning block writes should be at least 512 bytes and start on a 512 byte boundry\n"); + if (cmd & NANDRW_READ) ret = nand_read_ecc(nand, start, min(len, eblk + erasesize - start), - &n, (u_char*)buf, - noecc ? NULL : eccbuf); + &n, (u_char*)buf, eccbuf); else ret = nand_write_ecc(nand, start, min(len, eblk + erasesize - start), - &n, (u_char*)buf, - noecc ? NULL : eccbuf); + &n, (u_char*)buf, eccbuf); if (ret) break; @@ -502,19 +509,19 @@ static void nand_print(struct nand_chip *nand) /* ------------------------------------------------------------------------- */ -/* This function is needed to avoid calls of the __ashrdi3 function. */ -#if 0 -static int shr(int val, int shift) -{ - return val >> shift; -} -#endif -static int NanD_WaitReady(struct nand_chip *nand) +static int NanD_WaitReady(struct nand_chip *nand, int ale_wait) { /* This is inline, to optimise the common case, where it's ready instantly */ int ret = 0; - NAND_WAIT_READY(nand); +#ifdef NAND_NO_RB /* in config file, shorter delays currently wrap accesses */ + if(ale_wait) + NAND_WAIT_READY(nand); /* do the worst case 25us wait */ + else + udelay(10); +#else /* has functional r/b signal */ + NAND_WAIT_READY(nand); +#endif return ret; } @@ -533,7 +540,16 @@ static inline int NanD_Command(struct nand_chip *nand, unsigned char command) /* Lower the CLE line */ NAND_CTL_CLRCLE(nandptr); - return NanD_WaitReady(nand); +#ifdef NAND_NO_RB + if(command == NAND_CMD_RESET){ + u_char ret_val; + NanD_Command(nand, NAND_CMD_STATUS); + do{ + ret_val = READ_NAND(nandptr);/* wait till ready */ + } while((ret_val & 0x40) != 0x40); + } +#endif + return NanD_WaitReady(nand, 0); } /* NanD_Address: Set the current address for the flash chip */ @@ -573,7 +589,7 @@ static int NanD_Address(struct nand_chip *nand, int numbytes, unsigned long ofs) NAND_CTL_CLRALE(nandptr); /* Wait for the chip to respond */ - return NanD_WaitReady(nand); + return NanD_WaitReady(nand, 1); } /* NanD_SelectChip: Select a given flash chip within the current floor */ @@ -581,7 +597,7 @@ static int NanD_Address(struct nand_chip *nand, int numbytes, unsigned long ofs) static inline int NanD_SelectChip(struct nand_chip *nand, int chip) { /* Wait for it to be ready */ - return NanD_WaitReady(nand); + return NanD_WaitReady(nand, 0); } /* NanD_IdentChip: Identify a given NAND chip given {floor,chip} */ @@ -931,8 +947,8 @@ static int nand_write_page (struct nand_chip *nand, { int i; -#ifdef CONFIG_MTD_NAND_ECC unsigned long nandptr = nand->IO_ADDR; +#ifdef CONFIG_MTD_NAND_ECC #ifdef CONFIG_MTD_NAND_VERIFY_WRITE int ecc_bytes = (nand->oobblock == 512) ? 6 : 3; #endif @@ -992,12 +1008,20 @@ static int nand_write_page (struct nand_chip *nand, /* Send command to actually program the data */ NanD_Command(nand, NAND_CMD_PAGEPROG); NanD_Command(nand, NAND_CMD_STATUS); +#ifdef NAND_NO_RB + { u_char ret_val; + do{ + ret_val = READ_NAND(nandptr); /* wait till ready */ + } while((ret_val & 0x40) != 0x40); + } +#endif /* See if device thinks it succeeded */ if (READ_NAND(nand->IO_ADDR) & 0x01) { printf ("%s: Failed write, page 0x%08x, ", __FUNCTION__, page); return -1; } + #ifdef CONFIG_MTD_NAND_VERIFY_WRITE /* * The NAND device assumes that it is always writing to @@ -1069,7 +1093,10 @@ static int nand_write_ecc (struct nand_chip* nand, size_t to, size_t len, *retlen = 0; /* Select the NAND device */ - NAND_ENABLE_CE(nand); /* set pin low */ +#ifdef CONFIG_OMAP1510 + archflashwp(0,0); +#endif + NAND_ENABLE_CE(nand); /* set pin low */ /* Check the WP bit */ NanD_Command(nand, NAND_CMD_STATUS); @@ -1113,7 +1140,9 @@ static int nand_write_ecc (struct nand_chip* nand, size_t to, size_t len, out: /* De-select the NAND device */ NAND_DISABLE_CE(nand); /* set pin high */ - +#ifdef CONFIG_OMAP1510 + archflashwp(0,1); +#endif return ret; } @@ -1160,7 +1189,7 @@ static int nand_read_oob(struct nand_chip* nand, size_t ofs, size_t len, * causing the flash device to go into busy mode, so we need * to wait until ready 11.4.1 and Toshiba TC58256FT nands */ - ret = NanD_WaitReady(nand); + ret = NanD_WaitReady(nand, 1); NAND_DISABLE_CE(nand); /* set pin high */ return ret; @@ -1215,8 +1244,13 @@ static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len, NanD_Command(nand, NAND_CMD_PAGEPROG); NanD_Command(nand, NAND_CMD_STATUS); - /* NanD_WaitReady() is implicit in NanD_Command */ - +#ifdef NAND_NO_RB + { u_char ret_val; + do{ + ret_val = READ_NAND(nandptr); /* wait till ready */ + }while((ret_val & 0x40) != 0x40); + } +#endif if (READ_NAND(nandptr) & 1) { puts ("Error programming oob data\n"); /* There was an error */ @@ -1233,8 +1267,13 @@ static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len, NanD_Command(nand, NAND_CMD_PAGEPROG); NanD_Command(nand, NAND_CMD_STATUS); - /* NanD_WaitReady() is implicit in NanD_Command */ - +#ifdef NAND_NO_RB + { u_char ret_val; + do{ + ret_val = READ_NAND(nandptr); /* wait till ready */ + } while((ret_val & 0x40) != 0x40); + } +#endif if (READ_NAND(nandptr) & 1) { puts ("Error programming oob data\n"); /* There was an error */ @@ -1272,7 +1311,10 @@ static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean) nandptr = nand->IO_ADDR; /* Select the NAND device */ - NAND_ENABLE_CE(nand); /* set pin low */ +#ifdef CONFIG_OMAP1510 + archflashwp(0,0); +#endif + NAND_ENABLE_CE(nand); /* set pin low */ /* Check the WP bit */ NanD_Command(nand, NAND_CMD_STATUS); @@ -1308,6 +1350,13 @@ static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean) NanD_Command(nand, NAND_CMD_STATUS); +#ifdef NAND_NO_RB + { u_char ret_val; + do{ + ret_val = READ_NAND(nandptr); /* wait till ready */ + } while((ret_val & 0x40) != 0x40); + } +#endif if (READ_NAND(nandptr) & 1) { printf ("%s: Error erasing at 0x%lx\n", __FUNCTION__, (long)ofs); @@ -1346,7 +1395,9 @@ static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean) out: /* De-select the NAND device */ NAND_DISABLE_CE(nand); /* set pin high */ - +#ifdef CONFIG_OMAP1510 + archflashwp(0,1); +#endif return ret; } @@ -1596,5 +1647,6 @@ static int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc) /* Should never happen */ return -1; } + #endif #endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */ |