diff options
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r-- | drivers/mtd/nand/atmel_nand.c | 63 |
1 files changed, 56 insertions, 7 deletions
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 304491bcb41..15fb4fb38d1 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -16,6 +16,7 @@ #include <asm/arch/gpio.h> #include <asm/arch/at91_pio.h> +#include <malloc.h> #include <nand.h> #include <watchdog.h> @@ -50,13 +51,13 @@ struct atmel_nand_host { void __iomem *pmecc_index_of; /* data for pmecc computation */ - int16_t pmecc_smu[(CONFIG_PMECC_CAP + 2) * (2 * CONFIG_PMECC_CAP + 1)]; - int16_t pmecc_partial_syn[2 * CONFIG_PMECC_CAP + 1]; - int16_t pmecc_si[2 * CONFIG_PMECC_CAP + 1]; - int16_t pmecc_lmu[CONFIG_PMECC_CAP + 1]; /* polynomal order */ - int pmecc_mu[CONFIG_PMECC_CAP + 1]; - int pmecc_dmu[CONFIG_PMECC_CAP + 1]; - int pmecc_delta[CONFIG_PMECC_CAP + 1]; + int16_t *pmecc_smu; + int16_t *pmecc_partial_syn; + int16_t *pmecc_si; + int16_t *pmecc_lmu; /* polynomal order */ + int *pmecc_mu; + int *pmecc_dmu; + int *pmecc_delta; }; static struct atmel_nand_host pmecc_host; @@ -109,6 +110,48 @@ static void __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host) table_size * sizeof(int16_t); } +static void pmecc_data_free(struct atmel_nand_host *host) +{ + free(host->pmecc_partial_syn); + free(host->pmecc_si); + free(host->pmecc_lmu); + free(host->pmecc_smu); + free(host->pmecc_mu); + free(host->pmecc_dmu); + free(host->pmecc_delta); +} + +static int pmecc_data_alloc(struct atmel_nand_host *host) +{ + const int cap = host->pmecc_corr_cap; + int size; + + size = (2 * cap + 1) * sizeof(int16_t); + host->pmecc_partial_syn = malloc(size); + host->pmecc_si = malloc(size); + host->pmecc_lmu = malloc((cap + 1) * sizeof(int16_t)); + host->pmecc_smu = malloc((cap + 2) * size); + + size = (cap + 1) * sizeof(int); + host->pmecc_mu = malloc(size); + host->pmecc_dmu = malloc(size); + host->pmecc_delta = malloc(size); + + if (host->pmecc_partial_syn && + host->pmecc_si && + host->pmecc_lmu && + host->pmecc_smu && + host->pmecc_mu && + host->pmecc_dmu && + host->pmecc_delta) + return 0; + + /* error happened */ + pmecc_data_free(host); + return -ENOMEM; + +} + static void pmecc_gen_syndrome(struct mtd_info *mtd, int sector) { struct nand_chip *nand_chip = mtd->priv; @@ -694,6 +737,12 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand, return 0; } + /* Allocate data for PMECC computation */ + if (pmecc_data_alloc(host)) { + dev_err(host->dev, "Cannot allocate memory for PMECC computation!\n"); + return -ENOMEM; + } + nand->ecc.read_page = atmel_nand_pmecc_read_page; nand->ecc.write_page = atmel_nand_pmecc_write_page; nand->ecc.strength = cap; |