summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2010-07-12 08:22:03 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2010-07-12 08:22:03 +0200
commit6ffe2ec8cd37e432fdfc08f71cb9a46767ef1e39 (patch)
tree4ef60a59d5ca2ab0bb4391da3175fd868bffebbc /drivers
parenta2f567095ba3831a3198aa2e1cacda2f5dcbf820 (diff)
parent0be6fd0bf642541dbe999dbead7c3ae7e9c9db16 (diff)
downloadbarebox-6ffe2ec8cd37e432fdfc08f71cb9a46767ef1e39.tar.gz
barebox-6ffe2ec8cd37e432fdfc08f71cb9a46767ef1e39.tar.xz
Merge remote branch 'origin/omap' into next
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/nand/Kconfig8
-rw-r--r--drivers/mtd/nand/nand_omap_gpmc.c103
2 files changed, 87 insertions, 24 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index e0d9d0d3b6..ddc0c34e7d 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -25,14 +25,6 @@ config NAND_OMAP_GPMC
Support for NAND flash using GPMC. GPMC is a common memory
interface found on Texas Instrument's OMAP platforms
-config NAND_OMAP_GPMC_HWECC
- bool "The Hardware ECC support"
- depends on NAND && NAND_OMAP_GPMC
- default n
- help
- The ECC compuatation for the data to be written/read can be either by
- software or omap has Hw ecc engine which calculates it.
-
config NAND_ATMEL
bool
prompt "Atmel (AT91SAM9xxx) NAND driver"
diff --git a/drivers/mtd/nand/nand_omap_gpmc.c b/drivers/mtd/nand/nand_omap_gpmc.c
index c6647e56ed..1363808ce0 100644
--- a/drivers/mtd/nand/nand_omap_gpmc.c
+++ b/drivers/mtd/nand/nand_omap_gpmc.c
@@ -102,10 +102,57 @@ struct gpmc_nand_info {
uint64_t timeout;
unsigned inuse:1;
unsigned wait_pol:1;
-#ifdef CONFIG_NAND_OMAP_GPMC_HWECC
unsigned char ecc_parity_pairs;
unsigned int ecc_config;
-#endif
+};
+
+/* Typical BOOTROM oob layouts-requires hwecc **/
+
+/** Large Page x8 NAND device Layout */
+static struct nand_ecclayout ecc_lp_x8 = {
+ .eccbytes = 12,
+ .eccpos = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
+ .oobfree = {
+ {
+ .offset = 60,
+ .length = 2,
+ }
+ }
+};
+
+/** Large Page x16 NAND device Layout */
+static struct nand_ecclayout ecc_lp_x16 = {
+ .eccbytes = 12,
+ .eccpos = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13},
+ .oobfree = {
+ {
+ .offset = 60,
+ .length = 2,
+ }
+ }
+};
+
+/** Small Page x8 NAND device Layout */
+static struct nand_ecclayout ecc_sp_x8 = {
+ .eccbytes = 3,
+ .eccpos = {1, 2, 3},
+ .oobfree = {
+ {
+ .offset = 14,
+ .length = 2,
+ }
+ }
+};
+
+/** Small Page x16 NAND device Layout */
+static struct nand_ecclayout ecc_sp_x16 = {
+ .eccbytes = 3,
+ .eccpos = {2, 3, 4},
+ .oobfree = {
+ {
+ .offset = 14,
+ .length = 2 }
+ }
};
/**
@@ -203,8 +250,6 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
return;
}
-#ifdef CONFIG_NAND_OMAP_GPMC_HWECC
-
/**
* @brief This function will generate true ECC value, which can be used
* when correcting data read from NAND flash memory core
@@ -345,7 +390,6 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
break;
}
}
-#endif /* CONFIG_NAND_OMAP_GPMC_HWECC */
/**
* @brief nand device probe.
@@ -362,6 +406,7 @@ static int gpmc_nand_probe(struct device_d *pdev)
struct mtd_info *minfo;
unsigned long cs_base;
int err;
+ struct nand_ecclayout *layout, *lsp, *llp;
gpmcnand_dbg("pdev=%x", (unsigned int)pdev);
pdata = (struct gpmc_nand_platform_data *)pdev->platform_data;
@@ -453,11 +498,6 @@ static int gpmc_nand_probe(struct device_d *pdev)
/* State my controller */
nand->controller = &oinfo->controller;
- /* if a different placement scheme is requested */
- if (pdata->oob)
- nand->ecc.layout = pdata->oob;
-
-#ifdef CONFIG_NAND_OMAP_GPMC_HWECC
if (pdata->plat_options & NAND_HWECC_ENABLE) {
/* Program how many columns we expect+
* enable the cs we want and enable the engine
@@ -474,7 +514,6 @@ static int gpmc_nand_probe(struct device_d *pdev)
nand->ecc.steps = nand->ecc.layout->eccbytes / nand->ecc.bytes;
oinfo->ecc_parity_pairs = 12;
} else
-#endif
nand->ecc.mode = NAND_ECC_SOFT;
/* All information is ready.. now lets call setup, if present */
@@ -495,15 +534,47 @@ static int gpmc_nand_probe(struct device_d *pdev)
writeb(NAND_CMD_RESET, oinfo->gpmc_command);
mdelay(1);
- /* In normal mode, we scan to get just the device
- * presence and then to get the device geometry
- */
- if (nand_scan(minfo, 1)) {
- gpmcnand_err("device scan failed\n");
+ /* first scan to find the device and get the page size */
+ if (nand_scan_ident(minfo, 1)) {
+ err = -ENXIO;
+ goto out_release_mem;
+ }
+
+ switch (pdata->device_width) {
+ case 8:
+ lsp = &ecc_sp_x8;
+ llp = &ecc_lp_x8;
+ break;
+ case 16:
+ lsp = &ecc_sp_x16;
+ llp = &ecc_lp_x16;
+ break;
+ default:
+ err = -EINVAL;
+ goto out_release_mem;
+ }
+
+ switch (minfo->writesize) {
+ case 512:
+ layout = lsp;
+ break;
+ case 2048:
+ layout = llp;
+ break;
+ default:
+ err = -EINVAL;
+ goto out_release_mem;
+ }
+
+ /* second phase scan */
+ if (nand_scan_tail(minfo)) {
err = -ENXIO;
goto out_release_mem;
}
+ if (pdata->plat_options & NAND_HWECC_ENABLE)
+ nand->ecc.layout = layout;
+
/* We are all set to register with the system now! */
err = add_mtd_device(minfo);
if (err) {