Merge branch 'master' of git://git.denx.de/u-boot-nand-flash

master
Tom Rini 11 years ago
commit faca8ff55f
  1. 1
      arch/arm/cpu/armv7/am33xx/Makefile
  2. 52
      arch/arm/cpu/armv7/am33xx/mem.c
  3. 5
      arch/arm/include/asm/arch-am33xx/mem.h
  4. 0
      arch/arm/include/asm/omap_elm.h
  5. 16
      arch/arm/include/asm/omap_gpmc.h
  6. 24
      arch/powerpc/cpu/mpc8xxx/fsl_ifc.c
  7. 2
      arch/powerpc/include/asm/fsl_ifc.h
  8. 5
      board/atmel/sama5d3xek/sama5d3xek.c
  9. 14
      board/ti/am335x/board.c
  10. 63
      doc/README.nand
  11. 3
      doc/README.omap3
  12. 1
      drivers/mtd/nand/Makefile
  13. 40
      drivers/mtd/nand/atmel_nand.c
  14. 99
      drivers/mtd/nand/fsl_ifc_nand.c
  15. 7
      drivers/mtd/nand/fsl_ifc_spl.c
  16. 6
      drivers/mtd/nand/omap_elm.c
  17. 321
      drivers/mtd/nand/omap_gpmc.c
  18. 15
      drivers/mtd/onenand/onenand_base.c
  19. 2
      include/configs/ASH405.h
  20. 10
      include/configs/C29XPCIE.h
  21. 2
      include/configs/MPC8572DS.h
  22. 2
      include/configs/T4240QDS.h
  23. 2
      include/configs/alpr.h
  24. 5
      include/configs/am335x_evm.h
  25. 2
      include/configs/am335x_igep0033.h
  26. 1
      include/configs/am3517_crane.h
  27. 1
      include/configs/am3517_evm.h
  28. 1
      include/configs/devkit8000.h
  29. 2
      include/configs/mcx.h
  30. 1
      include/configs/omap3_beagle.h
  31. 1
      include/configs/omap3_evm.h
  32. 1
      include/configs/omap3_evm_quick_nand.h
  33. 1
      include/configs/omap3_igep00x0.h
  34. 1
      include/configs/omap3_overo.h
  35. 2
      include/configs/siemens-am33x-common.h
  36. 2
      include/configs/tam3517-common.h
  37. 4
      include/configs/tricorder.h
  38. 23
      include/linux/mtd/mtd.h
  39. 12
      include/mtd/mtd-abi.h

@ -19,4 +19,3 @@ obj-y += ddr.o
obj-y += emif4.o
obj-y += board.o
obj-y += mux.o
obj-$(CONFIG_NAND_OMAP_GPMC) += elm.o

@ -22,17 +22,6 @@
struct gpmc *gpmc_cfg;
#if defined(CONFIG_CMD_NAND)
static const u32 gpmc_m_nand[GPMC_MAX_REG] = {
M_NAND_GPMC_CONFIG1,
M_NAND_GPMC_CONFIG2,
M_NAND_GPMC_CONFIG3,
M_NAND_GPMC_CONFIG4,
M_NAND_GPMC_CONFIG5,
M_NAND_GPMC_CONFIG6, 0
};
#endif
void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base,
u32 size)
@ -61,11 +50,34 @@ void gpmc_init(void)
{
/* putting a blanket check on GPMC based on ZeBu for now */
gpmc_cfg = (struct gpmc *)GPMC_BASE;
#ifdef CONFIG_CMD_NAND
const u32 *gpmc_config = NULL;
u32 base = 0;
#if defined(CONFIG_NOR)
/* configure GPMC for NOR */
const u32 gpmc_regs[GPMC_MAX_REG] = { STNOR_GPMC_CONFIG1,
STNOR_GPMC_CONFIG2,
STNOR_GPMC_CONFIG3,
STNOR_GPMC_CONFIG4,
STNOR_GPMC_CONFIG5,
STNOR_GPMC_CONFIG6,
STNOR_GPMC_CONFIG7
};
u32 size = GPMC_SIZE_16M;
u32 base = CONFIG_SYS_FLASH_BASE;
#elif defined(CONFIG_NAND)
/* configure GPMC for NAND */
const u32 gpmc_regs[GPMC_MAX_REG] = { M_NAND_GPMC_CONFIG1,
M_NAND_GPMC_CONFIG2,
M_NAND_GPMC_CONFIG3,
M_NAND_GPMC_CONFIG4,
M_NAND_GPMC_CONFIG5,
M_NAND_GPMC_CONFIG6,
0
};
u32 size = GPMC_SIZE_256M;
u32 base = CONFIG_SYS_NAND_BASE;
#else
const u32 gpmc_regs[GPMC_MAX_REG] = { 0, 0, 0, 0, 0, 0, 0 };
u32 size = 0;
u32 base = 0;
#endif
/* global settings */
writel(0x00000008, &gpmc_cfg->sysconfig);
@ -81,12 +93,6 @@ void gpmc_init(void)
*/
writel(0, &gpmc_cfg->cs[0].config7);
sdelay(1000);
#ifdef CONFIG_CMD_NAND
gpmc_config = gpmc_m_nand;
base = PISMO1_NAND_BASE;
size = PISMO1_NAND_SIZE;
enable_gpmc_cs_config(gpmc_config, &gpmc_cfg->cs[0], base, size);
#endif
/* enable chip-select specific configurations */
enable_gpmc_cs_config(gpmc_regs, &gpmc_cfg->cs[0], base, size);
}

@ -68,9 +68,4 @@
#define PISMO2_NAND_CS0 7
#define PISMO2_NAND_CS1 8
/* make it readable for the gpmc_init */
#define PISMO1_NOR_BASE FLASH_BASE
#define PISMO1_NAND_BASE CONFIG_SYS_NAND_BASE
#define PISMO1_NAND_SIZE GPMC_SIZE_256M
#endif /* endif _MEM_H_ */

@ -68,4 +68,20 @@
}
#endif
enum omap_ecc {
/* 1-bit ECC calculation by Software, Error detection by Software */
OMAP_ECC_HAM1_CODE_SW = 1, /* avoid un-initialized int can be 0x0 */
/* 1-bit ECC calculation by GPMC, Error detection by Software */
/* ECC layout compatible to legacy ROMCODE. */
OMAP_ECC_HAM1_CODE_HW,
/* 4-bit ECC calculation by GPMC, Error detection by Software */
OMAP_ECC_BCH4_CODE_HW_DETECTION_SW,
/* 4-bit ECC calculation by GPMC, Error detection by ELM */
OMAP_ECC_BCH4_CODE_HW,
/* 8-bit ECC calculation by GPMC, Error detection by Software */
OMAP_ECC_BCH8_CODE_HW_DETECTION_SW,
/* 8-bit ECC calculation by GPMC, Error detection by ELM */
OMAP_ECC_BCH8_CODE_HW,
};
#endif /* __ASM_OMAP_GPMC_H */

