diff options
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/atmel_nand.c | 60 | ||||
-rw-r--r-- | drivers/mtd/nand/atmel_nand_ecc.h | 36 |
2 files changed, 51 insertions, 45 deletions
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 0d4f327..7cc1de0 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -80,6 +80,7 @@ static struct nand_ecclayout atmel_pmecc_oobinfo; * 8-bits 13-bytes 14-bytes * 12-bits 20-bytes 21-bytes * 24-bits 39-bytes 42-bytes + * 32-bits 52-bytes 56-bytes */ static int pmecc_get_ecc_bytes(int cap, int sector_size) { @@ -638,6 +639,9 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd) case 24: val = PMECC_CFG_BCH_ERR24; break; + case 32: + val = PMECC_CFG_BCH_ERR32; + break; } if (host->pmecc_sector_size == 512) @@ -677,34 +681,6 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd) #ifdef CONFIG_SYS_NAND_ONFI_DETECTION /* - * get_onfi_ecc_param - Get ECC requirement from ONFI parameters - * @ecc_bits: store the ONFI ECC correct bits capbility - * @sector_size: in how many bytes that ONFI require to correct @ecc_bits - * - * Returns -1 if ONFI parameters is not supported. In this case @ecc_bits, - * @sector_size are initialize to 0. - * Return 0 if success to get the ECC requirement. - */ -static int get_onfi_ecc_param(struct nand_chip *chip, - int *ecc_bits, int *sector_size) -{ - *ecc_bits = *sector_size = 0; - - if (chip->onfi_params.ecc_bits == 0xff) - /* TODO: the sector_size and ecc_bits need to be find in - * extended ecc parameter, currently we don't support it. - */ - return -1; - - *ecc_bits = chip->onfi_params.ecc_bits; - - /* The default sector size (ecc codeword size) is 512 */ - *sector_size = 512; - - return 0; -} - -/* * pmecc_choose_ecc - Get ecc requirement from ONFI parameters. If * pmecc_corr_cap or pmecc_sector_size is 0, then set it as * ONFI ECC parameters. @@ -724,17 +700,15 @@ static int pmecc_choose_ecc(struct atmel_nand_host *host, /* Get ECC requirement from ONFI parameters */ *cap = *sector_size = 0; if (chip->onfi_version) { - if (!get_onfi_ecc_param(chip, cap, sector_size)) { - MTDDEBUG(MTD_DEBUG_LEVEL1, "ONFI params, minimum required ECC: %d bits in %d bytes\n", - *cap, *sector_size); - } else { - dev_info(host->dev, "NAND chip ECC reqirement is in Extended ONFI parameter, we don't support yet.\n"); - } - } else { - dev_info(host->dev, "NAND chip is not ONFI compliant, assume ecc_bits is 2 in 512 bytes"); + *cap = chip->ecc_strength_ds; + *sector_size = chip->ecc_step_ds; + MTDDEBUG(MTD_DEBUG_LEVEL1, "ONFI params, minimum required ECC: %d bits in %d bytes\n", + *cap, *sector_size); } + if (*cap == 0 && *sector_size == 0) { - /* Non-ONFI compliant or use extended ONFI parameters */ + /* Non-ONFI compliant */ + dev_info(host->dev, "NAND chip is not ONFI compliant, assume ecc_bits is 2 in 512 bytes\n"); *cap = 2; *sector_size = 512; } @@ -753,7 +727,11 @@ static int pmecc_choose_ecc(struct atmel_nand_host *host, else if (*cap <= 24) host->pmecc_corr_cap = 24; else - return -EINVAL; +#ifdef CONFIG_SAMA5D2 + host->pmecc_corr_cap = 32; +#else + host->pmecc_corr_cap = 24; +#endif } if (host->pmecc_sector_size == 0) { /* use the most fitable sector size (the near smaller one ) */ @@ -851,8 +829,8 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand, * from ONFI. */ if (pmecc_choose_ecc(host, nand, &cap, §or_size)) { - dev_err(host->dev, "The NAND flash's ECC requirement(ecc_bits: %d, sector_size: %d) are not support!", - cap, sector_size); + dev_err(host->dev, "Required ECC %d bits in %d bytes not supported!\n", + cap, sector_size); return -EINVAL; } @@ -931,7 +909,7 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand, return -EINVAL; } - if (nand->ecc.bytes > mtd->oobsize - 2) { + if (nand->ecc.bytes > mtd->oobsize - PMECC_OOB_RESERVED_BYTES) { dev_err(host->dev, "No room for ECC bytes\n"); return -EINVAL; } diff --git a/drivers/mtd/nand/atmel_nand_ecc.h b/drivers/mtd/nand/atmel_nand_ecc.h index 79e3994..e13f385 100644 --- a/drivers/mtd/nand/atmel_nand_ecc.h +++ b/drivers/mtd/nand/atmel_nand_ecc.h @@ -58,14 +58,23 @@ struct pmecc_regs { /* 0x40 + sector_num * (0x40), Redundancy Registers */ struct { +#ifdef CONFIG_SAMA5D2 + u8 ecc[56]; /* PMECC Generated Redundancy Byte Per Sector */ + u32 reserved1[2]; +#else u8 ecc[44]; /* PMECC Generated Redundancy Byte Per Sector */ u32 reserved1[5]; +#endif } ecc_port[PMECC_MAX_SECTOR_NUM]; /* 0x240 + sector_num * (0x40) Remainder Registers */ struct { +#ifdef CONFIG_SAMA5D2 + u32 rem[16]; +#else u32 rem[12]; u32 reserved2[4]; +#endif } rem_port[PMECC_MAX_SECTOR_NUM]; u32 reserved3[16]; /* 0x440-0x47C Reserved */ }; @@ -76,6 +85,7 @@ struct pmecc_regs { #define PMECC_CFG_BCH_ERR8 (2 << 0) #define PMECC_CFG_BCH_ERR12 (3 << 0) #define PMECC_CFG_BCH_ERR24 (4 << 0) +#define PMECC_CFG_BCH_ERR32 (5 << 0) #define PMECC_CFG_SECTOR512 (0 << 4) #define PMECC_CFG_SECTOR1024 (1 << 4) @@ -120,19 +130,31 @@ struct pmecc_errloc_regs { u32 elimr; /* 0x0C Error Location Interrupt Mask Register */ u32 elisr; /* 0x20 Error Location Interrupt Status Register */ u32 reserved0; /* 0x24 Reserved */ +#ifdef CONFIG_SAMA5D2 + u32 sigma[33]; /* 0x28-0xA8 Error Location Sigma Registers */ + u32 el[32]; /* 0xAC-0x128 Error Location Registers */ + + /* + * 0x12C-0x1FC: + * Reserved for SAMA5D2. + */ + u32 reserved1[53]; +#else u32 sigma[25]; /* 0x28-0x88 Error Location Sigma Registers */ u32 el[24]; /* 0x8C-0xE8 Error Location Registers */ u32 reserved1[5]; /* 0xEC-0xFC Reserved */ +#endif /* - * 0x100-0x1F8: - * Reserved for AT91SAM9X5, AT91SAM9N12. - * HSMC registers for SAMA5D3, SAMA5D4. + * SAMA5 chip HSMC registers start here. But for 9X5 chip it is just + * reserved. + * + * Offset 0x00-0xF8: */ u32 reserved2[63]; /* - * 0x1FC: + * Offset 0xFC: * PMECC version for AT91SAM9X5, AT91SAM9N12. * HSMC version for SAMA5D3, SAMA5D4. Can refer as PMECC version. */ @@ -148,10 +170,16 @@ struct pmecc_errloc_regs { #define PMERRLOC_DISABLE (1 << 0) /* For Error Location Interrupt Status Register */ +#ifdef CONFIG_SAMA5D2 +#define PMERRLOC_ERR_NUM_MASK (0x3f << 8) +#else #define PMERRLOC_ERR_NUM_MASK (0x1f << 8) +#endif + #define PMERRLOC_CALC_DONE (1 << 0) /* PMECC IP version */ +#define PMECC_VERSION_SAMA5D2 0x210 #define PMECC_VERSION_SAMA5D4 0x113 #define PMECC_VERSION_SAMA5D3 0x112 #define PMECC_VERSION_AT91SAM9N12 0x102 |