From fcb774777562bb7bcdc53c608d0e6bae906ce0f6 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 28 Apr 2009 13:19:50 -0700 Subject: davinci_nand: cleanup I (minor) Minor cleanup for DaVinci NAND code: - Use I/O addresses from nand_chip; CONFIG_SYS_NAND_BASE won't be defined when there are multiple chipselect lines in use (as with common 2 GByte chips). - Cleanup handling of EMIF control registers * Only need one pointer pointing to them * Remove incorrect and unused struct supersetting them - Use the standard waitfunc; we don't need a custom version - Partial legacy cleanup: * Don't initialize every board like it's a DM6446 EVM * #ifdef a bit more code for BROKEN_ECC Sanity checked with small page NAND on dm355 and dm6446 EVMs; and large page on dm355 EVM (packaged as two devices, not one). Signed-off-by: David Brownell Signed-off-by: Scott Wood --- drivers/mtd/nand/davinci_nand.c | 55 +++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 33 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 8ef18b8..8b22024 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -49,6 +49,8 @@ extern struct nand_chip nand_dev_desc[CONFIG_SYS_MAX_NAND_DEVICE]; +static emif_registers *const emif_regs = (void *) DAVINCI_ASYNC_EMIF_CNTRL_BASE; + static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *this = mtd->priv; @@ -115,34 +117,31 @@ static struct nand_ecclayout davinci_nand_ecclayout = { static void nand_davinci_enable_hwecc(struct mtd_info *mtd, int mode) { - emifregs emif_addr; int dummy; - emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; - - dummy = emif_addr->NANDF1ECC; - dummy = emif_addr->NANDF2ECC; - dummy = emif_addr->NANDF3ECC; - dummy = emif_addr->NANDF4ECC; + dummy = emif_regs->NANDF1ECC; +#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC + dummy = emif_regs->NANDF2ECC; + dummy = emif_regs->NANDF3ECC; + dummy = emif_regs->NANDF4ECC; +#endif - emif_addr->NANDFCR |= (1 << 8); + /* FIXME: only chipselect 0 is supported for now */ + emif_regs->NANDFCR |= 1 << 8; } static u_int32_t nand_davinci_readecc(struct mtd_info *mtd, u_int32_t region) { u_int32_t ecc = 0; - emifregs emif_base_addr; - - emif_base_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; if (region == 1) - ecc = emif_base_addr->NANDF1ECC; + ecc = emif_regs->NANDF1ECC; else if (region == 2) - ecc = emif_base_addr->NANDF2ECC; + ecc = emif_regs->NANDF2ECC; else if (region == 3) - ecc = emif_base_addr->NANDF3ECC; + ecc = emif_regs->NANDF3ECC; else if (region == 4) - ecc = emif_base_addr->NANDF4ECC; + ecc = emif_regs->NANDF4ECC; return(ecc); } @@ -369,24 +368,18 @@ static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char * static int nand_davinci_dev_ready(struct mtd_info *mtd) { - emifregs emif_addr; - - emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; - - return(emif_addr->NANDFSR & 0x1); -} - -static int nand_davinci_waitfunc(struct mtd_info *mtd, struct nand_chip *this) -{ - while(!nand_davinci_dev_ready(mtd)) {;} - *NAND_CE0CLE = NAND_STATUS; - return(*NAND_CE0DATA); + return emif_regs->NANDFSR & 0x1; } static void nand_flash_init(void) { + /* This is for DM6446 EVM and *very* similar. DO NOT GROW THIS! + * Instead, have your board_init() set EMIF timings, based on its + * knowledge of the clocks and what devices are hooked up ... and + * don't even do that unless no UBL handled it. + */ +#ifdef CONFIG_SOC_DM6446 u_int32_t acfg1 = 0x3ffffffc; - emifregs emif_regs; /*------------------------------------------------------------------* * NAND FLASH CHIP TIMEOUT @ 459 MHz * @@ -408,17 +401,14 @@ static void nand_flash_init(void) | (0 << 0 ) /* asyncSize 8-bit bus */ ; - emif_regs = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; - emif_regs->AB1CR = acfg1; /* CS2 */ emif_regs->NANDFCR = 0x00000101; /* NAND flash on CS2 */ +#endif } int board_nand_init(struct nand_chip *nand) { - nand->IO_ADDR_R = (void __iomem *)NAND_CE0DATA; - nand->IO_ADDR_W = (void __iomem *)NAND_CE0DATA; nand->chip_delay = 0; nand->select_chip = nand_davinci_select_chip; #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT @@ -452,7 +442,6 @@ int board_nand_init(struct nand_chip *nand) nand->cmd_ctrl = nand_davinci_hwcontrol; nand->dev_ready = nand_davinci_dev_ready; - nand->waitfunc = nand_davinci_waitfunc; nand_flash_init(); -- cgit v1.1 From 6e29ed8e576a6900c5d8dcde36b423ac576894dc Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 28 Apr 2009 13:19:53 -0700 Subject: davinci_nand: cleanup II (CONFIG_SYS_DAVINCI_BROKEN_ECC) Remove CONFIG_SYS_DAVINCI_BROKEN_ECC option. It's not just nasty; it's also unused by any current boards, and doesn't even match the main U-Boot distributions from TI (which use soft ECC, or 4-bit ECC on newer chips that support it). DaVinci GIT kernels since 2.6.24, and mainline Linux since 2.6.30, match non-BROKEN code paths for 1-bit HW ECC. The BROKEN code paths do seem to partially match what MontaVista/TI kernels (4.0/2.6.10, and 5.0/2.6.18) do ... but only for small pages. Large page support is really broken (and it's unclear just what software it was trying to match!), and the ECC layout was making three more bytes available for use by filesystem (or whatever) code. Since this option itself seems broken, remove it. Add a comment about the MV/TI compat issue, and the most straightforward way to address it (should someone really need to solve it). Signed-off-by: David Brownell Signed-off-by: Scott Wood --- drivers/mtd/nand/davinci_nand.c | 218 +++------------------------------------- 1 file changed, 13 insertions(+), 205 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 8b22024..9e7b9dd 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -86,45 +86,12 @@ static void nand_davinci_select_chip(struct mtd_info *mtd, int chip) } #ifdef CONFIG_SYS_NAND_HW_ECC -#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC -/* Linux-compatible ECC uses MTD defaults. */ -/* These layouts are not compatible with Linux or RBL/UBL. */ -#ifdef CONFIG_SYS_NAND_LARGEPAGE -static struct nand_ecclayout davinci_nand_ecclayout = { - .eccbytes = 12, - .eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58}, - .oobfree = { - {.offset = 2, .length = 6}, - {.offset = 12, .length = 12}, - {.offset = 28, .length = 12}, - {.offset = 44, .length = 12}, - {.offset = 60, .length = 4} - } -}; -#elif defined(CONFIG_SYS_NAND_SMALLPAGE) -static struct nand_ecclayout davinci_nand_ecclayout = { - .eccbytes = 3, - .eccpos = {0, 1, 2}, - .oobfree = { - {.offset = 6, .length = 2}, - {.offset = 8, .length = 8} - } -}; -#else -#error "Either CONFIG_SYS_NAND_LARGEPAGE or CONFIG_SYS_NAND_SMALLPAGE must be defined!" -#endif -#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ static void nand_davinci_enable_hwecc(struct mtd_info *mtd, int mode) { int dummy; dummy = emif_regs->NANDF1ECC; -#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC - dummy = emif_regs->NANDF2ECC; - dummy = emif_regs->NANDF3ECC; - dummy = emif_regs->NANDF4ECC; -#endif /* FIXME: only chipselect 0 is supported for now */ emif_regs->NANDFCR |= 1 << 8; @@ -149,29 +116,6 @@ static u_int32_t nand_davinci_readecc(struct mtd_info *mtd, u_int32_t region) static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) { u_int32_t tmp; -#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC - /* - * This is not how you should read ECCs on large page Davinci devices. - * The region parameter gets you ECCs for flash chips on different chip - * selects, not the 4x512 byte pages in a 2048 byte page. - * - * Preserved for backwards compatibility though. - */ - - int region, n; - struct nand_chip *this = mtd->priv; - - n = (this->ecc.size/512); - - region = 1; - while (n--) { - tmp = nand_davinci_readecc(mtd, region); - *ecc_code++ = tmp; - *ecc_code++ = tmp >> 16; - *ecc_code++ = ((tmp >> 8) & 0x0f) | ((tmp >> 20) & 0xf0); - region++; - } -#else const int region = 1; tmp = nand_davinci_readecc(mtd, region); @@ -186,148 +130,26 @@ static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u *ecc_code++ = tmp; *ecc_code++ = tmp >> 8; *ecc_code++ = tmp >> 16; -#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ - return(0); -} - -#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC -static void nand_davinci_gen_true_ecc(u_int8_t *ecc_buf) -{ - u_int32_t tmp = ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xf0) << 20) | ((ecc_buf[2] & 0x0f) << 8); - - ecc_buf[0] = ~(P64o(tmp) | P64e(tmp) | P32o(tmp) | P32e(tmp) | P16o(tmp) | P16e(tmp) | P8o(tmp) | P8e(tmp)); - ecc_buf[1] = ~(P1024o(tmp) | P1024e(tmp) | P512o(tmp) | P512e(tmp) | P256o(tmp) | P256e(tmp) | P128o(tmp) | P128e(tmp)); - ecc_buf[2] = ~( P4o(tmp) | P4e(tmp) | P2o(tmp) | P2e(tmp) | P1o(tmp) | P1e(tmp) | P2048o(tmp) | P2048e(tmp)); -} - -static int nand_davinci_compare_ecc(u_int8_t *ecc_nand, u_int8_t *ecc_calc, u_int8_t *page_data) -{ - u_int32_t i; - u_int8_t tmp0_bit[8], tmp1_bit[8], tmp2_bit[8]; - u_int8_t comp0_bit[8], comp1_bit[8], comp2_bit[8]; - u_int8_t ecc_bit[24]; - u_int8_t ecc_sum = 0; - u_int8_t find_bit = 0; - u_int32_t find_byte = 0; - int is_ecc_ff; - - is_ecc_ff = ((*ecc_nand == 0xff) && (*(ecc_nand + 1) == 0xff) && (*(ecc_nand + 2) == 0xff)); - - nand_davinci_gen_true_ecc(ecc_nand); - nand_davinci_gen_true_ecc(ecc_calc); - - for (i = 0; i <= 2; i++) { - *(ecc_nand + i) = ~(*(ecc_nand + i)); - *(ecc_calc + i) = ~(*(ecc_calc + i)); - } - - for (i = 0; i < 8; i++) { - tmp0_bit[i] = *ecc_nand % 2; - *ecc_nand = *ecc_nand / 2; - } - - for (i = 0; i < 8; i++) { - tmp1_bit[i] = *(ecc_nand + 1) % 2; - *(ecc_nand + 1) = *(ecc_nand + 1) / 2; - } - - for (i = 0; i < 8; i++) { - tmp2_bit[i] = *(ecc_nand + 2) % 2; - *(ecc_nand + 2) = *(ecc_nand + 2) / 2; - } - for (i = 0; i < 8; i++) { - comp0_bit[i] = *ecc_calc % 2; - *ecc_calc = *ecc_calc / 2; - } - - for (i = 0; i < 8; i++) { - comp1_bit[i] = *(ecc_calc + 1) % 2; - *(ecc_calc + 1) = *(ecc_calc + 1) / 2; - } - - for (i = 0; i < 8; i++) { - comp2_bit[i] = *(ecc_calc + 2) % 2; - *(ecc_calc + 2) = *(ecc_calc + 2) / 2; - } - - for (i = 0; i< 6; i++) - ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2]; - - for (i = 0; i < 8; i++) - ecc_bit[i + 6] = tmp0_bit[i] ^ comp0_bit[i]; - - for (i = 0; i < 8; i++) - ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i]; - - ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0]; - ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1]; - - for (i = 0; i < 24; i++) - ecc_sum += ecc_bit[i]; + /* NOTE: the above code matches mainline Linux: + * .PQR.stu ==> ~PQRstu + * + * MontaVista/TI kernels encode those bytes differently, use + * complicated (and allegedly sometimes-wrong) correction code, + * and usually shipped with U-Boot that uses software ECC: + * .PQR.stu ==> PsQRtu + * + * If you need MV/TI compatible NAND I/O in U-Boot, it should + * be possible to (a) change the mangling above, (b) reverse + * that mangling in nand_davinci_correct_data() below. + */ - switch (ecc_sum) { - case 0: - /* Not reached because this function is not called if - ECC values are equal */ - return 0; - case 1: - /* Uncorrectable error */ - MTDDEBUG (MTD_DEBUG_LEVEL0, - "ECC UNCORRECTED_ERROR 1\n"); - return(-1); - case 12: - /* Correctable error */ - find_byte = (ecc_bit[23] << 8) + - (ecc_bit[21] << 7) + - (ecc_bit[19] << 6) + - (ecc_bit[17] << 5) + - (ecc_bit[15] << 4) + - (ecc_bit[13] << 3) + - (ecc_bit[11] << 2) + - (ecc_bit[9] << 1) + - ecc_bit[7]; - - find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1]; - - MTDDEBUG (MTD_DEBUG_LEVEL0, "Correcting single bit ECC " - "error at offset: %d, bit: %d\n", - find_byte, find_bit); - - page_data[find_byte] ^= (1 << find_bit); - - return(0); - default: - if (is_ecc_ff) { - if (ecc_calc[0] == 0 && ecc_calc[1] == 0 && ecc_calc[2] == 0) - return(0); - } - MTDDEBUG (MTD_DEBUG_LEVEL0, - "UNCORRECTED_ERROR default\n"); - return(-1); - } + return 0; } -#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) { struct nand_chip *this = mtd->priv; -#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC - int block_count = 0, i, rc; - - block_count = (this->ecc.size/512); - for (i = 0; i < block_count; i++) { - if (memcmp(read_ecc, calc_ecc, 3) != 0) { - rc = nand_davinci_compare_ecc(read_ecc, calc_ecc, dat); - if (rc < 0) { - return(rc); - } - } - read_ecc += 3; - calc_ecc += 3; - dat += 512; - } -#else u_int32_t ecc_nand = read_ecc[0] | (read_ecc[1] << 8) | (read_ecc[2] << 16); u_int32_t ecc_calc = calc_ecc[0] | (calc_ecc[1] << 8) | @@ -361,7 +183,6 @@ static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char * return -1; } } -#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ return(0); } #endif /* CONFIG_SYS_NAND_HW_ECC */ @@ -416,21 +237,8 @@ int board_nand_init(struct nand_chip *nand) #endif #ifdef CONFIG_SYS_NAND_HW_ECC nand->ecc.mode = NAND_ECC_HW; -#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC - nand->ecc.layout = &davinci_nand_ecclayout; -#ifdef CONFIG_SYS_NAND_LARGEPAGE - nand->ecc.size = 2048; - nand->ecc.bytes = 12; -#elif defined(CONFIG_SYS_NAND_SMALLPAGE) - nand->ecc.size = 512; - nand->ecc.bytes = 3; -#else -#error "Either CONFIG_SYS_NAND_LARGEPAGE or CONFIG_SYS_NAND_SMALLPAGE must be defined!" -#endif -#else nand->ecc.size = 512; nand->ecc.bytes = 3; -#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ nand->ecc.calculate = nand_davinci_calculate_ecc; nand->ecc.correct = nand_davinci_correct_data; nand->ecc.hwctl = nand_davinci_enable_hwecc; -- cgit v1.1 From 154b5484ac7dcbcd0fb5ba388d930b02f87fa302 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 10 May 2009 15:43:01 -0700 Subject: davinci_nand chipselect/init cleanup Update chipselect handling in davinci_nand.c so that it can handle 2 GByte chips the same way Linux does: as one device, even though it has two halves with independent chip selects. For such chips the "nand info" command reports: Device 0: 2x nand0, sector size 128 KiB Switch to use the default chipselect function unless the board really needs its own. The logic for the Sonata board moves out of the driver into board-specific code. (Which doesn't affect current build breakage if its NAND support is enabled...) Signed-off-by: David Brownell Signed-off-by: Scott Wood --- drivers/mtd/nand/davinci_nand.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 9e7b9dd..ca40c6a 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -47,8 +47,6 @@ #include #include -extern struct nand_chip nand_dev_desc[CONFIG_SYS_MAX_NAND_DEVICE]; - static emif_registers *const emif_regs = (void *) DAVINCI_ASYNC_EMIF_CNTRL_BASE; static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) @@ -70,21 +68,6 @@ static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int c writeb(cmd, this->IO_ADDR_W); } -/* Set WP on deselect, write enable on select */ -static void nand_davinci_select_chip(struct mtd_info *mtd, int chip) -{ -#define GPIO_SET_DATA01 0x01c67018 -#define GPIO_CLR_DATA01 0x01c6701c -#define GPIO_NAND_WP (1 << 4) -#ifdef SONATA_BOARD_GPIOWP - if (chip < 0) { - REG(GPIO_CLR_DATA01) |= GPIO_NAND_WP; - } else { - REG(GPIO_SET_DATA01) |= GPIO_NAND_WP; - } -#endif -} - #ifdef CONFIG_SYS_NAND_HW_ECC static void nand_davinci_enable_hwecc(struct mtd_info *mtd, int mode) @@ -228,10 +211,9 @@ static void nand_flash_init(void) #endif } -int board_nand_init(struct nand_chip *nand) +void davinci_nand_init(struct nand_chip *nand) { nand->chip_delay = 0; - nand->select_chip = nand_davinci_select_chip; #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT nand->options = NAND_USE_FLASH_BBT; #endif @@ -252,6 +234,12 @@ int board_nand_init(struct nand_chip *nand) nand->dev_ready = nand_davinci_dev_ready; nand_flash_init(); +} - return(0); +int board_nand_init(struct nand_chip *chip) __attribute__((weak)); + +int board_nand_init(struct nand_chip *chip) +{ + davinci_nand_init(chip); + return 0; } -- cgit v1.1 From cd84423a09f3a08029fe41c1db96168debd0b51f Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 25 May 2009 22:42:28 -0400 Subject: mtd: nand: new base driver for memory mapped nand devices The BF537-STAMP Blackfin board had a driver for working with NAND devices that are simply memory mapped. Since there is nothing Blackfin specific about this, generalize the driver a bit so that everyone can leverage it. Signed-off-by: Mike Frysinger Signed-off-by: Scott Wood --- drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/nand_plat.c | 53 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 drivers/mtd/nand/nand_plat.c (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 71dd5b9..fea58f4 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -45,6 +45,7 @@ COBJS-$(CONFIG_NAND_NOMADIK) += nomadik.o COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.c COBJS-$(CONFIG_NAND_S3C64XX) += s3c64xx.o COBJS-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o +COBJS-$(CONFIG_NAND_PLAT) += nand_plat.o endif COBJS := $(COBJS-y) diff --git a/drivers/mtd/nand/nand_plat.c b/drivers/mtd/nand/nand_plat.c new file mode 100644 index 0000000..b35492b --- /dev/null +++ b/drivers/mtd/nand/nand_plat.c @@ -0,0 +1,53 @@ +/* + * Genericish driver for memory mapped NAND devices + * + * Copyright (c) 2006-2009 Analog Devices Inc. + * Licensed under the GPL-2 or later. + */ + +/* Your board must implement the following macros: + * NAND_PLAT_WRITE_CMD(chip, cmd) + * NAND_PLAT_WRITE_ADR(chip, cmd) + * NAND_PLAT_INIT() + * + * It may also implement the following: + * NAND_PLAT_DEV_READY(chip) + */ + +#include +#include + +#include + +static void plat_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ + struct nand_chip *this = mtd->priv; + + if (cmd == NAND_CMD_NONE) + return; + + if (ctrl & NAND_CLE) + NAND_PLAT_WRITE_CMD(this, cmd); + else + NAND_PLAT_WRITE_ADR(this, cmd); +} + +#ifdef NAND_PLAT_DEV_READY +static int plat_dev_ready(struct mtd_info *mtd) +{ + return NAND_PLAT_DEV_READY((struct nand_chip *)mtd->priv); +} +#else +# define plat_dev_ready NULL +#endif + +int board_nand_init(struct nand_chip *nand) +{ + NAND_PLAT_INIT(); + + nand->cmd_ctrl = plat_cmd_ctrl; + nand->dev_ready = plat_dev_ready; + nand->ecc.mode = NAND_ECC_SOFT; + + return 0; +} -- cgit v1.1 From 378adfcdf4bbd77ee4cbc3276d4733e218308a21 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sat, 16 May 2009 14:27:40 +0200 Subject: mtd: nand: use loff_t for offset nand_util currently uses size_t which is arch dependent and not always a unsigned long. Now use loff_t, as does the linux mtd layer. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Scott Wood --- drivers/mtd/nand/nand_util.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index 88206d0..fc16282 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -315,7 +315,7 @@ int nand_lock(struct mtd_info *mtd, int tight) * NAND_LOCK_STATUS_UNLOCK: page unlocked * */ -int nand_get_lock_status(struct mtd_info *mtd, ulong offset) +int nand_get_lock_status(struct mtd_info *mtd, loff_t offset) { int ret = 0; int chipnr; @@ -436,7 +436,7 @@ int nand_unlock(struct mtd_info *mtd, ulong start, ulong length) * @param length image length * @return image length including bad blocks */ -static size_t get_len_incl_bad (nand_info_t *nand, size_t offset, +static size_t get_len_incl_bad (nand_info_t *nand, loff_t offset, const size_t length) { size_t len_incl_bad = 0; @@ -473,7 +473,7 @@ static size_t get_len_incl_bad (nand_info_t *nand, size_t offset, * @param buf buffer to read from * @return 0 in case of success */ -int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length, +int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, u_char *buffer) { int rval; @@ -498,7 +498,7 @@ int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length, if (len_incl_bad == *length) { rval = nand_write (nand, offset, length, buffer); if (rval != 0) - printf ("NAND write to offset %zx failed %d\n", + printf ("NAND write to offset %llx failed %d\n", offset, rval); return rval; @@ -509,7 +509,7 @@ int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length, size_t write_size; if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) { - printf ("Skip bad block 0x%08zx\n", + printf ("Skip bad block 0x%08llx\n", offset & ~(nand->erasesize - 1)); offset += nand->erasesize - block_offset; continue; @@ -522,7 +522,7 @@ int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length, rval = nand_write (nand, offset, &write_size, p_buffer); if (rval != 0) { - printf ("NAND write to offset %zx failed %d\n", + printf ("NAND write to offset %llx failed %d\n", offset, rval); *length -= left_to_write; return rval; @@ -550,7 +550,7 @@ int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length, * @param buffer buffer to write to * @return 0 in case of success */ -int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length, +int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, u_char *buffer) { int rval; @@ -568,7 +568,7 @@ int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length, if (len_incl_bad == *length) { rval = nand_read (nand, offset, length, buffer); if (rval != 0) - printf ("NAND read from offset %zx failed %d\n", + printf ("NAND read from offset %llx failed %d\n", offset, rval); return rval; @@ -579,7 +579,7 @@ int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length, size_t read_length; if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) { - printf ("Skipping bad block 0x%08zx\n", + printf ("Skipping bad block 0x%08llx\n", offset & ~(nand->erasesize - 1)); offset += nand->erasesize - block_offset; continue; @@ -592,7 +592,7 @@ int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length, rval = nand_read (nand, offset, &read_length, p_buffer); if (rval != 0) { - printf ("NAND read from offset %zx failed %d\n", + printf ("NAND read from offset %llx failed %d\n", offset, rval); *length -= left_to_read; return rval; -- cgit v1.1 From 98713d2663d5d30dde74f48f547114a2bfd9d463 Mon Sep 17 00:00:00 2001 From: "kevin.morfitt@fearnside-systems.co.uk" Date: Thu, 18 Jun 2009 18:41:03 +0100 Subject: Bug-fix in drivers mtd nand Makefile The S3C2410 NAND driver source file is included in the makefile instead of the object file. Signed-off-by: Kevin Morfitt Signed-off-by: Scott Wood --- drivers/mtd/nand/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index fea58f4..c1325b9 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -42,7 +42,7 @@ COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_nand.o COBJS-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o COBJS-$(CONFIG_NAND_MPC5121_NFC) += mpc5121_nfc.o COBJS-$(CONFIG_NAND_NOMADIK) += nomadik.o -COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.c +COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o COBJS-$(CONFIG_NAND_S3C64XX) += s3c64xx.o COBJS-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o COBJS-$(CONFIG_NAND_PLAT) += nand_plat.o -- cgit v1.1 From 66372fe2ab11cdeb0e841ad9eb6ba79769db4909 Mon Sep 17 00:00:00 2001 From: Mingkai Hu Date: Thu, 18 Jun 2009 18:23:27 +0800 Subject: fsl_elbc_nand: redirect the pointer of bbt pattern to RAM The bbt descriptors contains the pointer to the bbt pattern which are statically initialized memory struct. When relocated to RAM, these pointers will continue point to NOR flash(or L2 SRAM, or other boot device). If the contents of NOR flash changed or L2 SRAM disabled, it'll hang the system. Signed-off-by: Mingkai Hu Signed-off-by: Scott Wood --- drivers/mtd/nand/fsl_elbc_nand.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/mtd') diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 3f318e0..77a33c0 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -766,6 +766,9 @@ int board_nand_init(struct nand_chip *nand) nand->waitfunc = fsl_elbc_wait; /* set up nand options */ + /* redirect the pointer of bbt pattern to RAM */ + bbt_main_descr.pattern = bbt_pattern; + bbt_mirror_descr.pattern = mirror_pattern; nand->bbt_td = &bbt_main_descr; nand->bbt_md = &bbt_mirror_descr; @@ -812,6 +815,7 @@ int board_nand_init(struct nand_chip *nand) /* Large-page-specific setup */ if (or & OR_FCM_PGS) { priv->page_size = 1; + largepage_memorybased.pattern = scan_ff_pattern; nand->badblock_pattern = &largepage_memorybased; /* adjust ecc setup if needed */ -- cgit v1.1