@ -34,6 +34,9 @@ void init_early_memctl_regs(void)
#ifdef CONFIG_SYS_CSPR0_EXT
set_ifc_cspr_ext(IFC_CS0, CONFIG_SYS_CSPR0_EXT);
#endif
#ifdef CONFIG_SYS_CSOR0_EXT
set_ifc_csor_ext(IFC_CS0, CONFIG_SYS_CSOR0_EXT);
#endif
set_ifc_cspr(IFC_CS0, CONFIG_SYS_CSPR0);
set_ifc_amask(IFC_CS0, CONFIG_SYS_AMASK0);
set_ifc_csor(IFC_CS0, CONFIG_SYS_CSOR0);
@ -43,6 +46,9 @@ void init_early_memctl_regs(void)
#ifdef CONFIG_SYS_CSPR1_EXT
set_ifc_cspr_ext(IFC_CS1, CONFIG_SYS_CSPR1_EXT);
#endif
#ifdef CONFIG_SYS_CSOR1_EXT
set_ifc_csor_ext(IFC_CS1, CONFIG_SYS_CSOR1_EXT);
#endif
#if defined(CONFIG_SYS_CSPR1) && defined(CONFIG_SYS_CSOR1)
set_ifc_ftim(IFC_CS1, IFC_FTIM0, CONFIG_SYS_CS1_FTIM0);
set_ifc_ftim(IFC_CS1, IFC_FTIM1, CONFIG_SYS_CS1_FTIM1);
@ -57,6 +63,9 @@ void init_early_memctl_regs(void)
#ifdef CONFIG_SYS_CSPR2_EXT
set_ifc_cspr_ext(IFC_CS2, CONFIG_SYS_CSPR2_EXT);
#endif
#ifdef CONFIG_SYS_CSOR2_EXT
set_ifc_csor_ext(IFC_CS2, CONFIG_SYS_CSOR2_EXT);
#endif
#if defined(CONFIG_SYS_CSPR2) && defined(CONFIG_SYS_CSOR2)
set_ifc_ftim(IFC_CS2, IFC_FTIM0, CONFIG_SYS_CS2_FTIM0);
set_ifc_ftim(IFC_CS2, IFC_FTIM1, CONFIG_SYS_CS2_FTIM1);
@ -71,6 +80,9 @@ void init_early_memctl_regs(void)
#ifdef CONFIG_SYS_CSPR3_EXT
set_ifc_cspr_ext(IFC_CS3, CONFIG_SYS_CSPR3_EXT);
#endif
#ifdef CONFIG_SYS_CSOR3_EXT
set_ifc_csor_ext(IFC_CS3, CONFIG_SYS_CSOR3_EXT);
#endif
#if defined(CONFIG_SYS_CSPR3) && defined(CONFIG_SYS_CSOR3)
set_ifc_ftim(IFC_CS3, IFC_FTIM0, CONFIG_SYS_CS3_FTIM0);
set_ifc_ftim(IFC_CS3, IFC_FTIM1, CONFIG_SYS_CS3_FTIM1);
@ -85,6 +97,9 @@ void init_early_memctl_regs(void)
#ifdef CONFIG_SYS_CSPR4_EXT
set_ifc_cspr_ext(IFC_CS4, CONFIG_SYS_CSPR4_EXT);
#endif
#ifdef CONFIG_SYS_CSOR4_EXT
set_ifc_csor_ext(IFC_CS4, CONFIG_SYS_CSOR4_EXT);
#endif
#if defined(CONFIG_SYS_CSPR4) && defined(CONFIG_SYS_CSOR4)
set_ifc_ftim(IFC_CS4, IFC_FTIM0, CONFIG_SYS_CS4_FTIM0);
set_ifc_ftim(IFC_CS4, IFC_FTIM1, CONFIG_SYS_CS4_FTIM1);
@ -99,6 +114,9 @@ void init_early_memctl_regs(void)
#ifdef CONFIG_SYS_CSPR5_EXT
set_ifc_cspr_ext(IFC_CS5, CONFIG_SYS_CSPR5_EXT);
#endif
#ifdef CONFIG_SYS_CSOR5_EXT
set_ifc_csor_ext(IFC_CS5, CONFIG_SYS_CSOR5_EXT);
#endif
#if defined(CONFIG_SYS_CSPR5) && defined(CONFIG_SYS_CSOR5)
set_ifc_ftim(IFC_CS5, IFC_FTIM0, CONFIG_SYS_CS5_FTIM0);
set_ifc_ftim(IFC_CS5, IFC_FTIM1, CONFIG_SYS_CS5_FTIM1);
@ -113,6 +131,9 @@ void init_early_memctl_regs(void)
#ifdef CONFIG_SYS_CSPR6_EXT
set_ifc_cspr_ext(IFC_CS6, CONFIG_SYS_CSPR6_EXT);
#endif
#ifdef CONFIG_SYS_CSOR6_EXT
set_ifc_csor_ext(IFC_CS6, CONFIG_SYS_CSOR6_EXT);
#endif
#if defined(CONFIG_SYS_CSPR6) && defined(CONFIG_SYS_CSOR6)
set_ifc_ftim(IFC_CS6, IFC_FTIM0, CONFIG_SYS_CS6_FTIM0);
set_ifc_ftim(IFC_CS6, IFC_FTIM1, CONFIG_SYS_CS6_FTIM1);
@ -127,6 +148,9 @@ void init_early_memctl_regs(void)
#ifdef CONFIG_SYS_CSPR7_EXT
set_ifc_cspr_ext(IFC_CS7, CONFIG_SYS_CSPR7_EXT);
#endif
#ifdef CONFIG_SYS_CSOR7_EXT
set_ifc_csor_ext(IFC_CS7, CONFIG_SYS_CSOR7_EXT);
#endif
#if defined(CONFIG_SYS_CSPR7) && defined(CONFIG_SYS_CSOR7)
set_ifc_ftim(IFC_CS7, IFC_FTIM0, CONFIG_SYS_CS7_FTIM0);
set_ifc_ftim(IFC_CS7, IFC_FTIM1, CONFIG_SYS_CS7_FTIM1);

@ -77,6 +77,7 @@
#define CSOR_NAND_PGS_512 0x00000000
#define CSOR_NAND_PGS_2K 0x00080000
#define CSOR_NAND_PGS_4K 0x00100000
#define CSOR_NAND_PGS_8K 0x00180000
/* Spare region Size */
#define CSOR_NAND_SPRZ_MASK 0x0000E000
#define CSOR_NAND_SPRZ_SHIFT 13
@ -86,6 +87,7 @@
#define CSOR_NAND_SPRZ_210 0x00006000
#define CSOR_NAND_SPRZ_218 0x00008000
#define CSOR_NAND_SPRZ_224 0x0000A000
#define CSOR_NAND_SPRZ_CSOR_EXT 0x0000C000
/* Pages Per Block */
#define CSOR_NAND_PB_MASK 0x00000700
#define CSOR_NAND_PB_SHIFT 8

