forked from Xilinx/u-boot-xlnx
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* 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.
- Loading branch information
wdenk
committed
Jul 27, 2003
1 parent
7784674
commit 1f4bb37
Showing
13 changed files
with
314 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,6 @@ | |
* borrowed heavily from: | ||
* (c) 1999 Machine Vision Holdings, Inc. | ||
* (c) 1999, 2000 David Woodhouse <[email protected]> | ||
* | ||
*/ | ||
|
||
#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,15 +589,15 @@ 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 */ | ||
|
||
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) */ |
Oops, something went wrong.