aboutsummaryrefslogtreecommitdiff
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/Kconfig20
-rw-r--r--drivers/mtd/nand/Makefile1
-rw-r--r--drivers/mtd/nand/ams-delta.c6
-rw-r--r--drivers/mtd/nand/atmel_nand.c4
-rw-r--r--drivers/mtd/nand/autcpu12.c4
-rw-r--r--drivers/mtd/nand/bf5xx_nand.c93
-rw-r--r--drivers/mtd/nand/cmx270_nand.c4
-rw-r--r--drivers/mtd/nand/diskonchip.c30
-rw-r--r--drivers/mtd/nand/edb7312.c2
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c2
-rw-r--r--drivers/mtd/nand/h1910.c6
-rw-r--r--drivers/mtd/nand/nandsim.c66
-rw-r--r--drivers/mtd/nand/orion_nand.c4
-rw-r--r--drivers/mtd/nand/pxa3xx_nand.c4
-rw-r--r--drivers/mtd/nand/sharpsl.c2
-rw-r--r--drivers/mtd/nand/tmio_nand.c556
-rw-r--r--drivers/mtd/nand/ts7250.c2
17 files changed, 729 insertions, 77 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 71406e51785..41f361c49b3 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -104,11 +104,24 @@ config MTD_NAND_BF5XX
config MTD_NAND_BF5XX_HWECC
bool "BF5XX NAND Hardware ECC"
+ default y
depends on MTD_NAND_BF5XX
help
Enable the use of the BF5XX's internal ECC generator when
using NAND.
+config MTD_NAND_BF5XX_BOOTROM_ECC
+ bool "Use Blackfin BootROM ECC Layout"
+ default n
+ depends on MTD_NAND_BF5XX_HWECC
+ help
+ If you wish to modify NAND pages and allow the Blackfin on-chip
+ BootROM to boot from them, say Y here. This is only necessary
+ if you are booting U-Boot out of NAND and you wish to update
+ U-Boot from Linux' userspace. Otherwise, you should say N here.
+
+ If unsure, say N.
+
config MTD_NAND_RTC_FROM4
tristate "Renesas Flash ROM 4-slot interface board (FROM_BOARD4)"
depends on SH_SOLUTION_ENGINE
@@ -338,6 +351,13 @@ config MTD_NAND_PASEMI
Enables support for NAND Flash interface on PA Semi PWRficient
based boards
+config MTD_NAND_TMIO
+ tristate "NAND Flash device on Toshiba Mobile IO Controller"
+ depends on MTD_NAND && MFD_TMIO
+ help
+ Support for NAND flash connected to a Toshiba Mobile IO
+ Controller in some PDAs, including the Sharp SL6000x.
+
config MTD_NAND_NANDSIM
tristate "Support for NAND Flash Simulator"
depends on MTD_PARTITIONS
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index d772581de57..b786c5da82d 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_MTD_NAND_ATMEL) += atmel_nand.o
obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o
obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o
obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o
+obj-$(CONFIG_MTD_NAND_TMIO) += tmio_nand.o
obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o
obj-$(CONFIG_MTD_ALAUDA) += alauda.o
obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
index a0ba07c36ee..26d42987971 100644
--- a/drivers/mtd/nand/ams-delta.c
+++ b/drivers/mtd/nand/ams-delta.c
@@ -22,10 +22,10 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
-#include <asm/arch/hardware.h>
+#include <mach/hardware.h>
#include <asm/sizes.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/board-ams-delta.h>
+#include <mach/gpio.h>
+#include <mach/board-ams-delta.h>
/*
* MTD structure for E3 (Delta)
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 99aec46e214..3387e0d5076 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -32,8 +32,8 @@
#include <linux/gpio.h>
#include <linux/io.h>
-#include <asm/arch/board.h>
-#include <asm/arch/cpu.h>
+#include <mach/board.h>
+#include <mach/cpu.h>
#ifdef CONFIG_MTD_NAND_ATMEL_ECC_HW
#define hard_ecc 1
diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c
index 553dd7e9b41..7c95da1f612 100644
--- a/drivers/mtd/nand/autcpu12.c
+++ b/drivers/mtd/nand/autcpu12.c
@@ -32,9 +32,9 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
-#include <asm/arch/hardware.h>
+#include <mach/hardware.h>
#include <asm/sizes.h>
-#include <asm/arch/autcpu12.h>
+#include <mach/autcpu12.h>
/*
* MTD structure for AUTCPU12 board
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
index e87a5729732..9af2a2cc115 100644
--- a/drivers/mtd/nand/bf5xx_nand.c
+++ b/drivers/mtd/nand/bf5xx_nand.c
@@ -91,6 +91,41 @@ static const unsigned short bfin_nfc_pin_req[] =
P_NAND_ALE,
0};
+#ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC
+static uint8_t bbt_pattern[] = { 0xff };
+
+static struct nand_bbt_descr bootrom_bbt = {
+ .options = 0,
+ .offs = 63,
+ .len = 1,
+ .pattern = bbt_pattern,
+};
+
+static struct nand_ecclayout bootrom_ecclayout = {
+ .eccbytes = 24,
+ .eccpos = {
+ 0x8 * 0, 0x8 * 0 + 1, 0x8 * 0 + 2,
+ 0x8 * 1, 0x8 * 1 + 1, 0x8 * 1 + 2,
+ 0x8 * 2, 0x8 * 2 + 1, 0x8 * 2 + 2,
+ 0x8 * 3, 0x8 * 3 + 1, 0x8 * 3 + 2,
+ 0x8 * 4, 0x8 * 4 + 1, 0x8 * 4 + 2,
+ 0x8 * 5, 0x8 * 5 + 1, 0x8 * 5 + 2,
+ 0x8 * 6, 0x8 * 6 + 1, 0x8 * 6 + 2,
+ 0x8 * 7, 0x8 * 7 + 1, 0x8 * 7 + 2
+ },
+ .oobfree = {
+ { 0x8 * 0 + 3, 5 },
+ { 0x8 * 1 + 3, 5 },
+ { 0x8 * 2 + 3, 5 },
+ { 0x8 * 3 + 3, 5 },
+ { 0x8 * 4 + 3, 5 },
+ { 0x8 * 5 + 3, 5 },
+ { 0x8 * 6 + 3, 5 },
+ { 0x8 * 7 + 3, 5 },
+ }
+};
+#endif
+
/*
* Data structures for bf5xx nand flash controller driver
*/
@@ -273,7 +308,7 @@ static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat,
dat += 256;
read_ecc += 8;
calc_ecc += 8;
- ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
+ ret |= bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
}
return ret;
@@ -298,7 +333,7 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd,
ecc0 = bfin_read_NFC_ECC0();
ecc1 = bfin_read_NFC_ECC1();
- code[0] = (ecc0 & 0x3FF) | ((ecc1 & 0x3FF) << 11);
+ code[0] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11);
dev_dbg(info->device, "returning ecc 0x%08x\n", code[0]);
@@ -310,7 +345,7 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd,
if (page_size == 512) {
ecc0 = bfin_read_NFC_ECC2();
ecc1 = bfin_read_NFC_ECC3();
- code[1] = (ecc0 & 0x3FF) | ((ecc1 & 0x3FF) << 11);
+ code[1] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11);
/* second 3 bytes in ecc_code for second 256
* bytes of 512 page size
@@ -514,7 +549,6 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd,
/*
* System initialization functions
*/
-
static int bf5xx_nand_dma_init(struct bf5xx_nand_info *info)
{
int ret;
@@ -547,6 +581,13 @@ static int bf5xx_nand_dma_init(struct bf5xx_nand_info *info)
return 0;
}
+static void bf5xx_nand_dma_remove(struct bf5xx_nand_info *info)
+{
+ /* Free NFC DMA channel */
+ if (hardware_ecc)
+ free_dma(CH_NFC);
+}
+
/*
* BF5XX NFC hardware initialization
* - pin mux setup
@@ -605,7 +646,7 @@ static int bf5xx_nand_add_partition(struct bf5xx_nand_info *info)
#endif
}
-static int bf5xx_nand_remove(struct platform_device *pdev)
+static int __devexit bf5xx_nand_remove(struct platform_device *pdev)
{
struct bf5xx_nand_info *info = to_nand_info(pdev);
struct mtd_info *mtd = NULL;
@@ -623,6 +664,7 @@ static int bf5xx_nand_remove(struct platform_device *pdev)
}
peripheral_free_list(bfin_nfc_pin_req);
+ bf5xx_nand_dma_remove(info);
/* free the common resources */
kfree(info);
@@ -638,7 +680,7 @@ static int bf5xx_nand_remove(struct platform_device *pdev)
* it can allocate all necessary resources then calls the
* nand layer to look for devices
*/
-static int bf5xx_nand_probe(struct platform_device *pdev)
+static int __devinit bf5xx_nand_probe(struct platform_device *pdev)
{
struct bf5xx_nand_platform *plat = to_nand_plat(pdev);
struct bf5xx_nand_info *info = NULL;
@@ -648,22 +690,21 @@ static int bf5xx_nand_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "(%p)\n", pdev);
- if (peripheral_request_list(bfin_nfc_pin_req, DRV_NAME)) {
- printk(KERN_ERR DRV_NAME
- ": Requesting Peripherals failed\n");
- return -EFAULT;
- }
-
if (!plat) {
dev_err(&pdev->dev, "no platform specific information\n");
- goto exit_error;
+ return -EINVAL;
+ }
+
+ if (peripheral_request_list(bfin_nfc_pin_req, DRV_NAME)) {
+ dev_err(&pdev->dev, "requesting Peripherals failed\n");
+ return -EFAULT;
}
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (info == NULL) {
dev_err(&pdev->dev, "no memory for flash info\n");
err = -ENOMEM;
- goto exit_error;
+ goto out_err_kzalloc;
}
platform_set_drvdata(pdev, info);
@@ -707,11 +748,16 @@ static int bf5xx_nand_probe(struct platform_device *pdev)
/* initialise the hardware */
err = bf5xx_nand_hw_init(info);
- if (err != 0)
- goto exit_error;
+ if (err)
+ goto out_err_hw_init;
/* setup hardware ECC data struct */
if (hardware_ecc) {
+#ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC
+ chip->badblock_pattern = &bootrom_bbt;
+ chip->ecc.layout = &bootrom_ecclayout;
+#endif
+
if (plat->page_size == NFC_PG_SIZE_256) {
chip->ecc.bytes = 3;
chip->ecc.size = 256;
@@ -733,7 +779,7 @@ static int bf5xx_nand_probe(struct platform_device *pdev)
/* scan hardware nand chip and setup mtd info data struct */
if (nand_scan(mtd, 1)) {
err = -ENXIO;
- goto exit_error;
+ goto out_err_nand_scan;
}
/* add NAND partition */
@@ -742,11 +788,14 @@ static int bf5xx_nand_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "initialised ok\n");
return 0;
-exit_error:
- bf5xx_nand_remove(pdev);
+out_err_nand_scan:
+ bf5xx_nand_dma_remove(info);
+out_err_hw_init:
+ platform_set_drvdata(pdev, NULL);
+ kfree(info);
+out_err_kzalloc:
+ peripheral_free_list(bfin_nfc_pin_req);
- if (err == 0)
- err = -EINVAL;
return err;
}
@@ -775,7 +824,7 @@ static int bf5xx_nand_resume(struct platform_device *dev)
/* driver device registration */
static struct platform_driver bf5xx_nand_driver = {
.probe = bf5xx_nand_probe,
- .remove = bf5xx_nand_remove,
+ .remove = __devexit_p(bf5xx_nand_remove),
.suspend = bf5xx_nand_suspend,
.resume = bf5xx_nand_resume,
.driver = {
diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c
index fc8529bedfd..9eba3f04783 100644
--- a/drivers/mtd/nand/cmx270_nand.c
+++ b/drivers/mtd/nand/cmx270_nand.c
@@ -26,8 +26,8 @@
#include <asm/irq.h>
#include <asm/mach-types.h>
-#include <asm/arch/hardware.h>
-#include <asm/arch/pxa-regs.h>
+#include <mach/hardware.h>
+#include <mach/pxa-regs.h>
#define GPIO_NAND_CS (11)
#define GPIO_NAND_RB (89)
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 765d4f0f7c8..e4226e02d63 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -1125,9 +1125,9 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio
goto out;
mh = (struct NFTLMediaHeader *)buf;
- mh->NumEraseUnits = le16_to_cpu(mh->NumEraseUnits);
- mh->FirstPhysicalEUN = le16_to_cpu(mh->FirstPhysicalEUN);
- mh->FormattedSize = le32_to_cpu(mh->FormattedSize);
+ le16_to_cpus(&mh->NumEraseUnits);
+ le16_to_cpus(&mh->FirstPhysicalEUN);
+ le32_to_cpus(&mh->FormattedSize);
printk(KERN_INFO " DataOrgID = %s\n"
" NumEraseUnits = %d\n"
@@ -1235,12 +1235,12 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partiti
doc->mh1_page = doc->mh0_page + (4096 >> this->page_shift);
mh = (struct INFTLMediaHeader *)buf;
- mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks);
- mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions);
- mh->NoOfBDTLPartitions = le32_to_cpu(mh->NoOfBDTLPartitions);
- mh->BlockMultiplierBits = le32_to_cpu(mh->BlockMultiplierBits);
- mh->FormatFlags = le32_to_cpu(mh->FormatFlags);
- mh->PercentUsed = le32_to_cpu(mh->PercentUsed);
+ le32_to_cpus(&mh->NoOfBootImageBlocks);
+ le32_to_cpus(&mh->NoOfBinaryPartitions);
+ le32_to_cpus(&mh->NoOfBDTLPartitions);
+ le32_to_cpus(&mh->BlockMultiplierBits);
+ le32_to_cpus(&mh->FormatFlags);
+ le32_to_cpus(&mh->PercentUsed);
printk(KERN_INFO " bootRecordID = %s\n"
" NoOfBootImageBlocks = %d\n"
@@ -1277,12 +1277,12 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partiti
/* Scan the partitions */
for (i = 0; (i < 4); i++) {
ip = &(mh->Partitions[i]);
- ip->virtualUnits = le32_to_cpu(ip->virtualUnits);
- ip->firstUnit = le32_to_cpu(ip->firstUnit);
- ip->lastUnit = le32_to_cpu(ip->lastUnit);
- ip->flags = le32_to_cpu(ip->flags);
- ip->spareUnits = le32_to_cpu(ip->spareUnits);
- ip->Reserved0 = le32_to_cpu(ip->Reserved0);
+ le32_to_cpus(&ip->virtualUnits);
+ le32_to_cpus(&ip->firstUnit);
+ le32_to_cpus(&ip->lastUnit);
+ le32_to_cpus(&ip->flags);
+ le32_to_cpus(&ip->spareUnits);
+ le32_to_cpus(&ip->Reserved0);
printk(KERN_INFO " PARTITION[%d] ->\n"
" virtualUnits = %d\n"
diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c
index 387e4352903..86366bfba9f 100644
--- a/drivers/mtd/nand/edb7312.c
+++ b/drivers/mtd/nand/edb7312.c
@@ -23,7 +23,7 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
-#include <asm/arch/hardware.h> /* for CLPS7111_VIRT_BASE */
+#include <mach/hardware.h> /* for CLPS7111_VIRT_BASE */
#include <asm/sizes.h>
#include <asm/hardware/clps7111.h>
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 9dff51351f4..98ad3cefcaf 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -887,7 +887,7 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
goto err;
}
- priv->mtd.name = kasprintf(GFP_KERNEL, "%x.flash", res.start);
+ priv->mtd.name = kasprintf(GFP_KERNEL, "%x.flash", (unsigned)res.start);
if (!priv->mtd.name) {
ret = -ENOMEM;
goto err;
diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c
index 9e59de501c2..f8ce79b446e 100644
--- a/drivers/mtd/nand/h1910.c
+++ b/drivers/mtd/nand/h1910.c
@@ -24,10 +24,10 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
-#include <asm/arch/hardware.h> /* for CLPS7111_VIRT_BASE */
+#include <mach/hardware.h> /* for CLPS7111_VIRT_BASE */
#include <asm/sizes.h>
-#include <asm/arch/h1900-gpio.h>
-#include <asm/arch/ipaq.h>
+#include <mach/h1900-gpio.h>
+#include <mach/ipaq.h>
/*
* MTD structure for EDB7312 board
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index ecd70e2504f..556e8131ecd 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -28,6 +28,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/vmalloc.h>
+#include <asm/div64.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/string.h>
@@ -207,13 +208,16 @@ MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the I
#define STATE_CMD_READID 0x0000000A /* read ID */
#define STATE_CMD_ERASE2 0x0000000B /* sector erase second command */
#define STATE_CMD_RESET 0x0000000C /* reset */
+#define STATE_CMD_RNDOUT 0x0000000D /* random output command */
+#define STATE_CMD_RNDOUTSTART 0x0000000E /* random output start command */
#define STATE_CMD_MASK 0x0000000F /* command states mask */
/* After an address is input, the simulator goes to one of these states */
#define STATE_ADDR_PAGE 0x00000010 /* full (row, column) address is accepted */
#define STATE_ADDR_SEC 0x00000020 /* sector address was accepted */
-#define STATE_ADDR_ZERO 0x00000030 /* one byte zero address was accepted */
-#define STATE_ADDR_MASK 0x00000030 /* address states mask */
+#define STATE_ADDR_COLUMN 0x00000030 /* column address was accepted */
+#define STATE_ADDR_ZERO 0x00000040 /* one byte zero address was accepted */
+#define STATE_ADDR_MASK 0x00000070 /* address states mask */
/* Durind data input/output the simulator is in these states */
#define STATE_DATAIN 0x00000100 /* waiting for data input */
@@ -240,7 +244,7 @@ MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the I
#define ACTION_OOBOFF 0x00600000 /* add to address OOB offset */
#define ACTION_MASK 0x00700000 /* action mask */
-#define NS_OPER_NUM 12 /* Number of operations supported by the simulator */
+#define NS_OPER_NUM 13 /* Number of operations supported by the simulator */
#define NS_OPER_STATES 6 /* Maximum number of states in operation */
#define OPT_ANY 0xFFFFFFFF /* any chip supports this operation */
@@ -373,7 +377,10 @@ static struct nandsim_operations {
{OPT_ANY, {STATE_CMD_READID, STATE_ADDR_ZERO, STATE_DATAOUT_ID, STATE_READY}},
/* Large page devices read page */
{OPT_LARGEPAGE, {STATE_CMD_READ0, STATE_ADDR_PAGE, STATE_CMD_READSTART | ACTION_CPY,
- STATE_DATAOUT, STATE_READY}}
+ STATE_DATAOUT, STATE_READY}},
+ /* Large page devices random page read */
+ {OPT_LARGEPAGE, {STATE_CMD_RNDOUT, STATE_ADDR_COLUMN, STATE_CMD_RNDOUTSTART | ACTION_CPY,
+ STATE_DATAOUT, STATE_READY}},
};
struct weak_block {
@@ -579,7 +586,8 @@ static int init_nandsim(struct mtd_info *mtd)
if (ns->busw == 16)
NS_WARN("16-bit flashes support wasn't tested\n");
- printk("flash size: %llu MiB\n", ns->geom.totsz >> 20);
+ printk("flash size: %llu MiB\n",
+ (unsigned long long)ns->geom.totsz >> 20);
printk("page size: %u bytes\n", ns->geom.pgsz);
printk("OOB area size: %u bytes\n", ns->geom.oobsz);
printk("sector size: %u KiB\n", ns->geom.secsz >> 10);
@@ -588,8 +596,9 @@ static int init_nandsim(struct mtd_info *mtd)
printk("bus width: %u\n", ns->busw);
printk("bits in sector size: %u\n", ns->geom.secshift);
printk("bits in page size: %u\n", ns->geom.pgshift);
- printk("bits in OOB size: %u\n", ns->geom.oobshift);
- printk("flash size with OOB: %llu KiB\n", ns->geom.totszoob >> 10);
+ printk("bits in OOB size: %u\n", ns->geom.oobshift);
+ printk("flash size with OOB: %llu KiB\n",
+ (unsigned long long)ns->geom.totszoob >> 10);
printk("page address bytes: %u\n", ns->geom.pgaddrbytes);
printk("sector address bytes: %u\n", ns->geom.secaddrbytes);
printk("options: %#x\n", ns->options);
@@ -937,12 +946,18 @@ static char *get_state_name(uint32_t state)
return "STATE_CMD_ERASE2";
case STATE_CMD_RESET:
return "STATE_CMD_RESET";
+ case STATE_CMD_RNDOUT:
+ return "STATE_CMD_RNDOUT";
+ case STATE_CMD_RNDOUTSTART:
+ return "STATE_CMD_RNDOUTSTART";
case STATE_ADDR_PAGE:
return "STATE_ADDR_PAGE";
case STATE_ADDR_SEC:
return "STATE_ADDR_SEC";
case STATE_ADDR_ZERO:
return "STATE_ADDR_ZERO";
+ case STATE_ADDR_COLUMN:
+ return "STATE_ADDR_COLUMN";
case STATE_DATAIN:
return "STATE_DATAIN";
case STATE_DATAOUT:
@@ -973,6 +988,7 @@ static int check_command(int cmd)
switch (cmd) {
case NAND_CMD_READ0:
+ case NAND_CMD_READ1:
case NAND_CMD_READSTART:
case NAND_CMD_PAGEPROG:
case NAND_CMD_READOOB:
@@ -982,7 +998,8 @@ static int check_command(int cmd)
case NAND_CMD_READID:
case NAND_CMD_ERASE2:
case NAND_CMD_RESET:
- case NAND_CMD_READ1:
+ case NAND_CMD_RNDOUT:
+ case NAND_CMD_RNDOUTSTART:
return 0;
case NAND_CMD_STATUS_MULTI:
@@ -1021,6 +1038,10 @@ static uint32_t get_state_by_command(unsigned command)
return STATE_CMD_ERASE2;
case NAND_CMD_RESET:
return STATE_CMD_RESET;
+ case NAND_CMD_RNDOUT:
+ return STATE_CMD_RNDOUT;
+ case NAND_CMD_RNDOUTSTART:
+ return STATE_CMD_RNDOUTSTART;
}
NS_ERR("get_state_by_command: unknown command, BUG\n");
@@ -1582,6 +1603,11 @@ static void switch_state(struct nandsim *ns)
ns->regs.num = 1;
break;
+ case STATE_ADDR_COLUMN:
+ /* Column address is always 2 bytes */
+ ns->regs.num = ns->geom.pgaddrbytes - ns->geom.secaddrbytes;
+ break;
+
default:
NS_ERR("switch_state: BUG! unknown address state\n");
}
@@ -1693,15 +1719,21 @@ static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
return;
}
- /*
- * Chip might still be in STATE_DATAOUT
- * (if OPT_AUTOINCR feature is supported), STATE_DATAOUT_STATUS or
- * STATE_DATAOUT_STATUS_M state. If so, switch state.
- */
+ /* Check that the command byte is correct */
+ if (check_command(byte)) {
+ NS_ERR("write_byte: unknown command %#x\n", (uint)byte);
+ return;
+ }
+
if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS
|| NS_STATE(ns->state) == STATE_DATAOUT_STATUS_M
- || ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT))
+ || NS_STATE(ns->state) == STATE_DATAOUT) {
+ int row = ns->regs.row;
+
switch_state(ns);
+ if (byte == NAND_CMD_RNDOUT)
+ ns->regs.row = row;
+ }
/* Check if chip is expecting command */
if (NS_STATE(ns->nxstate) != STATE_UNKNOWN && !(ns->nxstate & STATE_CMD_MASK)) {
@@ -1715,12 +1747,6 @@ static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
}
- /* Check that the command byte is correct */
- if (check_command(byte)) {
- NS_ERR("write_byte: unknown command %#x\n", (uint)byte);
- return;
- }
-
NS_DBG("command byte corresponding to %s state accepted\n",
get_state_name(get_state_by_command(byte)));
ns->regs.command = byte;
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
index ee2ac3948cd..917cf8d3ae9 100644
--- a/drivers/mtd/nand/orion_nand.c
+++ b/drivers/mtd/nand/orion_nand.c
@@ -18,8 +18,8 @@
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/sizes.h>
-#include <asm/arch/hardware.h>
-#include <asm/plat-orion/orion_nand.h>
+#include <mach/hardware.h>
+#include <plat/orion_nand.h>
#ifdef CONFIG_MTD_CMDLINE_PARTS
static const char *part_probes[] = { "cmdlinepart", NULL };
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index fe2bc7e4211..a64ad15b8fd 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -22,8 +22,8 @@
#include <linux/irq.h>
#include <asm/dma.h>
-#include <asm/arch/pxa-regs.h>
-#include <asm/arch/pxa3xx_nand.h>
+#include <mach/pxa-regs.h>
+#include <mach/pxa3xx_nand.h>
#define CHIP_DELAY_TIMEOUT (2 * HZ/10)
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index 6dba2fb66ae..30a518e211b 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -21,7 +21,7 @@
#include <linux/mtd/partitions.h>
#include <linux/interrupt.h>
#include <asm/io.h>
-#include <asm/hardware.h>
+#include <mach/hardware.h>
#include <asm/mach-types.h>
static void __iomem *sharpsl_io_base;
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c
new file mode 100644
index 00000000000..cbab654b03c
--- /dev/null
+++ b/drivers/mtd/nand/tmio_nand.c
@@ -0,0 +1,556 @@
+/*
+ * Toshiba TMIO NAND flash controller driver
+ *
+ * Slightly murky pre-git history of the driver:
+ *
+ * Copyright (c) Ian Molton 2004, 2005, 2008
+ * Original work, independant of sharps code. Included hardware ECC support.
+ * Hard ECC did not work for writes in the early revisions.
+ * Copyright (c) Dirk Opfer 2005.
+ * Modifications developed from sharps code but
+ * NOT containing any, ported onto Ians base.
+ * Copyright (c) Chris Humbert 2005
+ * Copyright (c) Dmitry Baryshkov 2008
+ * Minor fixes
+ *
+ * Parts copyright Sebastian Carlier
+ *
+ * This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tmio.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * NAND Flash Host Controller Configuration Register
+ */
+#define CCR_COMMAND 0x04 /* w Command */
+#define CCR_BASE 0x10 /* l NAND Flash Control Reg Base Addr */
+#define CCR_INTP 0x3d /* b Interrupt Pin */
+#define CCR_INTE 0x48 /* b Interrupt Enable */
+#define CCR_EC 0x4a /* b Event Control */
+#define CCR_ICC 0x4c /* b Internal Clock Control */
+#define CCR_ECCC 0x5b /* b ECC Control */
+#define CCR_NFTC 0x60 /* b NAND Flash Transaction Control */
+#define CCR_NFM 0x61 /* b NAND Flash Monitor */
+#define CCR_NFPSC 0x62 /* b NAND Flash Power Supply Control */
+#define CCR_NFDC 0x63 /* b NAND Flash Detect Control */
+
+/*
+ * NAND Flash Control Register
+ */
+#define FCR_DATA 0x00 /* bwl Data Register */
+#define FCR_MODE 0x04 /* b Mode Register */
+#define FCR_STATUS 0x05 /* b Status Register */
+#define FCR_ISR 0x06 /* b Interrupt Status Register */
+#define FCR_IMR 0x07 /* b Interrupt Mask Register */
+
+/* FCR_MODE Register Command List */
+#define FCR_MODE_DATA 0x94 /* Data Data_Mode */
+#define FCR_MODE_COMMAND 0x95 /* Data Command_Mode */
+#define FCR_MODE_ADDRESS 0x96 /* Data Address_Mode */
+
+#define FCR_MODE_HWECC_CALC 0xB4 /* HW-ECC Data */
+#define FCR_MODE_HWECC_RESULT 0xD4 /* HW-ECC Calc result Read_Mode */
+#define FCR_MODE_HWECC_RESET 0xF4 /* HW-ECC Reset */
+
+#define FCR_MODE_POWER_ON 0x0C /* Power Supply ON to SSFDC card */
+#define FCR_MODE_POWER_OFF 0x08 /* Power Supply OFF to SSFDC card */
+
+#define FCR_MODE_LED_OFF 0x00 /* LED OFF */
+#define FCR_MODE_LED_ON 0x04 /* LED ON */
+
+#define FCR_MODE_EJECT_ON 0x68 /* Ejection events active */
+#define FCR_MODE_EJECT_OFF 0x08 /* Ejection events ignored */
+
+#define FCR_MODE_LOCK 0x6C /* Lock_Mode. Eject Switch Invalid */
+#define FCR_MODE_UNLOCK 0x0C /* UnLock_Mode. Eject Switch is valid */
+
+#define FCR_MODE_CONTROLLER_ID 0x40 /* Controller ID Read */
+#define FCR_MODE_STANDBY 0x00 /* SSFDC card Changes Standby State */
+
+#define FCR_MODE_WE 0x80
+#define FCR_MODE_ECC1 0x40
+#define FCR_MODE_ECC0 0x20
+#define FCR_MODE_CE 0x10
+#define FCR_MODE_PCNT1 0x08
+#define FCR_MODE_PCNT0 0x04
+#define FCR_MODE_ALE 0x02
+#define FCR_MODE_CLE 0x01
+
+#define FCR_STATUS_BUSY 0x80
+
+/*--------------------------------------------------------------------------*/
+
+struct tmio_nand {
+ struct mtd_info mtd;
+ struct nand_chip chip;
+
+ struct platform_device *dev;
+
+ void __iomem *ccr;
+ void __iomem *fcr;
+ unsigned long fcr_phys;
+
+ unsigned int irq;
+
+ /* for tmio_nand_read_byte */
+ u8 read;
+ unsigned read_good:1;
+};
+
+#define mtd_to_tmio(m) container_of(m, struct tmio_nand, mtd)
+
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+static const char *part_probes[] = { "cmdlinepart", NULL };
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+static void tmio_nand_hwcontrol(struct mtd_info *mtd, int cmd,
+ unsigned int ctrl)
+{
+ struct tmio_nand *tmio = mtd_to_tmio(mtd);
+ struct nand_chip *chip = mtd->priv;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ u8 mode;
+
+ if (ctrl & NAND_NCE) {
+ mode = FCR_MODE_DATA;
+
+ if (ctrl & NAND_CLE)
+ mode |= FCR_MODE_CLE;
+ else
+ mode &= ~FCR_MODE_CLE;
+
+ if (ctrl & NAND_ALE)
+ mode |= FCR_MODE_ALE;
+ else
+ mode &= ~FCR_MODE_ALE;
+ } else {
+ mode = FCR_MODE_STANDBY;
+ }
+
+ tmio_iowrite8(mode, tmio->fcr + FCR_MODE);
+ tmio->read_good = 0;
+ }
+
+ if (cmd != NAND_CMD_NONE)
+ tmio_iowrite8(cmd, chip->IO_ADDR_W);
+}
+
+static int tmio_nand_dev_ready(struct mtd_info *mtd)
+{
+ struct tmio_nand *tmio = mtd_to_tmio(mtd);
+
+ return !(tmio_ioread8(tmio->fcr + FCR_STATUS) & FCR_STATUS_BUSY);
+}
+
+static irqreturn_t tmio_irq(int irq, void *__tmio)
+{
+ struct tmio_nand *tmio = __tmio;
+ struct nand_chip *nand_chip = &tmio->chip;
+
+ /* disable RDYREQ interrupt */
+ tmio_iowrite8(0x00, tmio->fcr + FCR_IMR);
+
+ if (unlikely(!waitqueue_active(&nand_chip->controller->wq)))
+ dev_warn(&tmio->dev->dev, "spurious interrupt\n");
+
+ wake_up(&nand_chip->controller->wq);
+ return IRQ_HANDLED;
+}
+
+/*
+ *The TMIO core has a RDYREQ interrupt on the posedge of #SMRB.
+ *This interrupt is normally disabled, but for long operations like
+ *erase and write, we enable it to wake us up. The irq handler
+ *disables the interrupt.
+ */
+static int
+tmio_nand_wait(struct mtd_info *mtd, struct nand_chip *nand_chip)
+{
+ struct tmio_nand *tmio = mtd_to_tmio(mtd);
+ long timeout;
+
+ /* enable RDYREQ interrupt */
+ tmio_iowrite8(0x0f, tmio->fcr + FCR_ISR);
+ tmio_iowrite8(0x81, tmio->fcr + FCR_IMR);
+
+ timeout = wait_event_timeout(nand_chip->controller->wq,
+ tmio_nand_dev_ready(mtd),
+ msecs_to_jiffies(nand_chip->state == FL_ERASING ? 400 : 20));
+
+ if (unlikely(!tmio_nand_dev_ready(mtd))) {
+ tmio_iowrite8(0x00, tmio->fcr + FCR_IMR);
+ dev_warn(&tmio->dev->dev, "still busy with %s after %d ms\n",
+ nand_chip->state == FL_ERASING ? "erase" : "program",
+ nand_chip->state == FL_ERASING ? 400 : 20);
+
+ } else if (unlikely(!timeout)) {
+ tmio_iowrite8(0x00, tmio->fcr + FCR_IMR);
+ dev_warn(&tmio->dev->dev, "timeout waiting for interrupt\n");
+ }
+
+ nand_chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
+ return nand_chip->read_byte(mtd);
+}
+
+/*
+ *The TMIO controller combines two 8-bit data bytes into one 16-bit
+ *word. This function separates them so nand_base.c works as expected,
+ *especially its NAND_CMD_READID routines.
+ *
+ *To prevent stale data from being read, tmio_nand_hwcontrol() clears
+ *tmio->read_good.
+ */
+static u_char tmio_nand_read_byte(struct mtd_info *mtd)
+{
+ struct tmio_nand *tmio = mtd_to_tmio(mtd);
+ unsigned int data;
+
+ if (tmio->read_good--)
+ return tmio->read;
+
+ data = tmio_ioread16(tmio->fcr + FCR_DATA);
+ tmio->read = data >> 8;
+ return data;
+}
+
+/*
+ *The TMIO controller converts an 8-bit NAND interface to a 16-bit
+ *bus interface, so all data reads and writes must be 16-bit wide.
+ *Thus, we implement 16-bit versions of the read, write, and verify
+ *buffer functions.
+ */
+static void
+tmio_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+ struct tmio_nand *tmio = mtd_to_tmio(mtd);
+
+ tmio_iowrite16_rep(tmio->fcr + FCR_DATA, buf, len >> 1);
+}
+
+static void tmio_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+ struct tmio_nand *tmio = mtd_to_tmio(mtd);
+
+ tmio_ioread16_rep(tmio->fcr + FCR_DATA, buf, len >> 1);
+}
+
+static int
+tmio_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+ struct tmio_nand *tmio = mtd_to_tmio(mtd);
+ u16 *p = (u16 *) buf;
+
+ for (len >>= 1; len; len--)
+ if (*(p++) != tmio_ioread16(tmio->fcr + FCR_DATA))
+ return -EFAULT;
+ return 0;
+}
+
+static void tmio_nand_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+ struct tmio_nand *tmio = mtd_to_tmio(mtd);
+
+ tmio_iowrite8(FCR_MODE_HWECC_RESET, tmio->fcr + FCR_MODE);
+ tmio_ioread8(tmio->fcr + FCR_DATA); /* dummy read */
+ tmio_iowrite8(FCR_MODE_HWECC_CALC, tmio->fcr + FCR_MODE);
+}
+
+static int tmio_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+ u_char *ecc_code)
+{
+ struct tmio_nand *tmio = mtd_to_tmio(mtd);
+ unsigned int ecc;
+
+ tmio_iowrite8(FCR_MODE_HWECC_RESULT, tmio->fcr + FCR_MODE);
+
+ ecc = tmio_ioread16(tmio->fcr + FCR_DATA);
+ ecc_code[1] = ecc; /* 000-255 LP7-0 */
+ ecc_code[0] = ecc >> 8; /* 000-255 LP15-8 */
+ ecc = tmio_ioread16(tmio->fcr + FCR_DATA);
+ ecc_code[2] = ecc; /* 000-255 CP5-0,11b */
+ ecc_code[4] = ecc >> 8; /* 256-511 LP7-0 */
+ ecc = tmio_ioread16(tmio->fcr + FCR_DATA);
+ ecc_code[3] = ecc; /* 256-511 LP15-8 */
+ ecc_code[5] = ecc >> 8; /* 256-511 CP5-0,11b */
+
+ tmio_iowrite8(FCR_MODE_DATA, tmio->fcr + FCR_MODE);
+ return 0;
+}
+
+static int tmio_hw_init(struct platform_device *dev, struct tmio_nand *tmio)
+{
+ struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
+ int ret;
+
+ if (cell->enable) {
+ ret = cell->enable(dev);
+ if (ret)
+ return ret;
+ }
+
+ /* (4Ch) CLKRUN Enable 1st spcrunc */
+ tmio_iowrite8(0x81, tmio->ccr + CCR_ICC);
+
+ /* (10h)BaseAddress 0x1000 spba.spba2 */
+ tmio_iowrite16(tmio->fcr_phys, tmio->ccr + CCR_BASE);
+ tmio_iowrite16(tmio->fcr_phys >> 16, tmio->ccr + CCR_BASE + 16);
+
+ /* (04h)Command Register I/O spcmd */
+ tmio_iowrite8(0x02, tmio->ccr + CCR_COMMAND);
+
+ /* (62h) Power Supply Control ssmpwc */
+ /* HardPowerOFF - SuspendOFF - PowerSupplyWait_4MS */
+ tmio_iowrite8(0x02, tmio->ccr + CCR_NFPSC);
+
+ /* (63h) Detect Control ssmdtc */
+ tmio_iowrite8(0x02, tmio->ccr + CCR_NFDC);
+
+ /* Interrupt status register clear sintst */
+ tmio_iowrite8(0x0f, tmio->fcr + FCR_ISR);
+
+ /* After power supply, Media are reset smode */
+ tmio_iowrite8(FCR_MODE_POWER_ON, tmio->fcr + FCR_MODE);
+ tmio_iowrite8(FCR_MODE_COMMAND, tmio->fcr + FCR_MODE);
+ tmio_iowrite8(NAND_CMD_RESET, tmio->fcr + FCR_DATA);
+
+ /* Standby Mode smode */
+ tmio_iowrite8(FCR_MODE_STANDBY, tmio->fcr + FCR_MODE);
+
+ mdelay(5);
+
+ return 0;
+}
+
+static void tmio_hw_stop(struct platform_device *dev, struct tmio_nand *tmio)
+{
+ struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
+
+ tmio_iowrite8(FCR_MODE_POWER_OFF, tmio->fcr + FCR_MODE);
+ if (cell->disable)
+ cell->disable(dev);
+}
+
+static int tmio_probe(struct platform_device *dev)
+{
+ struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
+ struct tmio_nand_data *data = cell->driver_data;
+ struct resource *fcr = platform_get_resource(dev,
+ IORESOURCE_MEM, 0);
+ struct resource *ccr = platform_get_resource(dev,
+ IORESOURCE_MEM, 1);
+ int irq = platform_get_irq(dev, 0);
+ struct tmio_nand *tmio;
+ struct mtd_info *mtd;
+ struct nand_chip *nand_chip;
+#ifdef CONFIG_MTD_PARTITIONS
+ struct mtd_partition *parts;
+ int nbparts = 0;
+#endif
+ int retval;
+
+ if (data == NULL)
+ dev_warn(&dev->dev, "NULL platform data!\n");
+
+ tmio = kzalloc(sizeof *tmio, GFP_KERNEL);
+ if (!tmio) {
+ retval = -ENOMEM;
+ goto err_kzalloc;
+ }
+
+ tmio->dev = dev;
+
+ platform_set_drvdata(dev, tmio);
+ mtd = &tmio->mtd;
+ nand_chip = &tmio->chip;
+ mtd->priv = nand_chip;
+ mtd->name = "tmio-nand";
+
+ tmio->ccr = ioremap(ccr->start, ccr->end - ccr->start + 1);
+ if (!tmio->ccr) {
+ retval = -EIO;
+ goto err_iomap_ccr;
+ }
+
+ tmio->fcr_phys = (unsigned long)fcr->start;
+ tmio->fcr = ioremap(fcr->start, fcr->end - fcr->start + 1);
+ if (!tmio->fcr) {
+ retval = -EIO;
+ goto err_iomap_fcr;
+ }
+
+ retval = tmio_hw_init(dev, tmio);
+ if (retval)
+ goto err_hwinit;
+
+ /* Set address of NAND IO lines */
+ nand_chip->IO_ADDR_R = tmio->fcr;
+ nand_chip->IO_ADDR_W = tmio->fcr;
+
+ /* Set address of hardware control function */
+ nand_chip->cmd_ctrl = tmio_nand_hwcontrol;
+ nand_chip->dev_ready = tmio_nand_dev_ready;
+ nand_chip->read_byte = tmio_nand_read_byte;
+ nand_chip->write_buf = tmio_nand_write_buf;
+ nand_chip->read_buf = tmio_nand_read_buf;
+ nand_chip->verify_buf = tmio_nand_verify_buf;
+
+ /* set eccmode using hardware ECC */
+ nand_chip->ecc.mode = NAND_ECC_HW;
+ nand_chip->ecc.size = 512;
+ nand_chip->ecc.bytes = 6;
+ nand_chip->ecc.hwctl = tmio_nand_enable_hwecc;
+ nand_chip->ecc.calculate = tmio_nand_calculate_ecc;
+ nand_chip->ecc.correct = nand_correct_data;
+
+ if (data)
+ nand_chip->badblock_pattern = data->badblock_pattern;
+
+ /* 15 us command delay time */
+ nand_chip->chip_delay = 15;
+
+ retval = request_irq(irq, &tmio_irq,
+ IRQF_DISABLED, dev->dev.bus_id, tmio);
+ if (retval) {
+ dev_err(&dev->dev, "request_irq error %d\n", retval);
+ goto err_irq;
+ }
+
+ tmio->irq = irq;
+ nand_chip->waitfunc = tmio_nand_wait;
+
+ /* Scan to find existence of the device */
+ if (nand_scan(mtd, 1)) {
+ retval = -ENODEV;
+ goto err_scan;
+ }
+ /* Register the partitions */
+#ifdef CONFIG_MTD_PARTITIONS
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+ nbparts = parse_mtd_partitions(mtd, part_probes, &parts, 0);
+#endif
+ if (nbparts <= 0 && data) {
+ parts = data->partition;
+ nbparts = data->num_partitions;
+ }
+
+ if (nbparts)
+ retval = add_mtd_partitions(mtd, parts, nbparts);
+ else
+#endif
+ retval = add_mtd_device(mtd);
+
+ if (!retval)
+ return retval;
+
+ nand_release(mtd);
+
+err_scan:
+ if (tmio->irq)
+ free_irq(tmio->irq, tmio);
+err_irq:
+ tmio_hw_stop(dev, tmio);
+err_hwinit:
+ iounmap(tmio->fcr);
+err_iomap_fcr:
+ iounmap(tmio->ccr);
+err_iomap_ccr:
+ kfree(tmio);
+err_kzalloc:
+ return retval;
+}
+
+static int tmio_remove(struct platform_device *dev)
+{
+ struct tmio_nand *tmio = platform_get_drvdata(dev);
+
+ nand_release(&tmio->mtd);
+ if (tmio->irq)
+ free_irq(tmio->irq, tmio);
+ tmio_hw_stop(dev, tmio);
+ iounmap(tmio->fcr);
+ iounmap(tmio->ccr);
+ kfree(tmio);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int tmio_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
+
+ if (cell->suspend)
+ cell->suspend(dev);
+
+ tmio_hw_stop(dev, platform_get_drvdata(dev));
+ return 0;
+}
+
+static int tmio_resume(struct platform_device *dev)
+{
+ struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
+
+ /* FIXME - is this required or merely another attack of the broken
+ * SHARP platform? Looks suspicious.
+ */
+ tmio_hw_init(dev, platform_get_drvdata(dev));
+
+ if (cell->resume)
+ cell->resume(dev);
+
+ return 0;
+}
+#else
+#define tmio_suspend NULL
+#define tmio_resume NULL
+#endif
+
+static struct platform_driver tmio_driver = {
+ .driver.name = "tmio-nand",
+ .driver.owner = THIS_MODULE,
+ .probe = tmio_probe,
+ .remove = tmio_remove,
+ .suspend = tmio_suspend,
+ .resume = tmio_resume,
+};
+
+static int __init tmio_init(void)
+{
+ return platform_driver_register(&tmio_driver);
+}
+
+static void __exit tmio_exit(void)
+{
+ platform_driver_unregister(&tmio_driver);
+}
+
+module_init(tmio_init);
+module_exit(tmio_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Ian Molton, Dirk Opfer, Chris Humbert, Dmitry Baryshkov");
+MODULE_DESCRIPTION("NAND flash driver on Toshiba Mobile IO controller");
+MODULE_ALIAS("platform:tmio-nand");
diff --git a/drivers/mtd/nand/ts7250.c b/drivers/mtd/nand/ts7250.c
index 807a72752ee..2c410a01131 100644
--- a/drivers/mtd/nand/ts7250.c
+++ b/drivers/mtd/nand/ts7250.c
@@ -25,7 +25,7 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
-#include <asm/arch/hardware.h>
+#include <mach/hardware.h>
#include <asm/sizes.h>
#include <asm/mach-types.h>