@ -131,7 +131,8 @@ static void sama5d3xek_lcd_hw_init(void)
void lcd_show_board_info(void)
{
ulong dram_size, nand_size;
ulong dram_size;
uint64_t nand_size;
int i;
char temp[32];
@ -150,7 +151,7 @@ void lcd_show_board_info(void)
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
nand_size += nand_info[i].size;
#endif
lcd_printf("%ld MB SDRAM, %ld MB NAND\n",
lcd_printf("%ld MB SDRAM, %lld MB NAND\n",
dram_size >> 20, nand_size >> 20);
}
#endif /* CONFIG_LCD_INFO */

@ -481,26 +481,14 @@ void sdram_init(void)
*/
int board_init(void)
{
#ifdef CONFIG_NOR
const u32 gpmc_nor[GPMC_MAX_REG] = { STNOR_GPMC_CONFIG1,
STNOR_GPMC_CONFIG2, STNOR_GPMC_CONFIG3, STNOR_GPMC_CONFIG4,
STNOR_GPMC_CONFIG5, STNOR_GPMC_CONFIG6, STNOR_GPMC_CONFIG7 };
#endif
#if defined(CONFIG_HW_WATCHDOG)
hw_watchdog_init();
#endif
gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
#if defined(CONFIG_NOR) || defined(CONFIG_NAND)
gpmc_init();
#ifdef CONFIG_NOR
/* Reconfigure CS0 for NOR instead of NAND. */
enable_gpmc_cs_config(gpmc_nor, &gpmc_cfg->cs[0],
CONFIG_SYS_FLASH_BASE, GPMC_SIZE_16M);
#endif
return 0;
}

@ -104,6 +104,16 @@ Configuration Options:
CONFIG_SYS_MAX_NAND_DEVICE
The maximum number of NAND devices you want to support.
CONFIG_SYS_NAND_MAX_ECCPOS
If specified, overrides the maximum number of ECC bytes
supported. Useful for reducing image size, especially with SPL.
This must be at least 48 if nand_base.c is used.
CONFIG_SYS_NAND_MAX_OOBFREE
If specified, overrides the maximum number of free OOB regions
supported. Useful for reducing image size, especially with SPL.
This must be at least 2 if nand_base.c is used.
CONFIG_SYS_NAND_MAX_CHIPS
The maximum number of NAND chips per device to be supported.
@ -169,6 +179,59 @@ Configuration Options:
Please convert your driver even if you don't need the extra
flexibility, so that one day we can eliminate the old mechanism.
CONFIG_SYS_NAND_ONFI_DETECTION
Enables detection of ONFI compliant devices during probe.
And fetching device parameters flashed on device, by parsing
ONFI parameter page.
CONFIG_BCH
Enables software based BCH ECC algorithm present in lib/bch.c
This is used by SoC platforms which do not have built-in ELM
hardware engine required for BCH ECC correction.
Platform specific options
=========================
CONFIG_NAND_OMAP_GPMC
Enables omap_gpmc.c driver for OMAPx and AMxxxx platforms.
GPMC controller is used for parallel NAND flash devices, and can
do ECC calculation (not ECC error detection) for HAM1, BCH4, BCH8
and BCH16 ECC algorithms.
CONFIG_NAND_OMAP_ELM
Enables omap_elm.c driver for OMAPx and AMxxxx platforms.
ELM controller is used for ECC error detection (not ECC calculation)
of BCH4, BCH8 and BCH16 ECC algorithms.
Some legacy platforms like OMAP3xx do not have in-built ELM h/w engine,
thus such SoC platforms need to depend on software library for ECC error
detection. However ECC calculation on such plaforms would still be
done by GPMC controller.
CONFIG_NAND_OMAP_ECCSCHEME
On OMAP platforms, this CONFIG specifies NAND ECC scheme.
It can take following values:
OMAP_ECC_HAM1_CODE_SW
1-bit Hamming code using software lib.
(for legacy devices only)
OMAP_ECC_HAM1_CODE_HW
1-bit Hamming code using GPMC hardware.
(for legacy devices only)
OMAP_ECC_BCH4_CODE_HW_DETECTION_SW
4-bit BCH code (unsupported)
OMAP_ECC_BCH4_CODE_HW
4-bit BCH code (unsupported)
OMAP_ECC_BCH8_CODE_HW_DETECTION_SW
8-bit BCH code with
- ecc calculation using GPMC hardware engine,
- error detection using software library.
- requires CONFIG_BCH to enable software BCH library
(For legacy device which do not have ELM h/w engine)
OMAP_ECC_BCH8_CODE_HW
8-bit BCH code with
- ecc calculation using GPMC hardware engine,
- error detection using ELM hardware engine.
NOTE:
=====

@ -161,8 +161,7 @@ BCH8
To enable hardware assisted BCH8 (8-bit BCH [Bose, Chaudhuri, Hocquenghem]) on
OMAP3 devices we can use the BCH library in lib/bch.c. To do so add CONFIG_BCH
to enable the library and CONFIG_NAND_OMAP_BCH8 to to enable hardware assisted
syndrom generation to your board config.
and set CONFIG_NAND_OMAP_ECCSCHEME=5 (refer README.nand) for selecting BCH8_SW.
The NAND OOB layout is the same as in linux kernel, if the linux kernel BCH8
implementation for OMAP3 works for you so the u-boot version should also.
When you require the SPL to read with BCH8 there are two more configs to

@ -58,6 +58,7 @@ obj-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
obj-$(CONFIG_NAND_SPEAR) += spr_nand.o
obj-$(CONFIG_TEGRA_NAND) += tegra_nand.o
obj-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o
obj-$(CONFIG_NAND_OMAP_ELM) += omap_elm.o
obj-$(CONFIG_NAND_PLAT) += nand_plat.o
obj-$(CONFIG_NAND_DOCG4) += docg4.o

@ -412,7 +412,7 @@ static int pmecc_err_location(struct mtd_info *mtd)
}
if (!timeout) {
printk(KERN_ERR "atmel_nand : Timeout to calculate PMECC error location\n");
dev_err(host->dev, "atmel_nand : Timeout to calculate PMECC error location\n");
return -1;
}
@ -452,7 +452,7 @@ static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc,
*(buf + byte_pos) ^= (1 << bit_pos);
pos = sector_num * host->pmecc_sector_size + byte_pos;
printk(KERN_INFO "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
dev_dbg(host->dev, "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
pos, bit_pos, err_byte, *(buf + byte_pos));
} else {
/* Bit flip in OOB area */
@ -462,7 +462,7 @@ static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc,
ecc[tmp] ^= (1 << bit_pos);
pos = tmp + nand_chip->ecc.layout->eccpos[0];
printk(KERN_INFO "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
dev_dbg(host->dev, "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
pos, bit_pos, err_byte, ecc[tmp]);
}
@ -500,7 +500,7 @@ normal_check:
err_nbr = pmecc_err_location(mtd);
if (err_nbr == -1) {
printk(KERN_ERR "PMECC: Too many errors\n");
dev_err(host->dev, "PMECC: Too many errors\n");
mtd->ecc_stats.failed++;
return -EIO;
} else {
@ -544,7 +544,7 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
}
if (!timeout) {
printk(KERN_ERR "atmel_nand : Timeout to read PMECC page\n");
dev_err(host->dev, "atmel_nand : Timeout to read PMECC page\n");
return -1;
}
@ -584,7 +584,7 @@ static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
}
if (!timeout) {
printk(KERN_ERR "atmel_nand : Timeout to read PMECC status, fail to write PMECC in oob\n");
dev_err(host->dev, "atmel_nand : Timeout to read PMECC status, fail to write PMECC in oob\n");
goto out;
}
@ -827,6 +827,7 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
switch (mtd->writesize) {
case 2048:
case 4096:
case 8192:
host->pmecc_degree = (sector_size == 512) ?
PMECC_GF_DIMENSION_13 : PMECC_GF_DIMENSION_14;
host->pmecc_cw_len = (1 << host->pmecc_degree) - 1;
@ -840,8 +841,15 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
nand->ecc.steps = 1;
nand->ecc.bytes = host->pmecc_bytes_per_sector *
host->pmecc_sector_number;
if (nand->ecc.bytes > MTD_MAX_ECCPOS_ENTRIES_LARGE) {
dev_err(host->dev, "too large eccpos entries. max support ecc.bytes is %d\n",
MTD_MAX_ECCPOS_ENTRIES_LARGE);
return -EINVAL;
}
if (nand->ecc.bytes > mtd->oobsize - 2) {
printk(KERN_ERR "No room for ECC bytes\n");
dev_err(host->dev, "No room for ECC bytes\n");
return -EINVAL;
}
pmecc_config_ecc_layout(&atmel_pmecc_oobinfo,
@ -852,7 +860,7 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
case 512:
case 1024:
/* TODO */
printk(KERN_ERR "Unsupported page size for PMECC, use Software ECC\n");
dev_err(host->dev, "Unsupported page size for PMECC, use Software ECC\n");
default:
/* page size not handled by HW ECC */
/* switching back to soft ECC */
@ -1035,7 +1043,7 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
/* it doesn't seems to be a freshly
* erased block.
* We can't correct so many errors */
printk(KERN_WARNING "atmel_nand : multiple errors detected."
dev_warn(host->dev, "atmel_nand : multiple errors detected."
" Unable to correct.\n");
return -EIO;
}
@ -1045,12 +1053,12 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
/* there's nothing much to do here.
* the bit error is on the ECC itself.
*/
printk(KERN_WARNING "atmel_nand : one bit error on ECC code."
dev_warn(host->dev, "atmel_nand : one bit error on ECC code."
" Nothing to correct\n");
return 0;
}
printk(KERN_WARNING "atmel_nand : one bit error on data."
dev_warn(host->dev, "atmel_nand : one bit error on data."
" (word offset in the page :"
" 0x%x bit offset : 0x%x)\n",
ecc_word, ecc_bit);
@ -1062,7 +1070,7 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
/* 8 bits words */
dat[ecc_word] ^= (1 << ecc_bit);
}
printk(KERN_WARNING "atmel_nand : error corrected\n");
dev_warn(host->dev, "atmel_nand : error corrected\n");
return 1;
}
@ -1178,7 +1186,11 @@ int atmel_nand_chip_init(int devnum, ulong base_addr)
mtd->priv = nand;
nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr;
#ifdef CONFIG_NAND_ECC_BCH
nand->ecc.mode = NAND_ECC_SOFT_BCH;
#else
nand->ecc.mode = NAND_ECC_SOFT;
#endif
#ifdef CONFIG_SYS_NAND_DBW_16
nand->options = NAND_BUSWIDTH_16;
#endif
@ -1186,7 +1198,7 @@ int atmel_nand_chip_init(int devnum, ulong base_addr)
#ifdef CONFIG_SYS_NAND_READY_PIN
nand->dev_ready = at91_nand_ready;
#endif
nand->chip_delay = 20;
nand->chip_delay = 75;
ret = nand_scan_ident(mtd, CONFIG_SYS_NAND_MAX_CHIPS, NULL);
if (ret)
@ -1214,6 +1226,6 @@ void board_nand_init(void)
int i;
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
if (atmel_nand_chip_init(i, base_addr[i]))
printk(KERN_ERR "atmel_nand: Fail to initialize #%d chip",
dev_err(host->dev, "atmel_nand: Fail to initialize #%d chip",
i);
}

@ -125,6 +125,69 @@ static struct nand_ecclayout oob_4096_ecc8 = {
.oobfree = { {2, 6}, {136, 82} },
};
/* 8192-byte page size with 4-bit ECC */
static struct nand_ecclayout oob_8192_ecc4 = {
.eccbytes = 128,
.eccpos = {
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87,
88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99, 100, 101, 102, 103,
104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127,
128, 129, 130, 131, 132, 133, 134, 135,
},
.oobfree = { {2, 6}, {136, 208} },
};
/* 8192-byte page size with 8-bit ECC -- requires 218-byte OOB */
static struct nand_ecclayout oob_8192_ecc8 = {
.eccbytes = 256,
.eccpos = {
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87,
88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99, 100, 101, 102, 103,
104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127,
128, 129, 130, 131, 132, 133, 134, 135,
136, 137, 138, 139, 140, 141, 142, 143,
144, 145, 146, 147, 148, 149, 150, 151,
152, 153, 154, 155, 156, 157, 158, 159,
160, 161, 162, 163, 164, 165, 166, 167,
168, 169, 170, 171, 172, 173, 174, 175,
176, 177, 178, 179, 180, 181, 182, 183,
184, 185, 186, 187, 188, 189, 190, 191,
192, 193, 194, 195, 196, 197, 198, 199,
200, 201, 202, 203, 204, 205, 206, 207,
208, 209, 210, 211, 212, 213, 214, 215,
216, 217, 218, 219, 220, 221, 222, 223,
224, 225, 226, 227, 228, 229, 230, 231,
232, 233, 234, 235, 236, 237, 238, 239,
240, 241, 242, 243, 244, 245, 246, 247,
248, 249, 250, 251, 252, 253, 254, 255,
256, 257, 258, 259, 260, 261, 262, 263,
},
.oobfree = { {2, 6}, {264, 80} },
};
/*
* Generic flash bbt descriptors
@ -428,20 +491,27 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
if (mtd->writesize > 512) {
nand_fcr0 =
(NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
(NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD1_SHIFT);
(NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) |
(NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT);
out_be32(&ifc->ifc_nand.nand_fir0,
(IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
(IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
(IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
(IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP3_SHIFT) |
(IFC_FIR_OP_CW1 << IFC_NAND_FIR0_OP4_SHIFT));
out_be32(&ifc->ifc_nand.nand_fir1, 0);
(IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT));
out_be32(&ifc->ifc_nand.nand_fir1,
(IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) |
(IFC_FIR_OP_RDSTAT <<
IFC_NAND_FIR1_OP6_SHIFT) |
(IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT));
} else {
nand_fcr0 = ((NAND_CMD_PAGEPROG <<
IFC_NAND_FCR0_CMD1_SHIFT) |
(NAND_CMD_SEQIN <<
IFC_NAND_FCR0_CMD2_SHIFT));
IFC_NAND_FCR0_CMD2_SHIFT) |
(NAND_CMD_STATUS <<
IFC_NAND_FCR0_CMD3_SHIFT));
out_be32(&ifc->ifc_nand.nand_fir0,
(IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
@ -450,7 +520,11 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
(IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
(IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT));
out_be32(&ifc->ifc_nand.nand_fir1,
(IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT));
(IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) |
(IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) |
(IFC_FIR_OP_RDSTAT <<
IFC_NAND_FIR1_OP7_SHIFT) |
(IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT));
if (column >= mtd->writesize)
nand_fcr0 |=
@ -902,6 +976,21 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr)
priv->bufnum_mask = 1;
break;
case CSOR_NAND_PGS_8K:
if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
CSOR_NAND_ECC_MODE_4) {
layout = &oob_8192_ecc4;
nand->ecc.strength = 4;
} else {
layout = &oob_8192_ecc8;
nand->ecc.strength = 8;
nand->ecc.bytes = 16;
}
priv->bufnum_mask = 0;
break;
default:
printf("ifc nand: bad csor %#x: bad page size\n", csor);
return -ENODEV;

@ -112,10 +112,13 @@ static void nand_load(unsigned int offs, int uboot_size, uchar *dst)
port_size = (cspr & CSPR_PORT_SIZE_16) ? 16 : 8;
if (csor & CSOR_NAND_PGS_4K) {
if ((csor & CSOR_NAND_PGS_MASK) == CSOR_NAND_PGS_8K) {
page_size = 8192;
bufnum_mask = 0x0;
} else if ((csor & CSOR_NAND_PGS_MASK) == CSOR_NAND_PGS_4K) {
page_size = 4096;
bufnum_mask = 0x1;
} else if (csor & CSOR_NAND_PGS_2K) {
} else if ((csor & CSOR_NAND_PGS_MASK) == CSOR_NAND_PGS_2K) {
page_size = 2048;
bufnum_mask = 0x3;
} else {

@ -18,7 +18,7 @@
#include <asm/errno.h>
#include <asm/arch/cpu.h>
#include <asm/omap_gpmc.h>
#include <asm/arch/elm.h>
#include <asm/omap_elm.h>
#define ELM_DEFAULT_POLY (0)
@ -127,7 +127,7 @@ int elm_check_error(u8 *syndrome, u32 nibbles, u32 *error_count,
for (i = 0; i < *error_count; i++) {
error_locations[i] =
readl(&elm_cfg->error_location[poly].error_location_x[i]);
readl(&elm_cfg->error_location[poly].error_location_x[i]);
}
return 0;
@ -175,7 +175,7 @@ void elm_reset(void)
{
/* initiate reset */
writel((readl(&elm_cfg->sysconfig) | ELM_SYSCONFIG_SOFTRESET),
&elm_cfg->sysconfig);
&elm_cfg->sysconfig);
/* wait for reset complete and normal operation */
while ((readl(&elm_cfg->sysstatus) & ELM_SYSSTATUS_RESETDONE) !=

@ -15,15 +15,13 @@
#include <linux/bch.h>
#include <linux/compiler.h>
#include <nand.h>
#ifdef CONFIG_AM33XX
#include <asm/arch/elm.h>
#endif
#include <asm/omap_elm.h>
#define BADBLOCK_MARKER_LENGTH 2
#define SECTOR_BYTES 512
static uint8_t cs;
static __maybe_unused struct nand_ecclayout hw_nand_oob =
GPMC_NAND_HW_ECC_LAYOUT;
static __maybe_unused struct nand_ecclayout hw_bch8_nand_oob =
GPMC_NAND_HW_BCH8_ECC_LAYOUT;
static __maybe_unused struct nand_ecclayout omap_ecclayout;
/*
* omap_nand_hwcontrol - Set the address pointers corretly for the
@ -233,6 +231,7 @@ struct nand_bch_priv {
uint8_t type;
uint8_t nibbles;
struct bch_control *control;
enum omap_ecc ecc_scheme;
};
/* bch types */
@ -274,17 +273,15 @@ static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)
{
uint32_t val;
uint32_t dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1;
#ifdef CONFIG_AM33XX
uint32_t unused_length = 0;
#endif
uint32_t wr_mode = BCH_WRAPMODE_6;
struct nand_bch_priv *bch = chip->priv;
/* Clear the ecc result registers, select ecc reg as 1 */
writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
#ifdef CONFIG_AM33XX
wr_mode = BCH_WRAPMODE_1;
if (bch->ecc_scheme == OMAP_ECC_BCH8_CODE_HW) {
wr_mode = BCH_WRAPMODE_1;
switch (bch->nibbles) {
case ECC_BCH4_NIBBLES:
@ -320,7 +317,7 @@ static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)
val |= (unused_length << 22);
break;
}
#else
} else {
/*
* This ecc_size_config setting is for BCH sw library.
*
@ -333,7 +330,7 @@ static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)
* size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area)
*/
val = (32 << 22) | (0 << 12);
#endif
}
/* ecc size configuration */
writel(val, &gpmc_cfg->ecc_size_config);
@ -376,9 +373,9 @@ static void __maybe_unused omap_ecc_disable(struct mtd_info *mtd)
}
/*
* BCH8 support (needs ELM and thus AM33xx-only)
* BCH support using ELM module
*/
#ifdef CONFIG_AM33XX
#ifdef CONFIG_NAND_OMAP_ELM
/*
* omap_read_bch8_result - Read BCH result for BCH8 level
*
@ -631,20 +628,20 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
}
return 0;
}
#endif /* CONFIG_AM33XX */
#endif /* CONFIG_NAND_OMAP_ELM */
/*
* OMAP3 BCH8 support (with BCH library)
*/
#ifdef CONFIG_NAND_OMAP_BCH8
#ifdef CONFIG_BCH
/*
* omap_calculate_ecc_bch - Read BCH ECC result
* omap_calculate_ecc_bch_sw - Read BCH ECC result
*
* @mtd: MTD device structure
* @dat: The pointer to data on which ecc is computed (unused here)
* @ecc: The ECC output buffer
*/
static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
static int omap_calculate_ecc_bch_sw(struct mtd_info *mtd, const uint8_t *dat,
uint8_t *ecc)
{
int ret = 0;
@ -689,13 +686,13 @@ static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
}
/**
* omap_correct_data_bch - Decode received data and correct errors
* omap_correct_data_bch_sw - Decode received data and correct errors
* @mtd: MTD device structure
* @data: page data
* @read_ecc: ecc read from nand flash
* @calc_ecc: ecc read from HW ECC registers
*/
static int omap_correct_data_bch(struct mtd_info *mtd, u_char *data,
static int omap_correct_data_bch_sw(struct mtd_info *mtd, u_char *data,
u_char *read_ecc, u_char *calc_ecc)
{
int i, count;
@ -752,7 +749,150 @@ static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
chip_priv->control = NULL;
}
}
#endif /* CONFIG_NAND_OMAP_BCH8 */
#endif /* CONFIG_BCH */
/**
* omap_select_ecc_scheme - configures driver for particular ecc-scheme
* @nand: NAND chip device structure
* @ecc_scheme: ecc scheme to configure
* @pagesize: number of main-area bytes per page of NAND device
* @oobsize: number of OOB/spare bytes per page of NAND device
*/
static int omap_select_ecc_scheme(struct nand_chip *nand,
enum omap_ecc ecc_scheme, unsigned int pagesize, unsigned int oobsize) {
struct nand_bch_priv *bch = nand->priv;
struct nand_ecclayout *ecclayout = nand->ecc.layout;
int eccsteps = pagesize / SECTOR_BYTES;
int i;
switch (ecc_scheme) {
case OMAP_ECC_HAM1_CODE_SW:
debug("nand: selected OMAP_ECC_HAM1_CODE_SW\n");
/* For this ecc-scheme, ecc.bytes, ecc.layout, ... are
* initialized in nand_scan_tail(), so just set ecc.mode */
bch_priv.control = NULL;
bch_priv.type = 0;
nand->ecc.mode = NAND_ECC_SOFT;
nand->ecc.layout = NULL;
nand->ecc.size = pagesize;
bch->ecc_scheme = OMAP_ECC_HAM1_CODE_SW;
break;
case OMAP_ECC_HAM1_CODE_HW:
debug("nand: selected OMAP_ECC_HAM1_CODE_HW\n");
/* check ecc-scheme requirements before updating ecc info */
if ((3 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
printf("nand: error: insufficient OOB: require=%d\n", (
(3 * eccsteps) + BADBLOCK_MARKER_LENGTH));
return -EINVAL;
}
bch_priv.control = NULL;
bch_priv.type = 0;
/* populate ecc specific fields */
nand->ecc.mode = NAND_ECC_HW;
nand->ecc.strength = 1;
nand->ecc.size = SECTOR_BYTES;
nand->ecc.bytes = 3;
nand->ecc.hwctl = omap_enable_hwecc;
nand->ecc.correct = omap_correct_data;
nand->ecc.calculate = omap_calculate_ecc;
/* define ecc-layout */
ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
for (i = 0; i < ecclayout->eccbytes; i++)
ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH;
ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
BADBLOCK_MARKER_LENGTH;
bch->ecc_scheme = OMAP_ECC_HAM1_CODE_HW;
break;
case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
#ifdef CONFIG_BCH
debug("nand: selected OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
/* check ecc-scheme requirements before updating ecc info */
if ((13 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
printf("nand: error: insufficient OOB: require=%d\n", (
(13 * eccsteps) + BADBLOCK_MARKER_LENGTH));
return -EINVAL;
}
/* check if BCH S/W library can be used for error detection */
bch_priv.control = init_bch(13, 8, 0x201b);
if (!bch_priv.control) {
printf("nand: error: could not init_bch()\n");
return -ENODEV;
}
bch_priv.type = ECC_BCH8;
/* populate ecc specific fields */
nand->ecc.mode = NAND_ECC_HW;
nand->ecc.strength = 8;
nand->ecc.size = SECTOR_BYTES;
nand->ecc.bytes = 13;
nand->ecc.hwctl = omap_enable_ecc_bch;
nand->ecc.correct = omap_correct_data_bch_sw;
nand->ecc.calculate = omap_calculate_ecc_bch_sw;
/* define ecc-layout */
ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
for (i = 1; i < ecclayout->eccbytes; i++) {
if (i % nand->ecc.bytes)
ecclayout->eccpos[i] =
ecclayout->eccpos[i - 1] + 1;
else
ecclayout->eccpos[i] =
ecclayout->eccpos[i - 1] + 2;
}
ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
BADBLOCK_MARKER_LENGTH;
omap_hwecc_init_bch(nand, NAND_ECC_READ);
bch->ecc_scheme = OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
break;
#else
printf("nand: error: CONFIG_BCH required for ECC\n");
return -EINVAL;
#endif
case OMAP_ECC_BCH8_CODE_HW:
#ifdef CONFIG_NAND_OMAP_ELM
debug("nand: selected OMAP_ECC_BCH8_CODE_HW\n");
/* check ecc-scheme requirements before updating ecc info */
if ((14 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
printf("nand: error: insufficient OOB: require=%d\n", (
(14 * eccsteps) + BADBLOCK_MARKER_LENGTH));
return -EINVAL;
}
/* intialize ELM for ECC error detection */
elm_init();
bch_priv.type = ECC_BCH8;
/* populate ecc specific fields */
nand->ecc.mode = NAND_ECC_HW;
nand->ecc.strength = 8;
nand->ecc.size = SECTOR_BYTES;
nand->ecc.bytes = 14;
nand->ecc.hwctl = omap_enable_ecc_bch;
nand->ecc.correct = omap_correct_data_bch;
nand->ecc.calculate = omap_calculate_ecc_bch;
nand->ecc.read_page = omap_read_page_bch;
/* define ecc-layout */
ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
for (i = 0; i < ecclayout->eccbytes; i++)
ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH;
ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
BADBLOCK_MARKER_LENGTH;
bch->ecc_scheme = OMAP_ECC_BCH8_CODE_HW;
break;
#else
printf("nand: error: CONFIG_NAND_OMAP_ELM required for ECC\n");
return -EINVAL;
#endif
default:
debug("nand: error: ecc scheme not enabled or supported\n");
return -EINVAL;
}
return 0;
}
#ifndef CONFIG_SPL_BUILD
/*
@ -763,77 +903,45 @@ static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
* @eccstrength - the number of bits that could be corrected
* (1 - hamming, 4 - BCH4, 8 - BCH8, 16 - BCH16)
*/
void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
int __maybe_unused omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
{
struct nand_chip *nand;
struct mtd_info *mtd;
int err = 0;
if (nand_curr_device < 0 ||
nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
!nand_info[nand_curr_device].name) {
printf("Error: Can't switch ecc, no devices available\n");
return;
printf("nand: error: no NAND devices found\n");
return -ENODEV;
}
mtd = &nand_info[nand_curr_device];
nand = mtd->priv;
nand->options |= NAND_OWN_BUFFERS;
/* Reset ecc interface */
nand->ecc.mode = NAND_ECC_NONE;
nand->ecc.read_page = NULL;
nand->ecc.write_page = NULL;
nand->ecc.read_oob = NULL;
nand->ecc.write_oob = NULL;
nand->ecc.hwctl = NULL;
nand->ecc.correct = NULL;
nand->ecc.calculate = NULL;
nand->ecc.strength = eccstrength;
/* Setup the ecc configurations again */
if (hardware) {
if (eccstrength == 1) {
nand->ecc.mode = NAND_ECC_HW;
nand->ecc.layout = &hw_nand_oob;
nand->ecc.size = 512;
nand->ecc.bytes = 3;
nand->ecc.hwctl = omap_enable_hwecc;
nand->ecc.correct = omap_correct_data;
nand->ecc.calculate = omap_calculate_ecc;
omap_hwecc_init(nand);
printf("1-bit hamming HW ECC selected\n");
}
#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8)
else if (eccstrength == 8) {
nand->ecc.mode = NAND_ECC_HW;
nand->ecc.layout = &hw_bch8_nand_oob;
nand->ecc.size = 512;
#ifdef CONFIG_AM33XX
nand->ecc.bytes = 14;
nand->ecc.read_page = omap_read_page_bch;
#else
nand->ecc.bytes = 13;
#endif
nand->ecc.hwctl = omap_enable_ecc_bch;
nand->ecc.correct = omap_correct_data_bch;
nand->ecc.calculate = omap_calculate_ecc_bch;
omap_hwecc_init_bch(nand, NAND_ECC_READ);
printf("8-bit BCH HW ECC selected\n");
err = omap_select_ecc_scheme(nand,
OMAP_ECC_HAM1_CODE_HW,
mtd->writesize, mtd->oobsize);
} else if (eccstrength == 8) {
err = omap_select_ecc_scheme(nand,
OMAP_ECC_BCH8_CODE_HW,
mtd->writesize, mtd->oobsize);
} else {
printf("nand: error: unsupported ECC scheme\n");
return -EINVAL;
}
#endif
} else {
nand->ecc.mode = NAND_ECC_SOFT;
/* Use mtd default settings */
nand->ecc.layout = NULL;
nand->ecc.size = 0;
printf("SW ECC selected\n");
err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
mtd->writesize, mtd->oobsize);
}
/* Update NAND handling after ECC mode switch */
nand_scan_tail(mtd);
nand->options &= ~NAND_OWN_BUFFERS;
if (!err)
err = nand_scan_tail(mtd);
return err;
}
#endif /* CONFIG_SPL_BUILD */
@ -856,7 +964,7 @@ int board_nand_init(struct nand_chip *nand)
{
int32_t gpmc_config = 0;
cs = 0;
int err = 0;
/*
* xloader/Uboot's gpmc configuration would have configured GPMC for
* nand type of memory. The following logic scans and latches on to the
@ -873,7 +981,7 @@ int board_nand_init(struct nand_chip *nand)
cs++;
}
if (cs >= GPMC_MAX_CS) {
printf("NAND: Unable to find NAND settings in "
printf("nand: error: Unable to find NAND settings in "
"GPMC Configuration - quitting\n");
return -ENODEV;
}
@ -885,64 +993,27 @@ int board_nand_init(struct nand_chip *nand)
nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
nand->cmd_ctrl = omap_nand_hwcontrol;
nand->options = NAND_NO_PADDING | NAND_CACHEPRG;
nand->priv = &bch_priv;
nand->cmd_ctrl = omap_nand_hwcontrol;
nand->options |= NAND_NO_PADDING | NAND_CACHEPRG;
/* If we are 16 bit dev, our gpmc config tells us that */
if ((readl(&gpmc_cfg->cs[cs].config1) & 0x3000) == 0x1000)
nand->options |= NAND_BUSWIDTH_16;
nand->chip_delay = 100;
nand->ecc.layout = &omap_ecclayout;
#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8)
#ifdef CONFIG_AM33XX
/* AM33xx uses the ELM */
/* required in case of BCH */
elm_init();
#else
/*
* Whereas other OMAP based SoC do not have the ELM, they use the BCH
* SW library.
*/
bch_priv.control = init_bch(13, 8, 0x201b /* hw polynominal */);
if (!bch_priv.control) {
puts("Could not init_bch()\n");
return -ENODEV;
}
#endif
/* BCH info that will be correct for SPL or overridden otherwise. */
nand->priv = &bch_priv;
#endif
/* Default ECC mode */
#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8)
nand->ecc.mode = NAND_ECC_HW;
nand->ecc.layout = &hw_bch8_nand_oob;
nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
nand->ecc.strength = 8;
nand->ecc.hwctl = omap_enable_ecc_bch;
nand->ecc.correct = omap_correct_data_bch;
nand->ecc.calculate = omap_calculate_ecc_bch;
#ifdef CONFIG_AM33XX
nand->ecc.read_page = omap_read_page_bch;
#endif
omap_hwecc_init_bch(nand, NAND_ECC_READ);
#else
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_NAND_SOFTECC)
nand->ecc.mode = NAND_ECC_SOFT;
/* select ECC scheme */
#if defined(CONFIG_NAND_OMAP_ECCSCHEME)
err = omap_select_ecc_scheme(nand, CONFIG_NAND_OMAP_ECCSCHEME,
CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE);
#else
nand->ecc.mode = NAND_ECC_HW;
nand->ecc.layout = &hw_nand_oob;
nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
nand->ecc.hwctl = omap_enable_hwecc;
nand->ecc.correct = omap_correct_data;
nand->ecc.calculate = omap_calculate_ecc;
nand->ecc.strength = 1;
omap_hwecc_init(nand);
#endif
/* pagesize and oobsize are not required to configure sw ecc-scheme */
err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
0, 0);
#endif
if (err)
return err;
#ifdef CONFIG_SPL_BUILD
if (nand->options & NAND_BUSWIDTH_16)

@ -761,7 +761,8 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf,
uint8_t *oob_buf = this->oob_buf;
free = this->ecclayout->oobfree;
for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && free->length;
i++, free++) {
if (readcol >= lastgap)
readcol += free->offset - lastgap;
if (readend >= lastgap)
@ -770,7 +771,8 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf,
}
this->read_bufferram(mtd, 0, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize);
free = this->ecclayout->oobfree;
for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && free->length;
i++, free++) {
int free_end = free->offset + free->length;
if (free->offset < readend && free_end > readcol) {
int st = max_t(int,free->offset,readcol);
@ -1356,7 +1358,8 @@ static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf,
unsigned int i;
free = this->ecclayout->oobfree;
for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && free->length;
i++, free++) {
if (writecol >= lastgap)
writecol += free->offset - lastgap;
if (writeend >= lastgap)
@ -1364,7 +1367,8 @@ static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf,
lastgap = free->offset + free->length;
}
free = this->ecclayout->oobfree;
for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && free->length;
i++, free++) {
int free_end = free->offset + free->length;
if (free->offset < writeend && free_end > writecol) {
int st = max_t(int,free->offset,writecol);
@ -2750,7 +2754,8 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
* the out of band area
*/
this->ecclayout->oobavail = 0;
for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES &&
for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE &&
this->ecclayout->oobfree[i].length; i++)
this->ecclayout->oobavail +=
this->ecclayout->oobfree[i].length;

@ -143,6 +143,8 @@
#define CONFIG_SYS_NAND_SKIP_BAD_DOT_I 1 /* ".i" read skips bad blocks */
#define CONFIG_SYS_NAND_QUIET 1
#define CONFIG_SYS_NAND_MAX_OOBFREE 2
#define CONFIG_SYS_NAND_MAX_ECCPOS 56
/*-----------------------------------------------------------------------
* PCI stuff

@ -191,13 +191,14 @@
| CSPR_MSEL_NAND \
| CSPR_V)
#define CONFIG_SYS_NAND_AMASK IFC_AMASK(64*1024)
#define CONFIG_SYS_NAND_OOBSIZE 0x00000280 /* 640b */
#define CONFIG_SYS_NAND_CSOR (CSOR_NAND_ECC_ENC_EN /* ECC on encode */ \
| CSOR_NAND_ECC_DEC_EN /* ECC on decode */ \
| CSOR_NAND_ECC_MODE_4 /* 4-bit ECC */ \
| CSOR_NAND_RAL_2 /* RAL = 2 Bytes */ \
| CSOR_NAND_PGS_2K /* Page Size = 2k */ \
| CSOR_NAND_SPRZ_64 /* Spare size = 64 */ \
| CSOR_NAND_PB(64)) /* 64 Pages Per Block */
| CSOR_NAND_RAL_3 /* RAL = 3 Bytes */ \
| CSOR_NAND_PGS_8K /* Page Size = 8K */ \
| CSOR_NAND_SPRZ_CSOR_EXT /*oob in csor_ext*/\
| CSOR_NAND_PB(128)) /*128 Pages Per Block*/
#define CONFIG_SYS_NAND_FTIM0 (FTIM0_NAND_TCCST(0x01) | \
FTIM0_NAND_TWP(0x0c) | \
FTIM0_NAND_TWCHT(0x08) | \
@ -224,6 +225,7 @@
#define CONFIG_SYS_CSPR1 CONFIG_SYS_NAND_CSPR
#define CONFIG_SYS_AMASK1 CONFIG_SYS_NAND_AMASK
#define CONFIG_SYS_CSOR1 CONFIG_SYS_NAND_CSOR
#define CONFIG_SYS_CSOR1_EXT CONFIG_SYS_NAND_OOBSIZE
#define CONFIG_SYS_CS1_FTIM0 CONFIG_SYS_NAND_FTIM0
#define CONFIG_SYS_CS1_FTIM1 CONFIG_SYS_NAND_FTIM1
#define CONFIG_SYS_CS1_FTIM2 CONFIG_SYS_NAND_FTIM2

