[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