summaryrefslogtreecommitdiff
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/Kconfig15
-rw-r--r--drivers/mtd/nand/Makefile2
-rw-r--r--drivers/mtd/nand/atmel_nand.c9
-rw-r--r--drivers/mtd/nand/autcpu12.c237
-rw-r--r--drivers/mtd/nand/mxc_nand.c96
-rw-r--r--drivers/mtd/nand/omap2.c128
-rw-r--r--drivers/mtd/nand/sh_flctl.c4
-rw-r--r--drivers/mtd/nand/spia.c176
8 files changed, 179 insertions, 488 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 4883139460be..dae191b3c081 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -49,13 +49,6 @@ config MTD_NAND_MUSEUM_IDS
NAND chips (page size 256 byte, erase size 4-8KiB). The IDs
of these chips were reused by later, larger chips.
-config MTD_NAND_AUTCPU12
- tristate "SmartMediaCard on autronix autcpu12 board"
- depends on ARCH_AUTCPU12
- help
- This enables the driver for the autronix autcpu12 board to
- access the SmartMediaCard.
-
config MTD_NAND_DENALI
depends on PCI
tristate "Support Denali NAND controller on Intel Moorestown"
@@ -86,12 +79,6 @@ config MTD_NAND_GPIO
help
This enables a GPIO based NAND flash driver.
-config MTD_NAND_SPIA
- tristate "NAND Flash device on SPIA board"
- depends on ARCH_P720T
- help
- If you had to ask, you don't have one. Say 'N'.
-
config MTD_NAND_AMS_DELTA
tristate "NAND Flash device on Amstrad E3"
depends on MACH_AMS_DELTA
@@ -559,7 +546,7 @@ config MTD_NAND_JZ4740
config MTD_NAND_FSMC
tristate "Support for NAND on ST Micros FSMC"
- depends on PLAT_SPEAR || PLAT_NOMADIK || MACH_U300
+ depends on PLAT_SPEAR || ARCH_NOMADIK || ARCH_U8500 || MACH_U300
help
Enables support for NAND Flash chips on the ST Microelectronics
Flexible Static Memory Controller (FSMC)
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 2cbd0916b733..6c7f2b3ca8ae 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -9,9 +9,7 @@ obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o
obj-$(CONFIG_MTD_SM_COMMON) += sm_common.o
obj-$(CONFIG_MTD_NAND_CAFE) += cafe_nand.o
-obj-$(CONFIG_MTD_NAND_SPIA) += spia.o
obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o
-obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o
obj-$(CONFIG_MTD_NAND_DENALI) += denali.o
obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o
obj-$(CONFIG_MTD_NAND_BF5XX) += bf5xx_nand.o
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 914455783302..92623ac2015a 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -41,6 +41,7 @@
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/platform_data/atmel.h>
+#include <linux/pinctrl/consumer.h>
#include <mach/cpu.h>
@@ -1370,6 +1371,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
struct resource *mem;
struct mtd_part_parser_data ppdata = {};
int res;
+ struct pinctrl *pinctrl;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
@@ -1414,6 +1416,13 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
nand_chip->IO_ADDR_W = host->io_base;
nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl;
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ dev_err(host->dev, "Failed to request pinctrl\n");
+ res = PTR_ERR(pinctrl);
+ goto err_ecc_ioremap;
+ }
+
if (gpio_is_valid(host->board.rdy_pin)) {
res = gpio_request(host->board.rdy_pin, "nand_rdy");
if (res < 0) {
diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c
deleted file mode 100644
index 04769a49a7cb..000000000000
--- a/drivers/mtd/nand/autcpu12.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * drivers/mtd/autcpu12.c
- *
- * Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de>
- *
- * Derived from drivers/mtd/spia.c
- * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Overview:
- * This is a device driver for the NAND flash device found on the
- * autronix autcpu12 board, which is a SmartMediaCard. It supports
- * 16MiB, 32MiB and 64MiB cards.
- *
- *
- * 02-12-2002 TG Cleanup of module params
- *
- * 02-20-2002 TG adjusted for different rd/wr address support
- * added support for read device ready/busy line
- * added page_cache
- *
- * 10-06-2002 TG 128K card support added
- */
-
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-#include <asm/sizes.h>
-#include <mach/autcpu12.h>
-
-/*
- * MTD structure for AUTCPU12 board
- */
-static struct mtd_info *autcpu12_mtd = NULL;
-static void __iomem *autcpu12_fio_base;
-
-/*
- * Define partitions for flash devices
- */
-static struct mtd_partition partition_info16k[] = {
- { .name = "AUTCPU12 flash partition 1",
- .offset = 0,
- .size = 8 * SZ_1M },
- { .name = "AUTCPU12 flash partition 2",
- .offset = 8 * SZ_1M,
- .size = 8 * SZ_1M },
-};
-
-static struct mtd_partition partition_info32k[] = {
- { .name = "AUTCPU12 flash partition 1",
- .offset = 0,
- .size = 8 * SZ_1M },
- { .name = "AUTCPU12 flash partition 2",
- .offset = 8 * SZ_1M,
- .size = 24 * SZ_1M },
-};
-
-static struct mtd_partition partition_info64k[] = {
- { .name = "AUTCPU12 flash partition 1",
- .offset = 0,
- .size = 16 * SZ_1M },
- { .name = "AUTCPU12 flash partition 2",
- .offset = 16 * SZ_1M,
- .size = 48 * SZ_1M },
-};
-
-static struct mtd_partition partition_info128k[] = {
- { .name = "AUTCPU12 flash partition 1",
- .offset = 0,
- .size = 16 * SZ_1M },
- { .name = "AUTCPU12 flash partition 2",
- .offset = 16 * SZ_1M,
- .size = 112 * SZ_1M },
-};
-
-#define NUM_PARTITIONS16K 2
-#define NUM_PARTITIONS32K 2
-#define NUM_PARTITIONS64K 2
-#define NUM_PARTITIONS128K 2
-/*
- * hardware specific access to control-lines
- *
- * ALE bit 4 autcpu12_pedr
- * CLE bit 5 autcpu12_pedr
- * NCE bit 0 fio_ctrl
- *
- */
-static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd,
- unsigned int ctrl)
-{
- struct nand_chip *chip = mtd->priv;
-
- if (ctrl & NAND_CTRL_CHANGE) {
- void __iomem *addr;
- unsigned char bits;
-
- bits = clps_readb(AUTCPU12_SMC_PORT_OFFSET) & ~0x30;
- bits |= (ctrl & NAND_CLE) << 4;
- bits |= (ctrl & NAND_ALE) << 2;
- clps_writeb(bits, AUTCPU12_SMC_PORT_OFFSET);
-
- addr = autcpu12_fio_base + AUTCPU12_SMC_SELECT_OFFSET;
- writeb((readb(addr) & ~0x1) | (ctrl & NAND_NCE), addr);
- }
-
- if (cmd != NAND_CMD_NONE)
- writeb(cmd, chip->IO_ADDR_W);
-}
-
-/*
- * read device ready pin
- */
-int autcpu12_device_ready(struct mtd_info *mtd)
-{
- return clps_readb(AUTCPU12_SMC_PORT_OFFSET) & AUTCPU12_SMC_RDY;
-}
-
-/*
- * Main initialization routine
- */
-static int __init autcpu12_init(void)
-{
- struct nand_chip *this;
- int err = 0;
-
- /* Allocate memory for MTD device structure and private data */
- autcpu12_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip),
- GFP_KERNEL);
- if (!autcpu12_mtd) {
- printk("Unable to allocate AUTCPU12 NAND MTD device structure.\n");
- err = -ENOMEM;
- goto out;
- }
-
- /* map physical address */
- autcpu12_fio_base = ioremap(AUTCPU12_PHYS_SMC, SZ_1K);
- if (!autcpu12_fio_base) {
- printk("Ioremap autcpu12 SmartMedia Card failed\n");
- err = -EIO;
- goto out_mtd;
- }
-
- /* Get pointer to private data */
- this = (struct nand_chip *)(&autcpu12_mtd[1]);
-
- /* Initialize structures */
- memset(autcpu12_mtd, 0, sizeof(struct mtd_info));
- memset(this, 0, sizeof(struct nand_chip));
-
- /* Link the private data with the MTD structure */
- autcpu12_mtd->priv = this;
- autcpu12_mtd->owner = THIS_MODULE;
-
- /* Set address of NAND IO lines */
- this->IO_ADDR_R = autcpu12_fio_base;
- this->IO_ADDR_W = autcpu12_fio_base;
- this->cmd_ctrl = autcpu12_hwcontrol;
- this->dev_ready = autcpu12_device_ready;
- /* 20 us command delay time */
- this->chip_delay = 20;
- this->ecc.mode = NAND_ECC_SOFT;
-
- /* Enable the following for a flash based bad block table */
- /*
- this->bbt_options = NAND_BBT_USE_FLASH;
- */
- this->bbt_options = NAND_BBT_USE_FLASH;
-
- /* Scan to find existence of the device */
- if (nand_scan(autcpu12_mtd, 1)) {
- err = -ENXIO;
- goto out_ior;
- }
-
- /* Register the partitions */
- switch (autcpu12_mtd->size) {
- case SZ_16M:
- mtd_device_register(autcpu12_mtd, partition_info16k,
- NUM_PARTITIONS16K);
- break;
- case SZ_32M:
- mtd_device_register(autcpu12_mtd, partition_info32k,
- NUM_PARTITIONS32K);
- break;
- case SZ_64M:
- mtd_device_register(autcpu12_mtd, partition_info64k,
- NUM_PARTITIONS64K);
- break;
- case SZ_128M:
- mtd_device_register(autcpu12_mtd, partition_info128k,
- NUM_PARTITIONS128K);
- break;
- default:
- printk("Unsupported SmartMedia device\n");
- err = -ENXIO;
- goto out_ior;
- }
- goto out;
-
- out_ior:
- iounmap(autcpu12_fio_base);
- out_mtd:
- kfree(autcpu12_mtd);
- out:
- return err;
-}
-
-module_init(autcpu12_init);
-
-/*
- * Clean up routine
- */
-static void __exit autcpu12_cleanup(void)
-{
- /* Release resources, unregister device */
- nand_release(autcpu12_mtd);
-
- /* unmap physical address */
- iounmap(autcpu12_fio_base);
-
- /* Free the MTD device structure */
- kfree(autcpu12_mtd);
-}
-
-module_exit(autcpu12_cleanup);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
-MODULE_DESCRIPTION("Glue layer for SmartMediaCard on autronix autcpu12");
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 72e31d86030d..022dcdc256fb 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -37,15 +37,9 @@
#include <asm/mach/flash.h>
#include <linux/platform_data/mtd-mxc_nand.h>
-#include <mach/hardware.h>
#define DRIVER_NAME "mxc_nand"
-#define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35())
-#define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
-#define nfc_is_v3_2a() cpu_is_mx51()
-#define nfc_is_v3_2b() cpu_is_mx53()
-
/* Addresses for NFC registers */
#define NFC_V1_V2_BUF_SIZE (host->regs + 0x00)
#define NFC_V1_V2_BUF_ADDR (host->regs + 0x04)
@@ -1283,6 +1277,53 @@ static const struct mxc_nand_devtype_data imx53_nand_devtype_data = {
.ppb_shift = 8,
};
+static inline int is_imx21_nfc(struct mxc_nand_host *host)
+{
+ return host->devtype_data == &imx21_nand_devtype_data;
+}
+
+static inline int is_imx27_nfc(struct mxc_nand_host *host)
+{
+ return host->devtype_data == &imx27_nand_devtype_data;
+}
+
+static inline int is_imx25_nfc(struct mxc_nand_host *host)
+{
+ return host->devtype_data == &imx25_nand_devtype_data;
+}
+
+static inline int is_imx51_nfc(struct mxc_nand_host *host)
+{
+ return host->devtype_data == &imx51_nand_devtype_data;
+}
+
+static inline int is_imx53_nfc(struct mxc_nand_host *host)
+{
+ return host->devtype_data == &imx53_nand_devtype_data;
+}
+
+static struct platform_device_id mxcnd_devtype[] = {
+ {
+ .name = "imx21-nand",
+ .driver_data = (kernel_ulong_t) &imx21_nand_devtype_data,
+ }, {
+ .name = "imx27-nand",
+ .driver_data = (kernel_ulong_t) &imx27_nand_devtype_data,
+ }, {
+ .name = "imx25-nand",
+ .driver_data = (kernel_ulong_t) &imx25_nand_devtype_data,
+ }, {
+ .name = "imx51-nand",
+ .driver_data = (kernel_ulong_t) &imx51_nand_devtype_data,
+ }, {
+ .name = "imx53-nand",
+ .driver_data = (kernel_ulong_t) &imx53_nand_devtype_data,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(platform, mxcnd_devtype);
+
#ifdef CONFIG_OF_MTD
static const struct of_device_id mxcnd_dt_ids[] = {
{
@@ -1337,32 +1378,6 @@ static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
}
#endif
-static int __init mxcnd_probe_pdata(struct mxc_nand_host *host)
-{
- struct mxc_nand_platform_data *pdata = host->dev->platform_data;
-
- if (!pdata)
- return -ENODEV;
-
- host->pdata = *pdata;
-
- if (nfc_is_v1()) {
- if (cpu_is_mx21())
- host->devtype_data = &imx21_nand_devtype_data;
- else
- host->devtype_data = &imx27_nand_devtype_data;
- } else if (nfc_is_v21()) {
- host->devtype_data = &imx25_nand_devtype_data;
- } else if (nfc_is_v3_2a()) {
- host->devtype_data = &imx51_nand_devtype_data;
- } else if (nfc_is_v3_2b()) {
- host->devtype_data = &imx53_nand_devtype_data;
- } else
- BUG();
-
- return 0;
-}
-
static int __devinit mxcnd_probe(struct platform_device *pdev)
{
struct nand_chip *this;
@@ -1404,8 +1419,16 @@ static int __devinit mxcnd_probe(struct platform_device *pdev)
return PTR_ERR(host->clk);
err = mxcnd_probe_dt(host);
- if (err > 0)
- err = mxcnd_probe_pdata(host);
+ if (err > 0) {
+ struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
+ if (pdata) {
+ host->pdata = *pdata;
+ host->devtype_data = (struct mxc_nand_devtype_data *)
+ pdev->id_entry->driver_data;
+ } else {
+ err = -ENODEV;
+ }
+ }
if (err < 0)
return err;
@@ -1494,7 +1517,7 @@ static int __devinit mxcnd_probe(struct platform_device *pdev)
}
/* first scan to find the device and get the page size */
- if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) {
+ if (nand_scan_ident(mtd, is_imx25_nfc(host) ? 4 : 1, NULL)) {
err = -ENXIO;
goto escan;
}
@@ -1508,7 +1531,7 @@ static int __devinit mxcnd_probe(struct platform_device *pdev)
this->ecc.layout = host->devtype_data->ecclayout_4k;
if (this->ecc.mode == NAND_ECC_HW) {
- if (nfc_is_v1())
+ if (is_imx21_nfc(host) || is_imx27_nfc(host))
this->ecc.strength = 1;
else
this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
@@ -1555,6 +1578,7 @@ static struct platform_driver mxcnd_driver = {
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(mxcnd_dt_ids),
},
+ .id_table = mxcnd_devtype,
.probe = mxcnd_probe,
.remove = __devexit_p(mxcnd_remove),
};
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 5b3138620646..1f34ba104ef4 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -27,8 +27,6 @@
#include <linux/bch.h>
#endif
-#include <plat/dma.h>
-#include <plat/gpmc.h>
#include <linux/platform_data/mtd-nand-omap2.h>
#define DRIVER_NAME "omap2-nand"
@@ -106,10 +104,18 @@
#define CS_MASK 0x7
#define ENABLE_PREFETCH (0x1 << 7)
#define DMA_MPU_MODE_SHIFT 2
+#define ECCSIZE0_SHIFT 12
#define ECCSIZE1_SHIFT 22
#define ECC1RESULTSIZE 0x1
#define ECCCLEAR 0x100
#define ECC1 0x1
+#define PREFETCH_FIFOTHRESHOLD_MAX 0x40
+#define PREFETCH_FIFOTHRESHOLD(val) ((val) << 8)
+#define PREFETCH_STATUS_COUNT(val) (val & 0x00003fff)
+#define PREFETCH_STATUS_FIFO_CNT(val) ((val >> 24) & 0x7F)
+#define STATUS_BUFF_EMPTY 0x00000001
+
+#define OMAP24XX_DMA_GPMC 4
/* oob info generated runtime depending on ecc algorithm and layout selected */
static struct nand_ecclayout omap_oobinfo;
@@ -269,7 +275,7 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
/* wait until buffer is available for write */
do {
status = readl(info->reg.gpmc_status) &
- GPMC_STATUS_BUFF_EMPTY;
+ STATUS_BUFF_EMPTY;
} while (!status);
}
}
@@ -307,7 +313,7 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
/* wait until buffer is available for write */
do {
status = readl(info->reg.gpmc_status) &
- GPMC_STATUS_BUFF_EMPTY;
+ STATUS_BUFF_EMPTY;
} while (!status);
}
}
@@ -348,7 +354,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
} else {
do {
r_count = readl(info->reg.gpmc_prefetch_status);
- r_count = GPMC_PREFETCH_STATUS_FIFO_CNT(r_count);
+ r_count = PREFETCH_STATUS_FIFO_CNT(r_count);
r_count = r_count >> 2;
ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
p += r_count;
@@ -395,7 +401,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
} else {
while (len) {
w_count = readl(info->reg.gpmc_prefetch_status);
- w_count = GPMC_PREFETCH_STATUS_FIFO_CNT(w_count);
+ w_count = PREFETCH_STATUS_FIFO_CNT(w_count);
w_count = w_count >> 1;
for (i = 0; (i < w_count) && len; i++, len -= 2)
iowrite16(*p++, info->nand.IO_ADDR_W);
@@ -407,7 +413,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
do {
cpu_relax();
val = readl(info->reg.gpmc_prefetch_status);
- val = GPMC_PREFETCH_STATUS_COUNT(val);
+ val = PREFETCH_STATUS_COUNT(val);
} while (val && (tim++ < limit));
/* disable and stop the PFPW engine */
@@ -493,7 +499,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
do {
cpu_relax();
val = readl(info->reg.gpmc_prefetch_status);
- val = GPMC_PREFETCH_STATUS_COUNT(val);
+ val = PREFETCH_STATUS_COUNT(val);
} while (val && (tim++ < limit));
/* disable and stop the PFPW engine */
@@ -556,7 +562,7 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
u32 bytes;
bytes = readl(info->reg.gpmc_prefetch_status);
- bytes = GPMC_PREFETCH_STATUS_FIFO_CNT(bytes);
+ bytes = PREFETCH_STATUS_FIFO_CNT(bytes);
bytes = bytes & 0xFFFC; /* io in multiple of 4 bytes */
if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */
if (this_irq == info->gpmc_irq_count)
@@ -682,7 +688,7 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
do {
val = readl(info->reg.gpmc_prefetch_status);
- val = GPMC_PREFETCH_STATUS_COUNT(val);
+ val = PREFETCH_STATUS_COUNT(val);
cpu_relax();
} while (val && (tim++ < limit));
@@ -996,7 +1002,7 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
cond_resched();
}
- status = gpmc_nand_read(info->gpmc_cs, GPMC_NAND_DATA);
+ status = readb(info->reg.gpmc_nand_data);
return status;
}
@@ -1029,19 +1035,45 @@ static int omap_dev_ready(struct mtd_info *mtd)
static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode)
{
int nerrors;
- unsigned int dev_width;
+ unsigned int dev_width, nsectors;
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
struct nand_chip *chip = mtd->priv;
+ u32 val;
nerrors = (info->nand.ecc.bytes == 13) ? 8 : 4;
dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
+ nsectors = 1;
/*
* Program GPMC to perform correction on one 512-byte sector at a time.
* Using 4 sectors at a time (i.e. ecc.size = 2048) is also possible and
* gives a slight (5%) performance gain (but requires additional code).
*/
- (void)gpmc_enable_hwecc_bch(info->gpmc_cs, mode, dev_width, 1, nerrors);
+
+ writel(ECC1, info->reg.gpmc_ecc_control);
+
+ /*
+ * When using BCH, sector size is hardcoded to 512 bytes.
+ * Here we are using wrapping mode 6 both for reading and writing, with:
+ * size0 = 0 (no additional protected byte in spare area)
+ * size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area)
+ */
+ val = (32 << ECCSIZE1_SHIFT) | (0 << ECCSIZE0_SHIFT);
+ writel(val, info->reg.gpmc_ecc_size_config);
+
+ /* BCH configuration */
+ val = ((1 << 16) | /* enable BCH */
+ (((nerrors == 8) ? 1 : 0) << 12) | /* 8 or 4 bits */
+ (0x06 << 8) | /* wrap mode = 6 */
+ (dev_width << 7) | /* bus width */
+ (((nsectors-1) & 0x7) << 4) | /* number of sectors */
+ (info->gpmc_cs << 1) | /* ECC CS */
+ (0x1)); /* enable ECC */
+
+ writel(val, info->reg.gpmc_ecc_config);
+
+ /* clear ecc and enable bits */
+ writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control);
}
/**
@@ -1055,7 +1087,32 @@ static int omap3_calculate_ecc_bch4(struct mtd_info *mtd, const u_char *dat,
{
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
- return gpmc_calculate_ecc_bch4(info->gpmc_cs, dat, ecc_code);
+ unsigned long nsectors, val1, val2;
+ int i;
+
+ nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1;
+
+ for (i = 0; i < nsectors; i++) {
+
+ /* Read hw-computed remainder */
+ val1 = readl(info->reg.gpmc_bch_result0[i]);
+ val2 = readl(info->reg.gpmc_bch_result1[i]);
+
+ /*
+ * Add constant polynomial to remainder, in order to get an ecc
+ * sequence of 0xFFs for a buffer filled with 0xFFs; and
+ * left-justify the resulting polynomial.
+ */
+ *ecc_code++ = 0x28 ^ ((val2 >> 12) & 0xFF);
+ *ecc_code++ = 0x13 ^ ((val2 >> 4) & 0xFF);
+ *ecc_code++ = 0xcc ^ (((val2 & 0xF) << 4)|((val1 >> 28) & 0xF));
+ *ecc_code++ = 0x39 ^ ((val1 >> 20) & 0xFF);
+ *ecc_code++ = 0x96 ^ ((val1 >> 12) & 0xFF);
+ *ecc_code++ = 0xac ^ ((val1 >> 4) & 0xFF);
+ *ecc_code++ = 0x7f ^ ((val1 & 0xF) << 4);
+ }
+
+ return 0;
}
/**
@@ -1069,7 +1126,39 @@ static int omap3_calculate_ecc_bch8(struct mtd_info *mtd, const u_char *dat,
{
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
- return gpmc_calculate_ecc_bch8(info->gpmc_cs, dat, ecc_code);
+ unsigned long nsectors, val1, val2, val3, val4;
+ int i;
+
+ nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1;
+
+ for (i = 0; i < nsectors; i++) {
+
+ /* Read hw-computed remainder */
+ val1 = readl(info->reg.gpmc_bch_result0[i]);
+ val2 = readl(info->reg.gpmc_bch_result1[i]);
+ val3 = readl(info->reg.gpmc_bch_result2[i]);
+ val4 = readl(info->reg.gpmc_bch_result3[i]);
+
+ /*
+ * Add constant polynomial to remainder, in order to get an ecc
+ * sequence of 0xFFs for a buffer filled with 0xFFs.
+ */
+ *ecc_code++ = 0xef ^ (val4 & 0xFF);
+ *ecc_code++ = 0x51 ^ ((val3 >> 24) & 0xFF);
+ *ecc_code++ = 0x2e ^ ((val3 >> 16) & 0xFF);
+ *ecc_code++ = 0x09 ^ ((val3 >> 8) & 0xFF);
+ *ecc_code++ = 0xed ^ (val3 & 0xFF);
+ *ecc_code++ = 0x93 ^ ((val2 >> 24) & 0xFF);
+ *ecc_code++ = 0x9a ^ ((val2 >> 16) & 0xFF);
+ *ecc_code++ = 0xc2 ^ ((val2 >> 8) & 0xFF);
+ *ecc_code++ = 0x97 ^ (val2 & 0xFF);
+ *ecc_code++ = 0x79 ^ ((val1 >> 24) & 0xFF);
+ *ecc_code++ = 0xe5 ^ ((val1 >> 16) & 0xFF);
+ *ecc_code++ = 0x24 ^ ((val1 >> 8) & 0xFF);
+ *ecc_code++ = 0xb5 ^ (val1 & 0xFF);
+ }
+
+ return 0;
}
/**
@@ -1125,7 +1214,7 @@ static void omap3_free_bch(struct mtd_info *mtd)
*/
static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
{
- int ret, max_errors;
+ int max_errors;
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
#ifdef CONFIG_MTD_NAND_OMAP_BCH8
@@ -1142,11 +1231,6 @@ static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
goto fail;
}
- /* initialize GPMC BCH engine */
- ret = gpmc_init_hwecc_bch(info->gpmc_cs, 1, max_errors);
- if (ret)
- goto fail;
-
/* software bch library is only used to detect and locate errors */
info->bch = init_bch(13, max_errors, 0x201b /* hw polynomial */);
if (!info->bch)
@@ -1513,7 +1597,7 @@ static int omap_nand_remove(struct platform_device *pdev)
/* Release NAND device, its internal structures and partitions */
nand_release(&info->mtd);
iounmap(info->nand.IO_ADDR_R);
- release_mem_region(info->phys_base, NAND_IO_SIZE);
+ release_mem_region(info->phys_base, info->mem_size);
kfree(info);
return 0;
}
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
index 4fbfe96e37a1..f48ac5d80bbf 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -727,7 +727,9 @@ static void flctl_select_chip(struct mtd_info *mtd, int chipnr)
if (!flctl->qos_request) {
ret = dev_pm_qos_add_request(&flctl->pdev->dev,
- &flctl->pm_qos, 100);
+ &flctl->pm_qos,
+ DEV_PM_QOS_LATENCY,
+ 100);
if (ret < 0)
dev_err(&flctl->pdev->dev,
"PM QoS request failed: %d\n", ret);
diff --git a/drivers/mtd/nand/spia.c b/drivers/mtd/nand/spia.c
deleted file mode 100644
index bef76cd7c24c..000000000000
--- a/drivers/mtd/nand/spia.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * drivers/mtd/nand/spia.c
- *
- * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
- *
- *
- * 10-29-2001 TG change to support hardwarespecific access
- * to controllines (due to change in nand.c)
- * page_cache added
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Overview:
- * This is a device driver for the NAND flash device found on the
- * SPIA board which utilizes the Toshiba TC58V64AFT part. This is
- * a 64Mibit (8MiB x 8 bits) NAND flash device.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
-#include <asm/io.h>
-
-/*
- * MTD structure for SPIA board
- */
-static struct mtd_info *spia_mtd = NULL;
-
-/*
- * Values specific to the SPIA board (used with EP7212 processor)
- */
-#define SPIA_IO_BASE 0xd0000000 /* Start of EP7212 IO address space */
-#define SPIA_FIO_BASE 0xf0000000 /* Address where flash is mapped */
-#define SPIA_PEDR 0x0080 /*
- * IO offset to Port E data register
- * where the CLE, ALE and NCE pins
- * are wired to.
- */
-#define SPIA_PEDDR 0x00c0 /*
- * IO offset to Port E data direction
- * register so we can control the IO
- * lines.
- */
-
-/*
- * Module stuff
- */
-
-static int spia_io_base = SPIA_IO_BASE;
-static int spia_fio_base = SPIA_FIO_BASE;
-static int spia_pedr = SPIA_PEDR;
-static int spia_peddr = SPIA_PEDDR;
-
-module_param(spia_io_base, int, 0);
-module_param(spia_fio_base, int, 0);
-module_param(spia_pedr, int, 0);
-module_param(spia_peddr, int, 0);
-
-/*
- * Define partitions for flash device
- */
-static const struct mtd_partition partition_info[] = {
- {
- .name = "SPIA flash partition 1",
- .offset = 0,
- .size = 2 * 1024 * 1024},
- {
- .name = "SPIA flash partition 2",
- .offset = 2 * 1024 * 1024,
- .size = 6 * 1024 * 1024}
-};
-
-#define NUM_PARTITIONS 2
-
-/*
- * hardware specific access to control-lines
- *
- * ctrl:
- * NAND_CNE: bit 0 -> bit 2
- * NAND_CLE: bit 1 -> bit 0
- * NAND_ALE: bit 2 -> bit 1
- */
-static void spia_hwcontrol(struct mtd_info *mtd, int cmd)
-{
- struct nand_chip *chip = mtd->priv;
-
- if (ctrl & NAND_CTRL_CHANGE) {
- void __iomem *addr = spia_io_base + spia_pedr;
- unsigned char bits;
-
- bits = (ctrl & NAND_CNE) << 2;
- bits |= (ctrl & NAND_CLE | NAND_ALE) >> 1;
- writeb((readb(addr) & ~0x7) | bits, addr);
- }
-
- if (cmd != NAND_CMD_NONE)
- writeb(cmd, chip->IO_ADDR_W);
-}
-
-/*
- * Main initialization routine
- */
-static int __init spia_init(void)
-{
- struct nand_chip *this;
-
- /* Allocate memory for MTD device structure and private data */
- spia_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
- if (!spia_mtd) {
- printk("Unable to allocate SPIA NAND MTD device structure.\n");
- return -ENOMEM;
- }
-
- /* Get pointer to private data */
- this = (struct nand_chip *)(&spia_mtd[1]);
-
- /* Initialize structures */
- memset(spia_mtd, 0, sizeof(struct mtd_info));
- memset(this, 0, sizeof(struct nand_chip));
-
- /* Link the private data with the MTD structure */
- spia_mtd->priv = this;
- spia_mtd->owner = THIS_MODULE;
-
- /*
- * Set GPIO Port E control register so that the pins are configured
- * to be outputs for controlling the NAND flash.
- */
- (*(volatile unsigned char *)(spia_io_base + spia_peddr)) = 0x07;
-
- /* Set address of NAND IO lines */
- this->IO_ADDR_R = (void __iomem *)spia_fio_base;
- this->IO_ADDR_W = (void __iomem *)spia_fio_base;
- /* Set address of hardware control function */
- this->cmd_ctrl = spia_hwcontrol;
- /* 15 us command delay time */
- this->chip_delay = 15;
-
- /* Scan to find existence of the device */
- if (nand_scan(spia_mtd, 1)) {
- kfree(spia_mtd);
- return -ENXIO;
- }
-
- /* Register the partitions */
- mtd_device_register(spia_mtd, partition_info, NUM_PARTITIONS);
-
- /* Return happy */
- return 0;
-}
-
-module_init(spia_init);
-
-/*
- * Clean up routine
- */
-static void __exit spia_cleanup(void)
-{
- /* Release resources, unregister device */
- nand_release(spia_mtd);
-
- /* Free the MTD device structure */
- kfree(spia_mtd);
-}
-
-module_exit(spia_cleanup);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com");
-MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on SPIA board");