@ -322,6 +322,8 @@
#define CONFIG_CMD_NAND 1
#define CONFIG_NAND_FSL_ELBC 1
#define CONFIG_SYS_NAND_BLOCK_SIZE (128 * 1024)
#define CONFIG_SYS_NAND_MAX_OOBFREE 5
#define CONFIG_SYS_NAND_MAX_ECCPOS 56
/* NAND boot: 4K NAND loader config */
#define CONFIG_SYS_NAND_SPL_SIZE 0x1000

@ -229,6 +229,8 @@ unsigned long get_board_ddr_clk(void);
#define CONFIG_CMD_NAND
#define CONFIG_SYS_NAND_BLOCK_SIZE (128 * 1024)
#define CONFIG_SYS_NAND_MAX_OOBFREE 2
#define CONFIG_SYS_NAND_MAX_ECCPOS 256
#if defined(CONFIG_NAND)
#define CONFIG_SYS_CSPR0_EXT CONFIG_SYS_NAND_CSPR_EXT

@ -324,6 +324,8 @@
#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE + 0, CONFIG_SYS_NAND_BASE + 2, \
CONFIG_SYS_NAND_BASE + 4, CONFIG_SYS_NAND_BASE + 6 }
#define CONFIG_SYS_NAND_QUIET_TEST 1 /* don't warn upon unknown NAND flash */
#define CONFIG_SYS_NAND_MAX_OOBFREE 2
#define CONFIG_SYS_NAND_MAX_ECCPOS 56
/*-----------------------------------------------------------------------
* External Bus Controller (EBC) Setup

@ -220,6 +220,8 @@
#define CONFIG_SPL_LDSCRIPT "$(CPUDIR)/am33xx/u-boot-spl.lds"
#ifdef CONFIG_NAND
#define CONFIG_NAND_OMAP_GPMC
#define CONFIG_NAND_OMAP_ELM
#define CONFIG_SYS_NAND_5_ADDR_CYCLE
#define CONFIG_SYS_NAND_PAGE_COUNT (CONFIG_SYS_NAND_BLOCK_SIZE / \
CONFIG_SYS_NAND_PAGE_SIZE)
@ -237,7 +239,8 @@
#define CONFIG_SYS_NAND_ECCSIZE 512
#define CONFIG_SYS_NAND_ECCBYTES 14
#define CONFIG_SYS_NAND_ONFI_DETECTION
#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_BCH8_CODE_HW
#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE
#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000
#endif

@ -187,6 +187,7 @@
/* NAND support */
#define CONFIG_NAND
#define CONFIG_NAND_OMAP_GPMC
#define CONFIG_NAND_OMAP_ELM
#define GPMC_NAND_ECC_LP_x16_LAYOUT 1
#define CONFIG_SYS_NAND_BASE (0x08000000) /* phys address CS0 */
#define CONFIG_SYS_MAX_NAND_DEVICE 1
@ -263,6 +264,7 @@
#define CONFIG_SYS_NAND_ECCSIZE 512
#define CONFIG_SYS_NAND_ECCBYTES 14
#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_BCH8_CODE_HW
#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE

