* borrowed heavily from:
* (c) 1999 Machine Vision Holdings, Inc.
* (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
- *
*/
#include <common.h>
#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
*/
#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
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);
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");
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.
}
/* 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;
/* ------------------------------------------------------------------------- */
-/* 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;
}
/* 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 */
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} */
{
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
/* 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
*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);
out:
/* De-select the NAND device */
NAND_DISABLE_CE(nand); /* set pin high */
-
+#ifdef CONFIG_OMAP1510
+ archflashwp(0,1);
+#endif
return ret;
}
* 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;
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 */
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 */
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);
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);
out:
/* De-select the NAND device */
NAND_DISABLE_CE(nand); /* set pin high */
-
+#ifdef CONFIG_OMAP1510
+ archflashwp(0,1);
+#endif
return ret;
}
/* Should never happen */
return -1;
}
+
#endif
#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */