[U-Boot-Users] [RFC]Nand write/read without ecc

Terence Soh Terence.Soh at appliedbiosystems.com
Mon Jul 17 10:00:16 CEST 2006


Hi,

This patch is specifically for u-bootloader to program binaries generated 
by mkyaffsimage, for example, as these binaries includes the 16 bytes oob. 
All comments are appreciated.

Typical usage will be "nand write.noecc <source address> <Nand offset 
address> <size>".

Terence.

diff /data/src/u-boot-1.1.4/common/cmd_nand.c ./common/cmd_nand.c

8a9,12
>  *
>  * Added programming in both block and spare column area
>  * Specifically, it is meant for programming binary generated by 
mkyaffsimage
>  * (C) 2006 Applied Biosystems Instruments 
<terence.soh at appliedbiosystems.com>
70a75
> #define NANDRW_NOECC  0x08
93a99,105
> static int nand_write_noecc (struct nand_chip* nand, size_t to, size_t 
len,
>                          size_t * retlen, const u_char * buf);
> static int nand_read_noecc(struct nand_chip *nand, size_t start, size_t 
len,
>                size_t * retlen, u_char *buf);
> int nand_rw_noecc (struct nand_chip* nand, int cmd,
>           size_t start, size_t len,
>           size_t * retlen, u_char * buf);
98a111
> static int pages_per_block;
219a233,235
>               else if (cmdtail && !strncmp(cmdtail, ".noecc", 2)) {
>                       cmd |= NANDRW_NOECC;    /* read/write to OOB 
without ECC */
>               }
243,244c259,265
<               ret = nand_rw(nand_dev_desc + curr_device, cmd, off, size,
<                            (size_t *)&total, (u_char*)addr);
---
>               if(cmd & NANDRW_NOECC){
>                       ret = nand_rw_noecc(nand_dev_desc + curr_device, 
cmd, off, size,
>                                    &total, (u_char*)addr);
>               } else {
>                       ret = nand_rw(nand_dev_desc + curr_device, cmd, 
off, size,
>                                    &total, (u_char*)addr);
>               }
287a309,310
>       "nand read.noecc addr off size - read data without ECC"
>       "nand write.noecc addr off size - write data without ECC"
447a471,528
> /* Dealing in (nand->oobblock + nand->oobsize) i.e. 528, 2112... bytes 
per page */
> int nand_rw_noecc (struct nand_chip* nand, int cmd,
>           size_t start, size_t len,
>           size_t * retlen, u_char * buf)
> {
>       int ret = 0, n, total = 0;
>       unsigned long eblk;
> 
>       while (len) {
>               if (start%((nand->oobblock + 
nand->oobsize)*pages_per_block) == 0) {
>                       /* have crossed into new erase block, deal with
>                        * it if it is sure marked bad.
>                        */
>                       eblk = start/((nand->oobblock + 
nand->oobsize)*pages_per_block);
>                       eblk *= nand->oobblock;
>                       if (check_block(nand, eblk)) {
>                               if (cmd == (NANDRW_WRITE | NANDRW_NOECC)) 
{
>                                       start += ((nand->oobblock + 
nand->oobsize)*pages_per_block);
>                                       continue;
>                               }
>                       }
>               }
> 
>               if(cmd & NANDRW_NOECC){
>                       /* Start on 528/2112 bytes boundary */
>                       if(start%((nand->oobblock + nand->oobsize))){
>                               printf("\nError: Reading/Writing must 
start from %d byte page boundary, 0x%8X\n",
>                                       (nand->oobblock + 
nand->oobsize),start);
>                               return -1;
>                       }
>                       else{
>                               /* reading and writing without ECC */
>                               if (cmd & NANDRW_READ) {
>                                       ret = nand_read_noecc(nand, start,
>                                                       min(len, 
(nand->oobblock + nand->oobsize)*pages_per_block),
>                                                       &n, (u_char*)buf);
>                               } else {
>                                       ret = nand_write_noecc(nand, 
start,
>                                                       min(len, 
(nand->oobblock + nand->oobsize)*pages_per_block),
>                                                       &n, (u_char*)buf);
>                               }
>                       }
>               }
> 
>               if (ret)
>                       break;
> 
>               start  += n;
>               buf   += n;
>               total += n;
>               len   -= n;
>       }
>       if (retlen)
>               *retlen = total;
> 
>       return ret;
> }
> 
724a806
>                               pages_per_block = nand->erasesize / 
nand->oobblock;
878a961,1010
> /* Read entire page (without ECC) */
> static int nand_read_noecc(struct nand_chip *nand, size_t start, size_t 
len,
>                size_t * retlen, u_char *buf)
> {
>       int col, page;
> 
>       /* First we calculate the starting page */
>       /* Address here take spare area into account */
>       page = start / (nand->oobblock + nand->oobsize);
>       /* Get raw starting column */
>       col = start % (nand->oobblock + nand->oobsize);
> 
>       /* Initialize return value */
>       *retlen = 0;
>       NAND_ENABLE_CE(nand);           /* set pin low */
>       /* Loop until all data read */
>       while (*retlen < len) {
>               /* Send the read command */
>               NanD_Command(nand, NAND_CMD_READ0);
> 
>               /* Address to NAND flash don't take the spare area into 
account */
>               if (nand->bus16) {
>                       NanD_Address(nand, ADDR_COLUMN_PAGE,
>                                    (page * nand->oobblock) + (col >> 
1));
>               } else {
>                       NanD_Address(nand, ADDR_COLUMN_PAGE,
>                                    (page * nand->oobblock) + col);
>               }
> 
>               /* Read the data directly into the return buffer */
>               if ((*retlen + (nand->oobblock + nand->oobsize - col)) >= 
len) {
>                       NanD_ReadBuf(nand, buf + *retlen, len - *retlen);
>                       *retlen = len;
>                       /* We're done */
>                       continue;
>               } else {
>                       NanD_ReadBuf(nand, buf + *retlen, nand->oobblock + 
nand->oobsize - col);
>                       *retlen += nand->oobblock + nand->oobsize - col;
>               }
>               /* For subsequent reads align to page boundary. */
>               col = 0;
>               /* Increment page address */
>               page++;
>       }
>       /* De-select the NAND device */
>       NAND_DISABLE_CE(nand);          /* set pin high */
>       /* Always successful. No ECC */
>       return 0;
> }
> 
1247a1380,1457
> /* Write entire page (including out of bound area) */
> static int nand_write_noecc (struct nand_chip* nand, size_t to, size_t 
len,
>                          size_t * retlen, const u_char * buf)
> {
>       int i, page, col, ret, cnt = 0;
> 
>       /* Initialize return length value */
>       *retlen = 0;
>       ret = 0;
> 
>       /* Get page */
>       page = ((int) to) / (nand->oobblock + nand->oobsize);
>       /* Get the starting column. Should be zero */
>       col = to % (nand->oobblock + nand->oobsize);
> 
>       /* Loop until all data is written */
>       while (*retlen < len) {
>               /* Write data into buffer */
>               if ((col + len - *retlen) >= (nand->oobblock + 
nand->oobsize)) {
>                       /* >= (nand->oobblock + nand->oobsize) bytes to be 
written */
>                       for (i = col, cnt = 0; i < (nand->oobblock + 
nand->oobsize); i++, cnt++) {
>                               nand->data_buf[i] = buf[(*retlen + cnt)];
>                       }
>               } else {
>                       /* Less than (nand->oobblock + nand->oobsize) 
bytes to be written */
>                       for (i = col, cnt = 0; cnt < (len - *retlen); i++, 
cnt++) {
>                               nand->data_buf[i] = buf[(*retlen + cnt)];
>                       }
>               }
>               /* set pin low */
>               NAND_ENABLE_CE(nand);
>               NanD_Command (nand, NAND_CMD_SEQIN);
> 
>               if (nand->bus16) {
>                       NanD_Address (nand, ADDR_COLUMN_PAGE,
>                                     (page * nand->oobblock) + (col >> 
1));
>               } else {
>                       NanD_Address (nand, ADDR_COLUMN_PAGE,
>                                     (page * nand->oobblock) + col);
>               }
>               /* Write out complete page of data */
>               if (nand->bus16) {
>                       for (i = 0; i < cnt; i += 2) {
>                               WRITE_NAND (nand->data_buf[i] +
>                                           (nand->data_buf[i + 1] << 8),
>                                           nand->IO_ADDR);
>                       }
>               } else {
>                       /* Send command to begin auto page programming */
>                       for (i = 0; i < cnt ; i++)
>                               WRITE_NAND (nand->data_buf[i], 
nand->IO_ADDR);
>               }
>               /* Send command to actually program the data */
>               NanD_Command (nand, NAND_CMD_PAGEPROG);
>               NanD_Command (nand, NAND_CMD_STATUS);
> 
>               NAND_WAIT_READY(nand);
> 
>               /* See if device thinks it succeeded */
>               if(READ_NAND (nand->IO_ADDR) & 0x01) {
>                       printf ("%s: Failed write, page 0x%08x, ", 
__FUNCTION__,
>                               page);
>                       ret = -1;
>               }
> 
>               /* De-select the NAND device */
>               NAND_DISABLE_CE(nand);          /* set pin high */
> 
>               /* Next data start at page boundary */
>               col = 0;
>               /* Update written bytes count */
>               *retlen += cnt;
>               /* Increment page address */
>               page++;
>       }
>       return ret;
> }
> 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.denx.de/pipermail/u-boot/attachments/20060717/031d9aa2/attachment.htm 


More information about the U-Boot mailing list