@ -340,6 +340,7 @@
10, 11, 12, 13}
#define CONFIG_SYS_NAND_ECCSIZE 512
#define CONFIG_SYS_NAND_ECCBYTES 3
#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_HW
#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE
#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000

@ -334,6 +334,7 @@
10, 11, 12, 13}
#define CONFIG_SYS_NAND_ECCSIZE 512
#define CONFIG_SYS_NAND_ECCBYTES 3
#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_HW
#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE
#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000

@ -327,6 +327,7 @@
#define CONFIG_SYS_NAND_ECCSIZE 512
#define CONFIG_SYS_NAND_ECCBYTES 3
#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_HW
#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE

@ -353,7 +353,6 @@
#define CONFIG_SPL_FRAMEWORK
#define CONFIG_SPL_BOARD_INIT
#define CONFIG_SPL_NAND_SIMPLE
#define CONFIG_SPL_NAND_SOFTECC
#define CONFIG_SPL_LIBCOMMON_SUPPORT
#define CONFIG_SPL_LIBDISK_SUPPORT
@ -395,6 +394,7 @@
56, 57, 58, 59, 60, 61, 62, 63}
#define CONFIG_SYS_NAND_ECCSIZE 256
#define CONFIG_SYS_NAND_ECCBYTES 3
#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_SW
#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE

