X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=nand_spl%2Fnand_boot.c;h=125e7f3714cd8fe655b50b44d2ef9bb5722166d0;hb=2bf36ac638ab2db9f0295aa47064976eeebf80c1;hp=46285241e18bf9294036a886706e57403cb391a1;hpb=8370978318337df3979aa0852529d53d77ed736e;p=u-boot diff --git a/nand_spl/nand_boot.c b/nand_spl/nand_boot.c index 46285241e1..125e7f3714 100644 --- a/nand_spl/nand_boot.c +++ b/nand_spl/nand_boot.c @@ -2,31 +2,20 @@ * (C) Copyright 2006-2008 * Stefan Roese, DENX Software Engineering, sr@denx.de. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include -#define CONFIG_SYS_NAND_READ_DELAY \ - { volatile int dummy; int i; for (i=0; i<10000; i++) dummy = i; } - static int nand_ecc_pos[] = CONFIG_SYS_NAND_ECCPOS; +#define ECCSTEPS (CONFIG_SYS_NAND_PAGE_SIZE / \ + CONFIG_SYS_NAND_ECCSIZE) +#define ECCTOTAL (ECCSTEPS * CONFIG_SYS_NAND_ECCBYTES) + + #if (CONFIG_SYS_NAND_PAGE_SIZE <= 512) /* * NAND command for small page NAND devices (512) @@ -36,11 +25,8 @@ static int nand_command(struct mtd_info *mtd, int block, int page, int offs, u8 struct nand_chip *this = mtd->priv; int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT; - if (this->dev_ready) - while (!this->dev_ready(mtd)) - ; - else - CONFIG_SYS_NAND_READ_DELAY; + while (!this->dev_ready(mtd)) + ; /* Begin command latch cycle */ this->cmd_ctrl(mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE); @@ -61,11 +47,8 @@ static int nand_command(struct mtd_info *mtd, int block, int page, int offs, u8 /* * Wait a while for the data to be ready */ - if (this->dev_ready) - while (!this->dev_ready(mtd)) - ; - else - CONFIG_SYS_NAND_READ_DELAY; + while (!this->dev_ready(mtd)) + ; return 0; } @@ -80,11 +63,8 @@ static int nand_command(struct mtd_info *mtd, int block, int page, int offs, u8 void (*hwctrl)(struct mtd_info *mtd, int cmd, unsigned int ctrl) = this->cmd_ctrl; - if (this->dev_ready) - while (!this->dev_ready(mtd)) - ; - else - CONFIG_SYS_NAND_READ_DELAY; + while (!this->dev_ready(mtd)) + ; /* Emulate NAND_CMD_READOOB */ if (cmd == NAND_CMD_READOOB) { @@ -120,11 +100,8 @@ static int nand_command(struct mtd_info *mtd, int block, int page, int offs, u8 /* * Wait a while for the data to be ready */ - if (this->dev_ready) - while (!this->dev_ready(mtd)) - ; - else - CONFIG_SYS_NAND_READ_DELAY; + while (!this->dev_ready(mtd)) + ; return 0; } @@ -137,35 +114,64 @@ static int nand_is_bad_block(struct mtd_info *mtd, int block) nand_command(mtd, block, 0, CONFIG_SYS_NAND_BAD_BLOCK_POS, NAND_CMD_READOOB); /* - * Read one byte + * Read one byte (or two if it's a 16 bit chip). */ - if (readb(this->IO_ADDR_R) != 0xff) - return 1; + if (this->options & NAND_BUSWIDTH_16) { + if (readw(this->IO_ADDR_R) != 0xffff) + return 1; + } else { + if (readb(this->IO_ADDR_R) != 0xff) + return 1; + } return 0; } +#if defined(CONFIG_SYS_NAND_4BIT_HW_ECC_OOBFIRST) static int nand_read_page(struct mtd_info *mtd, int block, int page, uchar *dst) { struct nand_chip *this = mtd->priv; - u_char *ecc_calc; - u_char *ecc_code; - u_char *oob_data; + u_char ecc_calc[ECCTOTAL]; + u_char ecc_code[ECCTOTAL]; + u_char oob_data[CONFIG_SYS_NAND_OOBSIZE]; int i; int eccsize = CONFIG_SYS_NAND_ECCSIZE; int eccbytes = CONFIG_SYS_NAND_ECCBYTES; - int eccsteps = CONFIG_SYS_NAND_ECCSTEPS; + int eccsteps = ECCSTEPS; uint8_t *p = dst; - int stat; + nand_command(mtd, block, page, 0, NAND_CMD_READOOB); + this->read_buf(mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE); nand_command(mtd, block, page, 0, NAND_CMD_READ0); - /* No malloc available for now, just use some temporary locations - * in SDRAM - */ - ecc_calc = (u_char *)(CONFIG_SYS_SDRAM_BASE + 0x10000); - ecc_code = ecc_calc + 0x100; - oob_data = ecc_calc + 0x200; + /* Pick the ECC bytes out of the oob data */ + for (i = 0; i < ECCTOTAL; i++) + ecc_code[i] = oob_data[nand_ecc_pos[i]]; + + + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { + this->ecc.hwctl(mtd, NAND_ECC_READ); + this->read_buf(mtd, p, eccsize); + this->ecc.calculate(mtd, p, &ecc_calc[i]); + this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); + } + + return 0; +} +#else +static int nand_read_page(struct mtd_info *mtd, int block, int page, uchar *dst) +{ + struct nand_chip *this = mtd->priv; + u_char ecc_calc[ECCTOTAL]; + u_char ecc_code[ECCTOTAL]; + u_char oob_data[CONFIG_SYS_NAND_OOBSIZE]; + int i; + int eccsize = CONFIG_SYS_NAND_ECCSIZE; + int eccbytes = CONFIG_SYS_NAND_ECCBYTES; + int eccsteps = ECCSTEPS; + uint8_t *p = dst; + + nand_command(mtd, block, page, 0, NAND_CMD_READ0); for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { this->ecc.hwctl(mtd, NAND_ECC_READ); @@ -175,10 +181,10 @@ static int nand_read_page(struct mtd_info *mtd, int block, int page, uchar *dst) this->read_buf(mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE); /* Pick the ECC bytes out of the oob data */ - for (i = 0; i < CONFIG_SYS_NAND_ECCTOTAL; i++) + for (i = 0; i < ECCTOTAL; i++) ecc_code[i] = oob_data[nand_ecc_pos[i]]; - eccsteps = CONFIG_SYS_NAND_ECCSTEPS; + eccsteps = ECCSTEPS; p = dst; for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { @@ -186,11 +192,12 @@ static int nand_read_page(struct mtd_info *mtd, int block, int page, uchar *dst) * from correct_data(). We just hope that all possible errors * are corrected by this routine. */ - stat = this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); + this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); } return 0; } +#endif /* #if defined(CONFIG_SYS_NAND_4BIT_HW_ECC_OOBFIRST) */ static int nand_load(struct mtd_info *mtd, unsigned int offs, unsigned int uboot_size, uchar *dst) @@ -236,7 +243,6 @@ void nand_boot(void) { struct nand_chip nand_chip; nand_info_t nand_info; - int ret; __attribute__((noreturn)) void (*uboot)(void); /* @@ -246,6 +252,7 @@ void nand_boot(void) nand_info.priv = &nand_chip; nand_chip.IO_ADDR_R = nand_chip.IO_ADDR_W = (void __iomem *)CONFIG_SYS_NAND_BASE; nand_chip.dev_ready = NULL; /* preset to NULL */ + nand_chip.options = 0; board_nand_init(&nand_chip); if (nand_chip.select_chip) @@ -254,8 +261,8 @@ void nand_boot(void) /* * Load U-Boot image from NAND into RAM */ - ret = nand_load(&nand_info, CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE, - (uchar *)CONFIG_SYS_NAND_U_BOOT_DST); + nand_load(&nand_info, CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE, + (uchar *)CONFIG_SYS_NAND_U_BOOT_DST); #ifdef CONFIG_NAND_ENV_DST nand_load(&nand_info, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,