summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Wu <josh.wu@atmel.com>2012-11-30 16:51:10 +0800
committerJosh Wu <josh.wu@atmel.com>2012-11-30 16:51:10 +0800
commit59f94a35a359800c5ef90d258583af7a1a702b63 (patch)
treefb8f7b615863401539577ee07e2cd2bec9145f2d
parenta90f1d0717b76c7b8c1dbc711a4869ab3d309c99 (diff)
atmel_nand: alloc memory for pmecc data
-rw-r--r--drivers/mtd/nand/atmel_nand.c61
1 files changed, 54 insertions, 7 deletions
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 994dd9f095..e2f6c4f2a8 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -32,6 +32,7 @@
#include <asm/arch/gpio.h>
#include <asm/arch/at91_pio.h>
+#include <malloc.h>
#include <nand.h>
#include <watchdog.h>
@@ -66,13 +67,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;
@@ -125,6 +126,45 @@ static void __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host)
table_size * sizeof(int16_t);
}
+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 = (int16_t *)malloc(size);
+ host->pmecc_si = (int16_t *)malloc(size);
+ host->pmecc_lmu = (int16_t *)malloc((cap + 1) * sizeof(int16_t));
+ host->pmecc_smu = (int16_t *)
+ malloc((cap + 2) * (2 * cap + 1) * sizeof(int16_t));
+ size = (cap + 1) * sizeof(int);
+ host->pmecc_mu = (int *)malloc(size);
+ host->pmecc_dmu = (int *)malloc(size);
+ host->pmecc_delta = (int *)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 -ENOMEM;
+
+ return 0;
+}
+
+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 void pmecc_gen_syndrome(struct mtd_info *mtd, int sector)
{
struct nand_chip *nand_chip = mtd->priv;
@@ -704,6 +744,13 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
return 0;
}
+ /* Allocate data for PMECC computation */
+ if (pmecc_data_alloc(host)) {
+ printk(KERN_ERR "Cannot allocate memory for PMECC computation!\n");
+ pmecc_data_free(host);
+ return -ENOMEM;
+ }
+
nand->ecc.read_page = atmel_nand_pmecc_read_page;
nand->ecc.write_page = atmel_nand_pmecc_write_page;