@ -431,6 +431,7 @@
10, 11, 12, 13}
#define CONFIG_SYS_NAND_ECCSIZE 512
#define CONFIG_SYS_NAND_ECCBYTES 3
#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_HW
#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE
#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000

@ -107,6 +107,7 @@
10, 11, 12, 13}
#define CONFIG_SYS_NAND_ECCSIZE 512
#define CONFIG_SYS_NAND_ECCBYTES 3
#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_HW
#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE
#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000

@ -86,6 +86,7 @@
10, 11, 12, 13}
#define CONFIG_SYS_NAND_ECCSIZE 512
#define CONFIG_SYS_NAND_ECCBYTES 3
#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_HW
#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE
#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000

@ -362,6 +362,7 @@
10, 11, 12, 13}
#define CONFIG_SYS_NAND_ECCSIZE 512
#define CONFIG_SYS_NAND_ECCBYTES 3
#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_HW
#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE
#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000
#endif

@ -324,6 +324,7 @@
10, 11, 12, 13}
#define CONFIG_SYS_NAND_ECCSIZE 512
#define CONFIG_SYS_NAND_ECCBYTES 3
#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_HW
#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE
#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000

@ -195,6 +195,7 @@
#define CONFIG_SYS_NAND_ECCSIZE 512
#define CONFIG_SYS_NAND_ECCBYTES 14
#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_BCH8_CODE_HW
#define CONFIG_SYS_NAND_ECCSTEPS 4
#define CONFIG_SYS_NAND_ECCTOTAL (CONFIG_SYS_NAND_ECCBYTES * \
@ -430,6 +431,7 @@
"\0"
#define CONFIG_NAND_OMAP_GPMC
#define CONFIG_NAND_OMAP_ELM
#define GPMC_NAND_ECC_LP_x16_LAYOUT 1
#define CONFIG_SYS_NAND_BASE (0x08000000) /* physical address */
/* to access nand at */

@ -224,7 +224,6 @@
#define CONFIG_SPL_BOARD_INIT
#define CONFIG_SPL_CONSOLE
#define CONFIG_SPL_NAND_SIMPLE
#define CONFIG_SPL_NAND_SOFTECC
#define CONFIG_SPL_NAND_WORKSPACE 0x8f07f000 /* below BSS */
#define CONFIG_SPL_LIBCOMMON_SUPPORT
@ -261,6 +260,7 @@
56, 57, 58, 59, 60, 61, 62, 63}
#define CONFIG_SYS_NAND_ECCSIZE 256
#define CONFIG_SYS_NAND_ECCBYTES 3
#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_SW
#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE

@ -138,8 +138,9 @@
#define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND */
/* devices */
#define CONFIG_NAND_OMAP_BCH8
#define CONFIG_BCH
#define CONFIG_SYS_NAND_MAX_OOBFREE 2
#define CONFIG_SYS_NAND_MAX_ECCPOS 56
/* commands to include */
#include <config_cmd_default.h>
@ -374,6 +375,7 @@
#define CONFIG_SYS_NAND_ECCSIZE 512
#define CONFIG_SYS_NAND_ECCBYTES 13
#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_BCH8_CODE_HW_DETECTION_SW
#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE

@ -96,6 +96,29 @@ struct mtd_oob_ops {
uint8_t *oobbuf;
};
#ifdef CONFIG_SYS_NAND_MAX_OOBFREE
#define MTD_MAX_OOBFREE_ENTRIES_LARGE CONFIG_SYS_NAND_MAX_OOBFREE
#else
#define MTD_MAX_OOBFREE_ENTRIES_LARGE 32
#endif
#ifdef CONFIG_SYS_NAND_MAX_ECCPOS
#define MTD_MAX_ECCPOS_ENTRIES_LARGE CONFIG_SYS_NAND_MAX_ECCPOS
#else
#define MTD_MAX_ECCPOS_ENTRIES_LARGE 640
#endif
/*
* ECC layout control structure. Exported to userspace for
* diagnosis and to allow creation of raw images
*/
struct nand_ecclayout {
uint32_t eccbytes;
uint32_t eccpos[MTD_MAX_ECCPOS_ENTRIES_LARGE];
uint32_t oobavail;
struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES_LARGE];
};
struct mtd_info {
u_char type;
u_int32_t flags;

@ -155,18 +155,6 @@ struct nand_oobfree {
uint32_t length;
};
#define MTD_MAX_OOBFREE_ENTRIES 8
/*
* ECC layout control structure. Exported to userspace for
* diagnosis and to allow creation of raw images
*/
struct nand_ecclayout {
uint32_t eccbytes;
uint32_t eccpos[128];
uint32_t oobavail;
struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
};
/**
* struct mtd_ecc_stats - error correction stats
*

Loading…
Cancel
Save