summaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/Kconfig4
-rw-r--r--drivers/mtd/nand/ams-delta.c57
-rw-r--r--drivers/mtd/nand/au1550nd.c56
-rw-r--r--drivers/mtd/nand/autcpu12.c77
-rw-r--r--drivers/mtd/nand/cs553x_nand.c33
-rw-r--r--drivers/mtd/nand/diskonchip.c86
-rw-r--r--drivers/mtd/nand/edb7312.c42
-rw-r--r--drivers/mtd/nand/h1910.c40
-rw-r--r--drivers/mtd/nand/nand_base.c480
-rw-r--r--drivers/mtd/nand/nand_bbt.c104
-rw-r--r--drivers/mtd/nand/nandsim.c89
-rw-r--r--drivers/mtd/nand/ndfc.c23
-rw-r--r--drivers/mtd/nand/ppchameleonevb.c102
-rw-r--r--drivers/mtd/nand/rtc_from4.c34
-rw-r--r--drivers/mtd/nand/s3c2410.c64
-rw-r--r--drivers/mtd/nand/sharpsl.c41
-rw-r--r--drivers/mtd/nand/spia.c27
-rw-r--r--drivers/mtd/nand/toto.c65
-rw-r--r--drivers/mtd/nand/ts7250.c44
19 files changed, 557 insertions, 911 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index c2cb87fc4cb8..f24408d92688 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -65,7 +65,7 @@ config MTD_NAND_AMS_DELTA
config MTD_NAND_TOTO
tristate "NAND Flash device on TOTO board"
- depends on ARCH_OMAP && MTD_NAND
+ depends on ARCH_OMAP && MTD_NAND && BROKEN
help
Support for NAND flash on Texas Instruments Toto platform.
@@ -96,7 +96,7 @@ config MTD_NAND_RTC_FROM4
config MTD_NAND_PPCHAMELEONEVB
tristate "NAND Flash device on PPChameleonEVB board"
- depends on PPCHAMELEONEVB && MTD_NAND
+ depends on PPCHAMELEONEVB && MTD_NAND && BROKEN
help
This enables the NAND flash driver on the PPChameleon EVB Board.
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
index aeaf2dece095..d7897dc6b3c8 100644
--- a/drivers/mtd/nand/ams-delta.c
+++ b/drivers/mtd/nand/ams-delta.c
@@ -34,13 +34,6 @@ static struct mtd_info *ams_delta_mtd = NULL;
#define NAND_MASK (AMS_DELTA_LATCH2_NAND_NRE | AMS_DELTA_LATCH2_NAND_NWE | AMS_DELTA_LATCH2_NAND_CLE | AMS_DELTA_LATCH2_NAND_ALE | AMS_DELTA_LATCH2_NAND_NCE | AMS_DELTA_LATCH2_NAND_NWP)
-#define T_NAND_CTL_CLRALE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_ALE, 0)
-#define T_NAND_CTL_SETALE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_ALE, AMS_DELTA_LATCH2_NAND_ALE)
-#define T_NAND_CTL_CLRCLE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE, 0)
-#define T_NAND_CTL_SETCLE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE, AMS_DELTA_LATCH2_NAND_CLE)
-#define T_NAND_CTL_SETNCE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NCE, 0)
-#define T_NAND_CTL_CLRNCE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NCE, AMS_DELTA_LATCH2_NAND_NCE)
-
/*
* Define partitions for flash devices
*/
@@ -66,25 +59,6 @@ static struct mtd_partition partition_info[] = {
.size = 3 * SZ_256K },
};
-/*
- * hardware specific access to control-lines
-*/
-
-static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd)
-{
- switch (cmd) {
-
- case NAND_CTL_SETCLE: T_NAND_CTL_SETCLE(cmd); break;
- case NAND_CTL_CLRCLE: T_NAND_CTL_CLRCLE(cmd); break;
-
- case NAND_CTL_SETALE: T_NAND_CTL_SETALE(cmd); break;
- case NAND_CTL_CLRALE: T_NAND_CTL_CLRALE(cmd); break;
-
- case NAND_CTL_SETNCE: T_NAND_CTL_SETNCE(cmd); break;
- case NAND_CTL_CLRNCE: T_NAND_CTL_CLRNCE(cmd); break;
- }
-}
-
static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
{
struct nand_chip *this = mtd->priv;
@@ -141,6 +115,32 @@ static int ams_delta_verify_buf(struct mtd_info *mtd, const u_char *buf,
return 0;
}
+/*
+ * Command control function
+ *
+ * ctrl:
+ * NAND_NCE: bit 0 -> bit 2
+ * NAND_CLE: bit 1 -> bit 7
+ * NAND_ALE: bit 2 -> bit 6
+ */
+static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd,
+ unsigned int ctrl)
+{
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ unsigned long bits;
+
+ bits = (~ctrl & NAND_NCE) << 2;
+ bits |= (ctrl & NAND_CLE) << 7;
+ bits |= (ctrl & NAND_ALE) << 6;
+
+ ams_delta_latch2_write(0xC2, bits);
+ }
+
+ if (cmd != NAND_CMD_NONE)
+ ams_delta_write_byte(mtd, cmd);
+}
+
static int ams_delta_nand_ready(struct mtd_info *mtd)
{
return omap_get_gpio_datain(AMS_DELTA_GPIO_PIN_NAND_RB);
@@ -179,11 +179,10 @@ static int __init ams_delta_init(void)
this->IO_ADDR_R = (OMAP_MPUIO_BASE + OMAP_MPUIO_INPUT_LATCH);
this->IO_ADDR_W = (OMAP_MPUIO_BASE + OMAP_MPUIO_OUTPUT);
this->read_byte = ams_delta_read_byte;
- this->write_byte = ams_delta_write_byte;
this->write_buf = ams_delta_write_buf;
this->read_buf = ams_delta_read_buf;
this->verify_buf = ams_delta_verify_buf;
- this->hwcontrol = ams_delta_hwcontrol;
+ this->cmd_ctrl = ams_delta_hwcontrol;
if (!omap_request_gpio(AMS_DELTA_GPIO_PIN_NAND_RB)) {
this->dev_ready = ams_delta_nand_ready;
} else {
@@ -200,7 +199,7 @@ static int __init ams_delta_init(void)
AMS_DELTA_LATCH2_NAND_NCE |
AMS_DELTA_LATCH2_NAND_NWP);
- /* Scan to find existance of the device */
+ /* Scan to find existance of the device */
if (nand_scan(ams_delta_mtd, 1)) {
err = -ENXIO;
goto out_mtd;
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index 29dde7dcafa1..31228334da12 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -40,6 +40,7 @@
static struct mtd_info *au1550_mtd = NULL;
static void __iomem *p_nand;
static int nand_width = 1; /* default x8 */
+static void (*au1550_write_byte)(struct mtd_info *, u_char);
/*
* Define partitions for flash device
@@ -129,21 +130,6 @@ static u16 au_read_word(struct mtd_info *mtd)
}
/**
- * au_write_word - write one word to the chip
- * @mtd: MTD device structure
- * @word: data word to write
- *
- * write function for 16bit buswith without
- * endianess conversion
- */
-static void au_write_word(struct mtd_info *mtd, u16 word)
-{
- struct nand_chip *this = mtd->priv;
- writew(word, this->IO_ADDR_W);
- au_sync();
-}
-
-/**
* au_write_buf - write buffer to chip
* @mtd: MTD device structure
* @buf: data buffer
@@ -269,6 +255,18 @@ static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
return 0;
}
+/* Select the chip by setting nCE to low */
+#define NAND_CTL_SETNCE 1
+/* Deselect the chip by setting nCE to high */
+#define NAND_CTL_CLRNCE 2
+/* Select the command latch by setting CLE to high */
+#define NAND_CTL_SETCLE 3
+/* Deselect the command latch by setting CLE to low */
+#define NAND_CTL_CLRCLE 4
+/* Select the address latch by setting ALE to high */
+#define NAND_CTL_SETALE 5
+/* Deselect the address latch by setting ALE to low */
+#define NAND_CTL_CLRALE 6
static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
{
@@ -349,7 +347,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
ulong flags;
/* Begin command latch cycle */
- this->hwcontrol(mtd, NAND_CTL_SETCLE);
+ au1550_hwcontrol(mtd, NAND_CTL_SETCLE);
/*
* Write out the command to the device.
*/
@@ -367,25 +365,25 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
column -= 256;
readcmd = NAND_CMD_READ1;
}
- this->write_byte(mtd, readcmd);
+ au1550_write_byte(mtd, readcmd);
}
- this->write_byte(mtd, command);
+ au1550_write_byte(mtd, command);
/* Set ALE and clear CLE to start address cycle */
- this->hwcontrol(mtd, NAND_CTL_CLRCLE);
+ au1550_hwcontrol(mtd, NAND_CTL_CLRCLE);
if (column != -1 || page_addr != -1) {
- this->hwcontrol(mtd, NAND_CTL_SETALE);
+ au1550_hwcontrol(mtd, NAND_CTL_SETALE);
/* Serially input address */
if (column != -1) {
/* Adjust columns for 16 bit buswidth */
if (this->options & NAND_BUSWIDTH_16)
column >>= 1;
- this->write_byte(mtd, column);
+ au1550_write_byte(mtd, column);
}
if (page_addr != -1) {
- this->write_byte(mtd, (u8)(page_addr & 0xff));
+ au1550_write_byte(mtd, (u8)(page_addr & 0xff));
if (command == NAND_CMD_READ0 ||
command == NAND_CMD_READ1 ||
@@ -400,17 +398,17 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
*/
ce_override = 1;
local_irq_save(flags);
- this->hwcontrol(mtd, NAND_CTL_SETNCE);
+ au1550_hwcontrol(mtd, NAND_CTL_SETNCE);
}
- this->write_byte(mtd, (u8)(page_addr >> 8));
+ au1550_write_byte(mtd, (u8)(page_addr >> 8));
/* One more address cycle for devices > 32MiB */
if (this->chipsize > (32 << 20))
- this->write_byte(mtd, (u8)((page_addr >> 16) & 0x0f));
+ au1550_write_byte(mtd, (u8)((page_addr >> 16) & 0x0f));
}
/* Latch in address */
- this->hwcontrol(mtd, NAND_CTL_CLRALE);
+ au1550_hwcontrol(mtd, NAND_CTL_CLRALE);
}
/*
@@ -443,7 +441,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
udelay(1);
/* Release -CE and re-enable interrupts. */
- this->hwcontrol(mtd, NAND_CTL_CLRNCE);
+ au1550_hwcontrol(mtd, NAND_CTL_CLRNCE);
local_irq_restore(flags);
return;
}
@@ -571,7 +569,6 @@ static int __init au1xxx_nand_init(void)
nand_width = au_readl(MEM_STCFG3) & (1 << 22);
/* Set address of hardware control function */
- this->hwcontrol = au1550_hwcontrol;
this->dev_ready = au1550_device_ready;
this->select_chip = au1550_select_chip;
this->cmdfunc = au1550_command;
@@ -586,8 +583,7 @@ static int __init au1xxx_nand_init(void)
this->options |= NAND_BUSWIDTH_16;
this->read_byte = (!nand_width) ? au_read_byte16 : au_read_byte;
- this->write_byte = (!nand_width) ? au_write_byte16 : au_write_byte;
- this->write_word = au_write_word;
+ au1550_write_byte = (!nand_width) ? au_write_byte16 : au_write_byte;
this->read_word = au_read_word;
this->write_buf = (!nand_width) ? au_write_buf16 : au_write_buf;
this->read_buf = (!nand_width) ? au_read_buf16 : au_read_buf;
diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c
index dbb1b6267ade..fe94ae9ae1f2 100644
--- a/drivers/mtd/nand/autcpu12.c
+++ b/drivers/mtd/nand/autcpu12.c
@@ -4,7 +4,7 @@
* Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de>
*
* Derived from drivers/mtd/spia.c
- * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
+ * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
*
* $Id: autcpu12.c,v 1.23 2005/11/07 11:14:30 gleixner Exp $
*
@@ -42,11 +42,6 @@
* MTD structure for AUTCPU12 board
*/
static struct mtd_info *autcpu12_mtd = NULL;
-
-static int autcpu12_io_base = CS89712_VIRT_BASE;
-static int autcpu12_fio_pbase = AUTCPU12_PHYS_SMC;
-static int autcpu12_fio_ctrl = AUTCPU12_SMC_SELECT_OFFSET;
-static int autcpu12_pedr = AUTCPU12_SMC_PORT_OFFSET;
static void __iomem *autcpu12_fio_base;
/*
@@ -94,31 +89,42 @@ static struct mtd_partition partition_info128k[] = {
#define NUM_PARTITIONS128K 2
/*
* hardware specific access to control-lines
-*/
-
-static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd)
+ *
+ * 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)
{
- switch (cmd) {
+ struct nand_chip *chip = mtd->priv;
- case NAND_CTL_SETCLE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) |= AUTCPU12_SMC_CLE; break;
- case NAND_CTL_CLRCLE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) &= ~AUTCPU12_SMC_CLE; break;
+ if (ctrl & NAND_CTRL_CHANGE) {
+ void __iomem *addr
+ unsigned char bits;
- case NAND_CTL_SETALE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) |= AUTCPU12_SMC_ALE; break;
- case NAND_CTL_CLRALE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) &= ~AUTCPU12_SMC_ALE; break;
+ addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET;
+ bits = (ctrl & NAND_CLE) << 4;
+ bits |= (ctrl & NAND_ALE) << 2;
+ writeb((readb(addr) & ~0x30) | bits, addr);
- case NAND_CTL_SETNCE: (*(volatile unsigned char *) (autcpu12_fio_base + autcpu12_fio_ctrl)) = 0x01; break;
- case NAND_CTL_CLRNCE: (*(volatile unsigned char *) (autcpu12_fio_base + autcpu12_fio_ctrl)) = 0x00; break;
+ 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
-*/
+ * read device ready pin
+ */
int autcpu12_device_ready(struct mtd_info *mtd)
{
+ void __iomem *addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET;
- return ((*(volatile unsigned char *)(autcpu12_io_base + autcpu12_pedr)) & AUTCPU12_SMC_RDY) ? 1 : 0;
-
+ return readb(addr) & AUTCPU12_SMC_RDY;
}
/*
@@ -130,7 +136,8 @@ static int __init autcpu12_init(void)
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);
+ 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;
@@ -138,7 +145,7 @@ static int __init autcpu12_init(void)
}
/* map physical adress */
- autcpu12_fio_base = ioremap(autcpu12_fio_pbase, SZ_1K);
+ autcpu12_fio_base = ioremap(AUTCPU12_PHYS_SMC, SZ_1K);
if (!autcpu12_fio_base) {
printk("Ioremap autcpu12 SmartMedia Card failed\n");
err = -EIO;
@@ -159,7 +166,7 @@ static int __init autcpu12_init(void)
/* Set address of NAND IO lines */
this->IO_ADDR_R = autcpu12_fio_base;
this->IO_ADDR_W = autcpu12_fio_base;
- this->hwcontrol = autcpu12_hwcontrol;
+ this->cmd_ctrl = autcpu12_hwcontrol;
this->dev_ready = autcpu12_device_ready;
/* 20 us command delay time */
this->chip_delay = 20;
@@ -179,10 +186,22 @@ static int __init autcpu12_init(void)
/* Register the partitions */
switch (autcpu12_mtd->size) {
- case SZ_16M: add_mtd_partitions(autcpu12_mtd, partition_info16k, NUM_PARTITIONS16K); break;
- case SZ_32M: add_mtd_partitions(autcpu12_mtd, partition_info32k, NUM_PARTITIONS32K); break;
- case SZ_64M: add_mtd_partitions(autcpu12_mtd, partition_info64k, NUM_PARTITIONS64K); break;
- case SZ_128M: add_mtd_partitions(autcpu12_mtd, partition_info128k, NUM_PARTITIONS128K); break;
+ case SZ_16M:
+ add_mtd_partitions(autcpu12_mtd, partition_info16k,
+ NUM_PARTITIONS16K);
+ break;
+ case SZ_32M:
+ add_mtd_partitions(autcpu12_mtd, partition_info32k,
+ NUM_PARTITIONS32K);
+ break;
+ case SZ_64M:
+ add_mtd_partitions(autcpu12_mtd, partition_info64k,
+ NUM_PARTITIONS64K);
+ break;
+ case SZ_128M:
+ add_mtd_partitions(autcpu12_mtd, partition_info128k,
+ NUM_PARTITIONS128K);
+ break;
default:
printk("Unsupported SmartMedia device\n");
err = -ENXIO;
@@ -191,7 +210,7 @@ static int __init autcpu12_init(void)
goto out;
out_ior:
- iounmap((void *)autcpu12_fio_base);
+ iounmap(autcpu12_fio_base);
out_mtd:
kfree(autcpu12_mtd);
out:
@@ -209,7 +228,7 @@ static void __exit autcpu12_cleanup(void)
nand_release(autcpu12_mtd);
/* unmap physical adress */
- iounmap((void *)autcpu12_fio_base);
+ iounmap(autcpu12_fio_base);
/* Free the MTD device structure */
kfree(autcpu12_mtd);
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
index 064f3feadf53..1e0348ae325f 100644
--- a/drivers/mtd/nand/cs553x_nand.c
+++ b/drivers/mtd/nand/cs553x_nand.c
@@ -131,33 +131,17 @@ static void cs553x_write_byte(struct mtd_info *mtd, u_char byte)
writeb(byte, this->IO_ADDR_W + 0x801);
}
-static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd)
+static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd,
+ unsigned int ctrl)
{
struct nand_chip *this = mtd->priv;
void __iomem *mmio_base = this->IO_ADDR_R;
- unsigned char ctl;
-
- switch (cmd) {
- case NAND_CTL_SETCLE:
- ctl = CS_NAND_CTL_CLE;
- break;
-
- case NAND_CTL_CLRCLE:
- case NAND_CTL_CLRALE:
- case NAND_CTL_SETNCE:
- ctl = 0;
- break;
-
- case NAND_CTL_SETALE:
- ctl = CS_NAND_CTL_ALE;
- break;
-
- default:
- case NAND_CTL_CLRNCE:
- ctl = CS_NAND_CTL_CE;
- break;
+ if (ctrl & NAND_CTRL_CHANGE) {
+ unsigned char ctl = (ctrl & ~NAND_CTRL_CHANGE ) ^ 0x01;
+ writeb(ctl, mmio_base + MM_NAND_CTL);
}
- writeb(ctl, mmio_base + MM_NAND_CTL);
+ if (cmd != NAND_CMD_NONE)
+ cs553x_write_byte(mtd, cmd);
}
static int cs553x_device_ready(struct mtd_info *mtd)
@@ -233,10 +217,9 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
goto out_mtd;
}
- this->hwcontrol = cs553x_hwcontrol;
+ this->cmd_ctrl = cs553x_hwcontrol;
this->dev_ready = cs553x_device_ready;
this->read_byte = cs553x_read_byte;
- this->write_byte = cs553x_write_byte;
this->read_buf = cs553x_read_buf;
this->write_buf = cs553x_write_buf;
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index b771608ef84e..2ec9080e2b14 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -95,7 +95,8 @@ static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 };
#define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil)
#define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k)
-static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd);
+static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
+ unsigned int bitmask);
static void doc200x_select_chip(struct mtd_info *mtd, int chip);
static int debug = 0;
@@ -402,12 +403,10 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
uint16_t ret;
doc200x_select_chip(mtd, nr);
- doc200x_hwcontrol(mtd, NAND_CTL_SETCLE);
- this->write_byte(mtd, NAND_CMD_READID);
- doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE);
- doc200x_hwcontrol(mtd, NAND_CTL_SETALE);
- this->write_byte(mtd, 0);
- doc200x_hwcontrol(mtd, NAND_CTL_CLRALE);
+ doc200x_hwcontrol(mtd, NAND_CMD_READID,
+ NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+ doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
+ doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
/* We cant' use dev_ready here, but at least we wait for the
* command to complete
@@ -425,12 +424,11 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
} ident;
void __iomem *docptr = doc->virtadr;
- doc200x_hwcontrol(mtd, NAND_CTL_SETCLE);
- doc2000_write_byte(mtd, NAND_CMD_READID);
- doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE);
- doc200x_hwcontrol(mtd, NAND_CTL_SETALE);
- doc2000_write_byte(mtd, 0);
- doc200x_hwcontrol(mtd, NAND_CTL_CLRALE);
+ doc200x_hwcontrol(mtd, NAND_CMD_READID,
+ NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+ doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
+ doc200x_hwcontrol(mtd, NAND_CMD_NONE,
+ NAND_NCE | NAND_CTRL_CHANGE);
udelay(50);
@@ -690,54 +688,41 @@ static void doc200x_select_chip(struct mtd_info *mtd, int chip)
chip -= (floor * doc->chips_per_floor);
/* 11.4.4 -- deassert CE before changing chip */
- doc200x_hwcontrol(mtd, NAND_CTL_CLRNCE);
+ doc200x_hwcontrol(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
WriteDOC(floor, docptr, FloorSelect);
WriteDOC(chip, docptr, CDSNDeviceSelect);
- doc200x_hwcontrol(mtd, NAND_CTL_SETNCE);
+ doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
doc->curchip = chip;
doc->curfloor = floor;
}
-static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd)
+#define CDSN_CTRL_MSK (CDSN_CTRL_CE | CDSN_CTRL_CLE | CDSN_CTRL_ALE)
+
+static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
+ unsigned int ctrl)
{
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
void __iomem *docptr = doc->virtadr;
- switch (cmd) {
- case NAND_CTL_SETNCE:
- doc->CDSNControl |= CDSN_CTRL_CE;
- break;
- case NAND_CTL_CLRNCE:
- doc->CDSNControl &= ~CDSN_CTRL_CE;
- break;
- case NAND_CTL_SETCLE:
- doc->CDSNControl |= CDSN_CTRL_CLE;
- break;
- case NAND_CTL_CLRCLE:
- doc->CDSNControl &= ~CDSN_CTRL_CLE;
- break;
- case NAND_CTL_SETALE:
- doc->CDSNControl |= CDSN_CTRL_ALE;
- break;
- case NAND_CTL_CLRALE:
- doc->CDSNControl &= ~CDSN_CTRL_ALE;
- break;
- case NAND_CTL_SETWP:
- doc->CDSNControl |= CDSN_CTRL_WP;
- break;
- case NAND_CTL_CLRWP:
- doc->CDSNControl &= ~CDSN_CTRL_WP;
- break;
+ if (ctrl & NAND_CTRL_CHANGE) {
+ doc->CDSNControl &= ~CDSN_CTRL_MSK;
+ doc->CDSNControl |= ctrl & CDSN_CTRL_MSK;
+ if (debug)
+ printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl);
+ WriteDOC(doc->CDSNControl, docptr, CDSNControl);
+ /* 11.4.3 -- 4 NOPs after CSDNControl write */
+ DoC_Delay(doc, 4);
+ }
+ if (cmd != NAND_CMD_NONE) {
+ if (DoC_is_2000(doc))
+ doc2000_write_byte(mtd, cmd);
+ else
+ doc2001_write_byte(mtd, cmd);
}
- if (debug)
- printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl);
- WriteDOC(doc->CDSNControl, docptr, CDSNControl);
- /* 11.4.3 -- 4 NOPs after CSDNControl write */
- DoC_Delay(doc, 4);
}
static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
@@ -1454,7 +1439,6 @@ static inline int __init doc2000_init(struct mtd_info *mtd)
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
- this->write_byte = doc2000_write_byte;
this->read_byte = doc2000_read_byte;
this->write_buf = doc2000_writebuf;
this->read_buf = doc2000_readbuf;
@@ -1472,7 +1456,6 @@ static inline int __init doc2001_init(struct mtd_info *mtd)
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
- this->write_byte = doc2001_write_byte;
this->read_byte = doc2001_read_byte;
this->write_buf = doc2001_writebuf;
this->read_buf = doc2001_readbuf;
@@ -1504,16 +1487,15 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd)
struct nand_chip *this = mtd->priv;
struct doc_priv *doc = this->priv;
- this->write_byte = NULL;
this->read_byte = doc2001plus_read_byte;
this->write_buf = doc2001plus_writebuf;
this->read_buf = doc2001plus_readbuf;
this->verify_buf = doc2001plus_verifybuf;
this->scan_bbt = inftl_scan_bbt;
- this->hwcontrol = NULL;
+ this->cmd_ctrl = NULL;
this->select_chip = doc2001plus_select_chip;
this->cmdfunc = doc2001plus_command;
- this->enable_hwecc = doc2001plus_enable_hwecc;
+ this->ecc.hwctl = doc2001plus_enable_hwecc;
doc->chips_per_floor = 1;
mtd->name = "DiskOnChip Millennium Plus";
@@ -1670,7 +1652,7 @@ static int __init doc_probe(unsigned long physadr)
nand->priv = doc;
nand->select_chip = doc200x_select_chip;
- nand->hwcontrol = doc200x_hwcontrol;
+ nand->cmd_ctrl = doc200x_hwcontrol;
nand->dev_ready = doc200x_dev_ready;
nand->waitfunc = doc200x_wait;
nand->block_bad = doc200x_block_bad;
diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c
index 8e56570af91f..ba5a2174a408 100644
--- a/drivers/mtd/nand/edb7312.c
+++ b/drivers/mtd/nand/edb7312.c
@@ -73,32 +73,26 @@ static struct mtd_partition partition_info[] = {
/*
* hardware specific access to control-lines
+ *
+ * NAND_NCE: bit 0 -> bit 7
+ * NAND_CLE: bit 1 -> bit 4
+ * NAND_ALE: bit 2 -> bit 5
*/
-static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd)
+static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
- switch (cmd) {
-
- case NAND_CTL_SETCLE:
- clps_writeb(clps_readb(ep7312_pxdr) | 0x10, ep7312_pxdr);
- break;
- case NAND_CTL_CLRCLE:
- clps_writeb(clps_readb(ep7312_pxdr) & ~0x10, ep7312_pxdr);
- break;
-
- case NAND_CTL_SETALE:
- clps_writeb(clps_readb(ep7312_pxdr) | 0x20, ep7312_pxdr);
- break;
- case NAND_CTL_CLRALE:
- clps_writeb(clps_readb(ep7312_pxdr) & ~0x20, ep7312_pxdr);
- break;
-
- case NAND_CTL_SETNCE:
- clps_writeb((clps_readb(ep7312_pxdr) | 0x80) & ~0x40, ep7312_pxdr);
- break;
- case NAND_CTL_CLRNCE:
- clps_writeb((clps_readb(ep7312_pxdr) | 0x80) | 0x40, ep7312_pxdr);
- break;
+ struct nand_chip *chip = mtd->priv;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ unsigned char bits;
+
+ bits = (ctrl & (NAND_CLE | NAND_ALE)) << 3;
+ bits = (ctrl & NAND_NCE) << 7;
+
+ clps_writeb((clps_readb(ep7312_pxdr) & 0xB0) | 0x10,
+ ep7312_pxdr);
}
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, chip->IO_ADDR_W);
}
/*
@@ -159,7 +153,7 @@ static int __init ep7312_init(void)
/* insert callbacks */
this->IO_ADDR_R = ep7312_fio_base;
this->IO_ADDR_W = ep7312_fio_base;
- this->hwcontrol = ep7312_hwcontrol;
+ this->cmd_ctrl = ep7312_hwcontrol;
this->dev_ready = ep7312_device_ready;
/* 15 us command delay time */
this->chip_delay = 15;
diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c
index 06e91fa11b34..2d585d2d090c 100644
--- a/drivers/mtd/nand/h1910.c
+++ b/drivers/mtd/nand/h1910.c
@@ -56,36 +56,18 @@ static struct mtd_partition partition_info[] = {
/*
* hardware specific access to control-lines
+ *
+ * NAND_NCE: bit 0 - don't care
+ * NAND_CLE: bit 1 - address bit 2
+ * NAND_ALE: bit 2 - address bit 3
*/
-static void h1910_hwcontrol(struct mtd_info *mtd, int cmd)
+static void h1910_hwcontrol(struct mtd_info *mtd, int cmd,
+ unsigned int ctrl)
{
- struct nand_chip *this = (struct nand_chip *)(mtd->priv);
-
- switch (cmd) {
-
- case NAND_CTL_SETCLE:
- this->IO_ADDR_R |= (1 << 2);
- this->IO_ADDR_W |= (1 << 2);
- break;
- case NAND_CTL_CLRCLE:
- this->IO_ADDR_R &= ~(1 << 2);
- this->IO_ADDR_W &= ~(1 << 2);
- break;
-
- case NAND_CTL_SETALE:
- this->IO_ADDR_R |= (1 << 3);
- this->IO_ADDR_W |= (1 << 3);
- break;
- case NAND_CTL_CLRALE:
- this->IO_ADDR_R &= ~(1 << 3);
- this->IO_ADDR_W &= ~(1 << 3);
- break;
-
- case NAND_CTL_SETNCE:
- break;
- case NAND_CTL_CLRNCE:
- break;
- }
+ struct nand_chip *chip = mtd->priv;
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, chip->IO_ADDR_W | ((ctrl & 0x6) << 1));
}
/*
@@ -145,7 +127,7 @@ static int __init h1910_init(void)
/* insert callbacks */
this->IO_ADDR_R = nandaddr;
this->IO_ADDR_W = nandaddr;
- this->hwcontrol = h1910_hwcontrol;
+ this->cmd_ctrl = h1910_hwcontrol;
this->dev_ready = NULL; /* unknown whether that was correct or not so we will just do it like this */
/* 15 us command delay time */
this->chip_delay = 50;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 778535006c83..649c238837bb 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -139,23 +139,12 @@ static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len);
static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, uint8_t *buf);
-static int nand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, uint8_t *buf, uint8_t *eccbuf,
- struct nand_oobinfo *oobsel);
static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, uint8_t *buf);
static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const uint8_t *buf);
-static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const uint8_t *buf, uint8_t *eccbuf,
- struct nand_oobinfo *oobsel);
static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const uint8_t *buf);
-static int nand_writev(struct mtd_info *mtd, const struct kvec *vecs,
- unsigned long count, loff_t to, size_t *retlen);
-static int nand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
- unsigned long count, loff_t to, size_t *retlen,
- uint8_t *eccbuf, struct nand_oobinfo *oobsel);
static int nand_erase(struct mtd_info *mtd, struct erase_info *instr);
static void nand_sync(struct mtd_info *mtd);
@@ -175,6 +164,12 @@ static int nand_verify_pages(struct mtd_info *mtd, struct nand_chip *this,
static int nand_get_device(struct nand_chip *this, struct mtd_info *mtd,
int new_state);
+/*
+ * For devices which display every fart in the system on a seperate LED. Is
+ * compiled away when LED support is disabled.
+ */
+DEFINE_LED_TRIGGER(nand_led_trigger);
+
/**
* nand_release_device - [GENERIC] release chip
* @mtd: MTD device structure
@@ -209,19 +204,6 @@ static uint8_t nand_read_byte(struct mtd_info *mtd)
}
/**
- * nand_write_byte - [DEFAULT] write one byte to the chip
- * @mtd: MTD device structure
- * @byte: pointer to data byte to write
- *
- * Default write function for 8it buswith
- */
-static void nand_write_byte(struct mtd_info *mtd, uint8_t byte)
-{
- struct nand_chip *this = mtd->priv;
- writeb(byte, this->IO_ADDR_W);
-}
-
-/**
* nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip
* @mtd: MTD device structure
*
@@ -235,20 +217,6 @@ static uint8_t nand_read_byte16(struct mtd_info *mtd)
}
/**
- * nand_write_byte16 - [DEFAULT] write one byte endianess aware to the chip
- * @mtd: MTD device structure
- * @byte: pointer to data byte to write
- *
- * Default write function for 16bit buswith with
- * endianess conversion
- */
-static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte)
-{
- struct nand_chip *this = mtd->priv;
- writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
-}
-
-/**
* nand_read_word - [DEFAULT] read one word from the chip
* @mtd: MTD device structure
*
@@ -262,20 +230,6 @@ static u16 nand_read_word(struct mtd_info *mtd)
}
/**
- * nand_write_word - [DEFAULT] write one word to the chip
- * @mtd: MTD device structure
- * @word: data word to write
- *
- * Default write function for 16bit buswith without
- * endianess conversion
- */
-static void nand_write_word(struct mtd_info *mtd, u16 word)
-{
- struct nand_chip *this = mtd->priv;
- writew(word, this->IO_ADDR_W);
-}
-
-/**
* nand_select_chip - [DEFAULT] control CE line
* @mtd: MTD device structure
* @chip: chipnumber to select, -1 for deselect
@@ -287,10 +241,10 @@ static void nand_select_chip(struct mtd_info *mtd, int chip)
struct nand_chip *this = mtd->priv;
switch (chip) {
case -1:
- this->hwcontrol(mtd, NAND_CTL_CLRNCE);
+ this->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
break;
case 0:
- this->hwcontrol(mtd, NAND_CTL_SETNCE);
+ this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
break;
default:
@@ -528,8 +482,6 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
return nand_isbad_bbt(mtd, ofs, allowbbt);
}
-DEFINE_LED_TRIGGER(nand_led_trigger);
-
/*
* Wait for the ready pin, after a command
* The timeout is catched later.
@@ -559,13 +511,12 @@ static void nand_wait_ready(struct mtd_info *mtd)
* Send command to NAND device. This function is used for small page
* devices (256/512 Bytes per page)
*/
-static void nand_command(struct mtd_info *mtd, unsigned command, int column,
- int page_addr)
+static void nand_command(struct mtd_info *mtd, unsigned int command,
+ int column, int page_addr)
{
register struct nand_chip *this = mtd->priv;
+ int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
- /* Begin command latch cycle */
- this->hwcontrol(mtd, NAND_CTL_SETCLE);
/*
* Write out the command to the device.
*/
@@ -583,33 +534,32 @@ static void nand_command(struct mtd_info *mtd, unsigned command, int column,
column -= 256;
readcmd = NAND_CMD_READ1;
}
- this->write_byte(mtd, readcmd);
+ this->cmd_ctrl(mtd, readcmd, ctrl);
+ ctrl &= ~NAND_CTRL_CHANGE;
}
- this->write_byte(mtd, command);
-
- /* Set ALE and clear CLE to start address cycle */
- this->hwcontrol(mtd, NAND_CTL_CLRCLE);
-
- if (column != -1 || page_addr != -1) {
- this->hwcontrol(mtd, NAND_CTL_SETALE);
+ this->cmd_ctrl(mtd, command, ctrl);
- /* Serially input address */
- if (column != -1) {
- /* Adjust columns for 16 bit buswidth */
- if (this->options & NAND_BUSWIDTH_16)
- column >>= 1;
- this->write_byte(mtd, column);
- }
- if (page_addr != -1) {
- this->write_byte(mtd, (uint8_t)(page_addr & 0xff));
- this->write_byte(mtd, (uint8_t)((page_addr >> 8) & 0xff));
- /* One more address cycle for devices > 32MiB */
- if (this->chipsize > (32 << 20))
- this->write_byte(mtd, (uint8_t)((page_addr >> 16) & 0x0f));
- }
- /* Latch in address */
- this->hwcontrol(mtd, NAND_CTL_CLRALE);
+ /*
+ * Address cycle, when necessary
+ */
+ ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
+ /* Serially input address */
+ if (column != -1) {
+ /* Adjust columns for 16 bit buswidth */
+ if (this->options & NAND_BUSWIDTH_16)
+ column >>= 1;
+ this->cmd_ctrl(mtd, column, ctrl);
+ ctrl &= ~NAND_CTRL_CHANGE;
+ }
+ if (page_addr != -1) {
+ this->cmd_ctrl(mtd, page_addr, ctrl);
+ ctrl &= ~NAND_CTRL_CHANGE;
+ this->cmd_ctrl(mtd, page_addr >> 8, ctrl);
+ /* One more address cycle for devices > 32MiB */
+ if (this->chipsize > (32 << 20))
+ this->cmd_ctrl(mtd, page_addr >> 16, ctrl);
}
+ this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
/*
* program and erase have their own busy handlers
@@ -622,15 +572,16 @@ static void nand_command(struct mtd_info *mtd, unsigned command, int column,
case NAND_CMD_ERASE2:
case NAND_CMD_SEQIN:
case NAND_CMD_STATUS:
+ this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
return;
case NAND_CMD_RESET:
if (this->dev_ready)
break;
udelay(this->chip_delay);
- this->hwcontrol(mtd, NAND_CTL_SETCLE);
- this->write_byte(mtd, NAND_CMD_STATUS);
- this->hwcontrol(mtd, NAND_CTL_CLRCLE);
+ this->cmd_ctrl(mtd, NAND_CMD_STATUS,
+ NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+ this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ;
return;
@@ -659,12 +610,13 @@ static void nand_command(struct mtd_info *mtd, unsigned command, int column,
* @column: the column address for this command, -1 if none
* @page_addr: the page address for this command, -1 if none
*
- * Send command to NAND device. This is the version for the new large page devices
- * We dont have the separate regions as we have in the small page devices.
- * We must emulate NAND_CMD_READOOB to keep the code compatible.
+ * Send command to NAND device. This is the version for the new large page
+ * devices We dont have the separate regions as we have in the small page
+ * devices. We must emulate NAND_CMD_READOOB to keep the code compatible.
*
*/
-static void nand_command_lp(struct mtd_info *mtd, unsigned command, int column, int page_addr)
+static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
+ int column, int page_addr)
{
register struct nand_chip *this = mtd->priv;
@@ -674,34 +626,33 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned command, int column,
command = NAND_CMD_READ0;
}
- /* Begin command latch cycle */
- this->hwcontrol(mtd, NAND_CTL_SETCLE);
- /* Write out the command to the device. */
- this->write_byte(mtd, (command & 0xff));
- /* End command latch cycle */
- this->hwcontrol(mtd, NAND_CTL_CLRCLE);
+ /* Command latch cycle */
+ this->cmd_ctrl(mtd, command & 0xff,
+ NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
if (column != -1 || page_addr != -1) {
- this->hwcontrol(mtd, NAND_CTL_SETALE);
+ int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
/* Serially input address */
if (column != -1) {
/* Adjust columns for 16 bit buswidth */
if (this->options & NAND_BUSWIDTH_16)
column >>= 1;
- this->write_byte(mtd, column & 0xff);
- this->write_byte(mtd, column >> 8);
+ this->cmd_ctrl(mtd, column, ctrl);
+ ctrl &= ~NAND_CTRL_CHANGE;
+ this->cmd_ctrl(mtd, column >> 8, ctrl);
}
if (page_addr != -1) {
- this->write_byte(mtd, (uint8_t)(page_addr & 0xff));
- this->write_byte(mtd, (uint8_t)((page_addr >> 8) & 0xff));
+ this->cmd_ctrl(mtd, page_addr, ctrl);
+ this->cmd_ctrl(mtd, page_addr >> 8,
+ NAND_NCE | NAND_ALE);
/* One more address cycle for devices > 128MiB */
if (this->chipsize > (128 << 20))
- this->write_byte(mtd, (uint8_t)((page_addr >> 16) & 0xff));
+ this->cmd_ctrl(mtd, page_addr >> 16,
+ NAND_NCE | NAND_ALE);
}
- /* Latch in address */
- this->hwcontrol(mtd, NAND_CTL_CLRALE);
}
+ this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
/*
* program and erase have their own busy handlers
@@ -733,20 +684,14 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned command, int column,
if (this->dev_ready)
break;
udelay(this->chip_delay);
- this->hwcontrol(mtd, NAND_CTL_SETCLE);
- this->write_byte(mtd, NAND_CMD_STATUS);
- this->hwcontrol(mtd, NAND_CTL_CLRCLE);
+ this->cmd_ctrl(mtd, NAND_CMD_STATUS, NAND_NCE | NAND_CLE);
+ this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ;
return;
case NAND_CMD_READ0:
- /* Begin command latch cycle */
- this->hwcontrol(mtd, NAND_CTL_SETCLE);
- /* Write out the start read command */
- this->write_byte(mtd, NAND_CMD_READSTART);
- /* End command latch cycle */
- this->hwcontrol(mtd, NAND_CTL_CLRCLE);
- /* Fall through into ready check */
+ this->cmd_ctrl(mtd, NAND_CMD_READSTART, NAND_NCE | NAND_CLE);
+ this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
/* This applies to read commands */
default:
@@ -1085,27 +1030,6 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retl
}
/**
- * nand_read_ecc - [MTD Interface] MTD compability function for nand_do_read_ecc
- * @mtd: MTD device structure
- * @from: offset to read from
- * @len: number of bytes to read
- * @retlen: pointer to variable to store the number of read bytes
- * @buf: the databuffer to put data
- * @oob_buf: filesystem supplied oob data buffer
- * @oobsel: oob selection structure
- *
- * This function simply calls nand_do_read_ecc with flags = 0xff
- */
-static int nand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, uint8_t *buf, uint8_t *oob_buf, struct nand_oobinfo *oobsel)
-{
- /* use userspace supplied oobinfo, if zero */
- if (oobsel == NULL)
- oobsel = &mtd->oobinfo;
- return nand_do_read_ecc(mtd, from, len, retlen, buf, oob_buf, oobsel, 0xff);
-}
-
-/**
* nand_do_read_ecc - [MTD Interface] Read data with ECC
* @mtd: MTD device structure
* @from: offset to read from
@@ -1529,6 +1453,56 @@ int nand_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, s
}
/**
+ * nand_write_raw - [GENERIC] Write raw data including oob
+ * @mtd: MTD device structure
+ * @buf: source buffer
+ * @to: offset to write to
+ * @len: number of bytes to write
+ * @buf: source buffer
+ * @oob: oob buffer
+ *
+ * Write raw data including oob
+ */
+int nand_write_raw(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
+ uint8_t *buf, uint8_t *oob)
+{
+ struct nand_chip *this = mtd->priv;
+ int page = (int)(to >> this->page_shift);
+ int chip = (int)(to >> this->chip_shift);
+ int ret;
+
+ *retlen = 0;
+
+ /* Do not allow writes past end of device */
+ if ((to + len) > mtd->size) {
+ DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt write "
+ "beyond end of device\n");
+ return -EINVAL;
+ }
+
+ /* Grab the lock and see if the device is available */
+ nand_get_device(this, mtd, FL_WRITING);
+
+ this->select_chip(mtd, chip);
+ this->data_poi = buf;
+
+ while (len != *retlen) {
+ ret = nand_write_page(mtd, this, page, oob, &mtd->oobinfo, 0);
+ if (ret)
+ return ret;
+ page++;
+ *retlen += mtd->writesize;
+ this->data_poi += mtd->writesize;
+ oob += mtd->oobsize;
+ }
+
+ /* Deselect and wake up anyone waiting on the device */
+ nand_release_device(mtd);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nand_write_raw);
+
+/**
* nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer
* @mtd: MTD device structure
* @fsbuf: buffer given by fs driver
@@ -1590,57 +1564,39 @@ static uint8_t *nand_prepare_oobbuf(struct mtd_info *mtd, uint8_t *fsbuf, struct
#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0
/**
- * nand_write - [MTD Interface] compability function for nand_write_ecc
+ * nand_write - [MTD Interface] NAND write with ECC
* @mtd: MTD device structure
* @to: offset to write to
* @len: number of bytes to write
* @retlen: pointer to variable to store the number of written bytes
* @buf: the data to write
*
- * This function simply calls nand_write_ecc with oob buffer and oobsel = NULL
- *
-*/
-static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const uint8_t *buf)
-{
- return (nand_write_ecc(mtd, to, len, retlen, buf, NULL, NULL));
-}
-
-/**
- * nand_write_ecc - [MTD Interface] NAND write with ECC
- * @mtd: MTD device structure
- * @to: offset to write to
- * @len: number of bytes to write
- * @retlen: pointer to variable to store the number of written bytes
- * @buf: the data to write
- * @eccbuf: filesystem supplied oob data buffer
- * @oobsel: oob selection structure
- *
* NAND write with ECC
*/
-static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const uint8_t *buf, uint8_t *eccbuf,
- struct nand_oobinfo *oobsel)
+static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const uint8_t *buf)
{
int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr;
int autoplace = 0, numpages, totalpages;
struct nand_chip *this = mtd->priv;
- uint8_t *oobbuf, *bufstart;
+ uint8_t *oobbuf, *bufstart, *eccbuf = NULL;
int ppblock = (1 << (this->phys_erase_shift - this->page_shift));
+ struct nand_oobinfo *oobsel = &mtd->oobinfo;
- DEBUG(MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len);
+ DEBUG(MTD_DEBUG_LEVEL3, "nand_write: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len);
/* Initialize retlen, in case of early exit */
*retlen = 0;
/* Do not allow write past end of device */
if ((to + len) > mtd->size) {
- DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: Attempt to write past end of page\n");
+ DEBUG(MTD_DEBUG_LEVEL0, "nand_write: Attempt to write past end of page\n");
return -EINVAL;
}
/* reject writes, which are not page aligned */
if (NOTALIGNED(to) || NOTALIGNED(len)) {
- printk(KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");
+ printk(KERN_NOTICE "nand_write: Attempt to write not page aligned data\n");
return -EINVAL;
}
@@ -1656,10 +1612,6 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
if (nand_check_wp(mtd))
goto out;
- /* if oobsel is NULL, use chip defaults */
- if (oobsel == NULL)
- oobsel = &mtd->oobinfo;
-
/* Autoplace of oob data ? Use the default placement scheme */
if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
oobsel = this->autooob;
@@ -1694,7 +1646,7 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
*/
ret = nand_write_page(mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0));
if (ret) {
- DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: write_page failed %d\n", ret);
+ DEBUG(MTD_DEBUG_LEVEL0, "nand_write: write_page failed %d\n", ret);
goto out;
}
/* Next oob page */
@@ -1717,7 +1669,7 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
ret = nand_verify_pages(mtd, this, startpage, page - startpage,
oobbuf, oobsel, chipnr, (eccbuf != NULL));
if (ret) {
- DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret);
+ DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret);
goto out;
}
*retlen = written;
@@ -1746,7 +1698,7 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
if (!ret)
*retlen = written;
else
- DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret);
+ DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret);
out:
/* Deselect and wake up anyone waiting on the device */
@@ -1857,187 +1809,6 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, size_t *r
}
/**
- * nand_writev - [MTD Interface] compabilty function for nand_writev_ecc
- * @mtd: MTD device structure
- * @vecs: the iovectors to write
- * @count: number of vectors
- * @to: offset to write to
- * @retlen: pointer to variable to store the number of written bytes
- *
- * NAND write with kvec. This just calls the ecc function
- */
-static int nand_writev(struct mtd_info *mtd, const struct kvec *vecs, unsigned long count,
- loff_t to, size_t *retlen)
-{
- return (nand_writev_ecc(mtd, vecs, count, to, retlen, NULL, NULL));
-}
-
-/**
- * nand_writev_ecc - [MTD Interface] write with iovec with ecc
- * @mtd: MTD device structure
- * @vecs: the iovectors to write
- * @count: number of vectors
- * @to: offset to write to
- * @retlen: pointer to variable to store the number of written bytes
- * @eccbuf: filesystem supplied oob data buffer
- * @oobsel: oob selection structure
- *
- * NAND write with iovec with ecc
- */
-static int nand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, unsigned long count,
- loff_t to, size_t *retlen, uint8_t *eccbuf, struct nand_oobinfo *oobsel)
-{
- int i, page, len, total_len, ret = -EIO, written = 0, chipnr;
- int oob, numpages, autoplace = 0, startpage;
- struct nand_chip *this = mtd->priv;
- int ppblock = (1 << (this->phys_erase_shift - this->page_shift));
- uint8_t *oobbuf, *bufstart;
-
- /* Preset written len for early exit */
- *retlen = 0;
-
- /* Calculate total length of data */
- total_len = 0;
- for (i = 0; i < count; i++)
- total_len += (int)vecs[i].iov_len;
-
- DEBUG(MTD_DEBUG_LEVEL3, "nand_writev: to = 0x%08x, len = %i, count = %ld\n", (unsigned int)to, (unsigned int)total_len, count);
-
- /* Do not allow write past end of page */
- if ((to + total_len) > mtd->size) {
- DEBUG(MTD_DEBUG_LEVEL0, "nand_writev: Attempted write past end of device\n");
- return -EINVAL;
- }
-
- /* reject writes, which are not page aligned */
- if (NOTALIGNED(to) || NOTALIGNED(total_len)) {
- printk(KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");
- return -EINVAL;
- }
-
- /* Grab the lock and see if the device is available */
- nand_get_device(this, mtd, FL_WRITING);
-
- /* Get the current chip-nr */
- chipnr = (int)(to >> this->chip_shift);
- /* Select the NAND device */
- this->select_chip(mtd, chipnr);
-
- /* Check, if it is write protected */
- if (nand_check_wp(mtd))
- goto out;
-
- /* if oobsel is NULL, use chip defaults */
- if (oobsel == NULL)
- oobsel = &mtd->oobinfo;
-
- /* Autoplace of oob data ? Use the default placement scheme */
- if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
- oobsel = this->autooob;
- autoplace = 1;
- }
- if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
- autoplace = 1;
-
- /* Setup start page */
- page = (int)(to >> this->page_shift);
- /* Invalidate the page cache, if we write to the cached page */
- if (page <= this->pagebuf && this->pagebuf < ((to + total_len) >> this->page_shift))
- this->pagebuf = -1;
-
- startpage = page & this->pagemask;
-
- /* Loop until all kvec' data has been written */
- len = 0;
- while (count) {
- /* If the given tuple is >= pagesize then
- * write it out from the iov
- */
- if ((vecs->iov_len - len) >= mtd->writesize) {
- /* Calc number of pages we can write
- * out of this iov in one go */
- numpages = (vecs->iov_len - len) >> this->page_shift;
- /* Do not cross block boundaries */
- numpages = min(ppblock - (startpage & (ppblock - 1)), numpages);
- oobbuf = nand_prepare_oobbuf(mtd, NULL, oobsel, autoplace, numpages);
- bufstart = (uint8_t *) vecs->iov_base;
- bufstart += len;
- this->data_poi = bufstart;
- oob = 0;
- for (i = 1; i <= numpages; i++) {
- /* Write one page. If this is the last page to write
- * then use the real pageprogram command, else select
- * cached programming if supported by the chip.
- */
- ret = nand_write_page(mtd, this, page & this->pagemask,
- &oobbuf[oob], oobsel, i != numpages);
- if (ret)
- goto out;
- this->data_poi += mtd->writesize;
- len += mtd->writesize;
- oob += mtd->oobsize;
- page++;
- }
- /* Check, if we have to switch to the next tuple */
- if (len >= (int)vecs->iov_len) {
- vecs++;
- len = 0;
- count--;
- }
- } else {
- /* We must use the internal buffer, read data out of each
- * tuple until we have a full page to write
- */
- int cnt = 0;
- while (cnt < mtd->writesize) {
- if (vecs->iov_base != NULL && vecs->iov_len)
- this->data_buf[cnt++] = ((uint8_t *) vecs->iov_base)[len++];
- /* Check, if we have to switch to the next tuple */
- if (len >= (int)vecs->iov_len) {
- vecs++;
- len = 0;
- count--;
- }
- }
- this->pagebuf = page;
- this->data_poi = this->data_buf;
- bufstart = this->data_poi;
- numpages = 1;
- oobbuf = nand_prepare_oobbuf(mtd, NULL, oobsel, autoplace, numpages);
- ret = nand_write_page(mtd, this, page & this->pagemask, oobbuf, oobsel, 0);
- if (ret)
- goto out;
- page++;
- }
-
- this->data_poi = bufstart;
- ret = nand_verify_pages(mtd, this, startpage, numpages, oobbuf, oobsel, chipnr, 0);
- if (ret)
- goto out;
-
- written += mtd->writesize * numpages;
- /* All done ? */
- if (!count)
- break;
-
- startpage = page & this->pagemask;
- /* Check, if we cross a chip boundary */
- if (!startpage) {
- chipnr++;
- this->select_chip(mtd, -1);
- this->select_chip(mtd, chipnr);
- }
- }
- ret = 0;
- out:
- /* Deselect and wake up anyone waiting on the device */
- nand_release_device(mtd);
-
- *retlen = written;
- return ret;
-}
-
-/**
* single_erease_cmd - [GENERIC] NAND standard block erase command function
* @mtd: MTD device structure
* @page: the page address of the block which will be erased
@@ -2392,12 +2163,8 @@ static void nand_set_defaults(struct nand_chip *this, int busw)
if (!this->select_chip)
this->select_chip = nand_select_chip;
- if (!this->write_byte)
- this->write_byte = busw ? nand_write_byte16 : nand_write_byte;
if (!this->read_byte)
this->read_byte = busw ? nand_read_byte16 : nand_read_byte;
- if (!this->write_word)
- this->write_word = nand_write_word;
if (!this->read_word)
this->read_word = nand_read_word;
if (!this->block_bad)
@@ -2713,13 +2480,8 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
mtd->unpoint = NULL;
mtd->read = nand_read;
mtd->write = nand_write;
- mtd->read_ecc = nand_read_ecc;
- mtd->write_ecc = nand_write_ecc;
mtd->read_oob = nand_read_oob;
mtd->write_oob = nand_write_oob;
- mtd->readv = NULL;
- mtd->writev = nand_writev;
- mtd->writev_ecc = nand_writev_ecc;
mtd->sync = nand_sync;
mtd->lock = NULL;
mtd->unlock = NULL;
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index fbccb2a25186..ecaaca18d1e0 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -156,7 +156,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
while (totlen) {
len = min(totlen, (size_t) (1 << this->bbt_erase_shift));
- res = mtd->read_ecc(mtd, from, len, &retlen, buf, NULL, this->autooob);
+ res = mtd->read(mtd, from, len, &retlen, buf);
if (res < 0) {
if (retlen != len) {
printk(KERN_INFO "nand_bbt: Error reading bad block table\n");
@@ -471,17 +471,17 @@ static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt
*
*/
static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
- struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel)
+ struct nand_bbt_descr *td, struct nand_bbt_descr *md,
+ int chipsel)
{
struct nand_chip *this = mtd->priv;
- struct nand_oobinfo oobinfo;
struct erase_info einfo;
int i, j, res, chip = 0;
int bits, startblock, dir, page, offs, numblocks, sft, sftmsk;
- int nrchips, bbtoffs, pageoffs;
+ int nrchips, bbtoffs, pageoffs, ooboffs;
uint8_t msk[4];
uint8_t rcode = td->reserved_block_code;
- size_t retlen, len = 0;
+ size_t retlen, len = 0, ooblen;
loff_t to;
if (!rcode)
@@ -526,12 +526,14 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
for (i = 0; i < td->maxblocks; i++) {
int block = startblock + dir * i;
/* Check, if the block is bad */
- switch ((this->bbt[block >> 2] >> (2 * (block & 0x03))) & 0x03) {
+ switch ((this->bbt[block >> 2] >>
+ (2 * (block & 0x03))) & 0x03) {
case 0x01:
case 0x03:
continue;
}
- page = block << (this->bbt_erase_shift - this->page_shift);
+ page = block <<
+ (this->bbt_erase_shift - this->page_shift);
/* Check, if the block is used by the mirror table */
if (!md || md->pages[chip] != page)
goto write;
@@ -542,11 +544,20 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
/* Set up shift count and masks for the flash table */
bits = td->options & NAND_BBT_NRBITS_MSK;
+ msk[2] = ~rcode;
switch (bits) {
- case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x01; break;
- case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x03; break;
- case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C; msk[2] = ~rcode; msk[3] = 0x0f; break;
- case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; msk[2] = ~rcode; msk[3] = 0xff; break;
+ case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01;
+ msk[3] = 0x01;
+ break;
+ case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01;
+ msk[3] = 0x03;
+ break;
+ case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C;
+ msk[3] = 0x0f;
+ break;
+ case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F;
+ msk[3] = 0xff;
+ break;
default: return -EINVAL;
}
@@ -554,49 +565,55 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
to = ((loff_t) page) << this->page_shift;
- memcpy(&oobinfo, this->autooob, sizeof(oobinfo));
- oobinfo.useecc = MTD_NANDECC_PLACEONLY;
-
/* Must we save the block contents ? */
if (td->options & NAND_BBT_SAVECONTENT) {
/* Make it block aligned */
to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1));
len = 1 << this->bbt_erase_shift;
- res = mtd->read_ecc(mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
+ res = mtd->read(mtd, to, len, &retlen, buf);
if (res < 0) {
if (retlen != len) {
- printk(KERN_INFO
- "nand_bbt: Error reading block for writing the bad block table\n");
+ printk(KERN_INFO "nand_bbt: Error "
+ "reading block for writing "
+ "the bad block table\n");
return res;
}
- printk(KERN_WARNING "nand_bbt: ECC error while reading block for writing bad block table\n");
+ printk(KERN_WARNING "nand_bbt: ECC error "
+ "while reading block for writing "
+ "bad block table\n");
}
+ /* Read oob data */
+ ooblen = (len >> this->page_shift) * mtd->oobsize;
+ res = mtd->read_oob(mtd, to + mtd->writesize, ooblen,
+ &retlen, &buf[len]);
+ if (res < 0 || retlen != ooblen)
+ goto outerr;
+
/* Calc the byte offset in the buffer */
pageoffs = page - (int)(to >> this->page_shift);
offs = pageoffs << this->page_shift;
/* Preset the bbt area with 0xff */
memset(&buf[offs], 0xff, (size_t) (numblocks >> sft));
- /* Preset the bbt's oob area with 0xff */
- memset(&buf[len + pageoffs * mtd->oobsize], 0xff,
- ((len >> this->page_shift) - pageoffs) * mtd->oobsize);
- if (td->options & NAND_BBT_VERSION) {
- buf[len + (pageoffs * mtd->oobsize) + td->veroffs] = td->version[chip];
- }
+ ooboffs = len + (pageoffs * mtd->oobsize);
+
} else {
/* Calc length */
len = (size_t) (numblocks >> sft);
/* Make it page aligned ! */
- len = (len + (mtd->writesize - 1)) & ~(mtd->writesize - 1);
+ len = (len + (mtd->writesize - 1)) &
+ ~(mtd->writesize - 1);
/* Preset the buffer with 0xff */
- memset(buf, 0xff, len + (len >> this->page_shift) * mtd->oobsize);
+ memset(buf, 0xff, len +
+ (len >> this->page_shift)* mtd->oobsize);
offs = 0;
+ ooboffs = len;
/* Pattern is located in oob area of first page */
- memcpy(&buf[len + td->offs], td->pattern, td->len);
- if (td->options & NAND_BBT_VERSION) {
- buf[len + td->veroffs] = td->version[chip];
- }
+ memcpy(&buf[ooboffs + td->offs], td->pattern, td->len);
}
+ if (td->options & NAND_BBT_VERSION)
+ buf[ooboffs + td->veroffs] = td->version[chip];
+
/* walk through the memory table */
for (i = 0; i < numblocks;) {
uint8_t dat;
@@ -604,7 +621,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
for (j = 0; j < 4; j++, i++) {
int sftcnt = (i << (3 - sft)) & sftmsk;
/* Do not store the reserved bbt blocks ! */
- buf[offs + (i >> sft)] &= ~(msk[dat & 0x03] << sftcnt);
+ buf[offs + (i >> sft)] &=
+ ~(msk[dat & 0x03] << sftcnt);
dat >>= 2;
}
}
@@ -614,23 +632,25 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
einfo.addr = (unsigned long)to;
einfo.len = 1 << this->bbt_erase_shift;
res = nand_erase_nand(mtd, &einfo, 1);
- if (res < 0) {
- printk(KERN_WARNING "nand_bbt: Error during block erase: %d\n", res);
- return res;
- }
+ if (res < 0)
+ goto outerr;
- res = mtd->write_ecc(mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
- if (res < 0) {
- printk(KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res);
- return res;
- }
- printk(KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n",
- (unsigned int)to, td->version[chip]);
+ res = nand_write_raw(mtd, to, len, &retlen, buf, &buf[len]);
+ if (res < 0)
+ goto outerr;
+
+ printk(KERN_DEBUG "Bad block table written to 0x%08x, version "
+ "0x%02X\n", (unsigned int)to, td->version[chip]);
/* Mark it as used */
td->pages[chip] = page;
}
return 0;
+
+ outerr:
+ printk(KERN_WARNING
+ "nand_bbt: Error while writing bad block table %d\n", res);
+ return res;
}
/**
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 22af9b29d2bf..ebd64abc8be8 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -1071,68 +1071,6 @@ switch_state(struct nandsim *ns)
}
}
-static void
-ns_hwcontrol(struct mtd_info *mtd, int cmd)
-{
- struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
-
- switch (cmd) {
-
- /* set CLE line high */
- case NAND_CTL_SETCLE:
- NS_DBG("ns_hwcontrol: start command latch cycles\n");
- ns->lines.cle = 1;
- break;
-
- /* set CLE line low */
- case NAND_CTL_CLRCLE:
- NS_DBG("ns_hwcontrol: stop command latch cycles\n");
- ns->lines.cle = 0;
- break;
-
- /* set ALE line high */
- case NAND_CTL_SETALE:
- NS_DBG("ns_hwcontrol: start address latch cycles\n");
- ns->lines.ale = 1;
- break;
-
- /* set ALE line low */
- case NAND_CTL_CLRALE:
- NS_DBG("ns_hwcontrol: stop address latch cycles\n");
- ns->lines.ale = 0;
- break;
-
- /* set WP line high */
- case NAND_CTL_SETWP:
- NS_DBG("ns_hwcontrol: enable write protection\n");
- ns->lines.wp = 1;
- break;
-
- /* set WP line low */
- case NAND_CTL_CLRWP:
- NS_DBG("ns_hwcontrol: disable write protection\n");
- ns->lines.wp = 0;
- break;
-
- /* set CE line low */
- case NAND_CTL_SETNCE:
- NS_DBG("ns_hwcontrol: enable chip\n");
- ns->lines.ce = 1;
- break;
-
- /* set CE line high */
- case NAND_CTL_CLRNCE:
- NS_DBG("ns_hwcontrol: disable chip\n");
- ns->lines.ce = 0;
- break;
-
- default:
- NS_ERR("hwcontrol: unknown command\n");
- }
-
- return;
-}
-
static u_char
ns_nand_read_byte(struct mtd_info *mtd)
{
@@ -1359,6 +1297,18 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
return;
}
+static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask)
+{
+ struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
+
+ ns->lines.cle = bitmask & NAND_CLE ? 1 : 0;
+ ns->lines.ale = bitmask & NAND_ALE ? 1 : 0;
+ ns->lines.ce = bitmask & NAND_NCE ? 1 : 0;
+
+ if (cmd != NAND_CMD_NONE)
+ ns_nand_write_byte(mtd, cmd);
+}
+
static int
ns_device_ready(struct mtd_info *mtd)
{
@@ -1377,17 +1327,6 @@ ns_nand_read_word(struct mtd_info *mtd)
}
static void
-ns_nand_write_word(struct mtd_info *mtd, uint16_t word)
-{
- struct nand_chip *chip = (struct nand_chip *)mtd->priv;
-
- NS_DBG("write_word\n");
-
- chip->write_byte(mtd, word & 0xFF);
- chip->write_byte(mtd, word >> 8);
-}
-
-static void
ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
{
struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
@@ -1514,14 +1453,12 @@ static int __init ns_init_module(void)
/*
* Register simulator's callbacks.
*/
- chip->hwcontrol = ns_hwcontrol;
+ chip->cmd_ctrl = ns_hwcontrol;
chip->read_byte = ns_nand_read_byte;
chip->dev_ready = ns_device_ready;
- chip->write_byte = ns_nand_write_byte;
chip->write_buf = ns_nand_write_buf;
chip->read_buf = ns_nand_read_buf;
chip->verify_buf = ns_nand_verify_buf;
- chip->write_word = ns_nand_write_word;
chip->read_word = ns_nand_read_word;
chip->ecc.mode = NAND_ECC_SOFT;
chip->options |= NAND_SKIP_BBTSCAN;
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index e2dc81de106a..481541a683ca 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -60,22 +60,17 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip)
writel(ccr, ndfc->ndfcbase + NDFC_CCR);
}
-static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd)
+static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
- struct ndfc_controller *ndfc = &ndfc_ctrl;
struct nand_chip *chip = mtd->priv;
- switch (cmd) {
- case NAND_CTL_SETCLE:
- chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_CMD;
- break;
- case NAND_CTL_SETALE:
- chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_ALE;
- break;
- default:
- chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA;
- break;
- }
+ if (cmd == NAND_CMD_NONE)
+ return;
+
+ if (ctrl & NAND_CLE)
+ writel(cmd & 0xFF, chip->IO_ADDR_W + NDFC_CMD);
+ else
+ writel(cmd & 0xFF, chip->IO_ADDR_W + NDFC_ALE);
}
static int ndfc_ready(struct mtd_info *mtd)
@@ -158,7 +153,7 @@ static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA;
- chip->hwcontrol = ndfc_hwcontrol;
+ chip->cmd_ctrl = ndfc_hwcontrol;
chip->dev_ready = ndfc_ready;
chip->select_chip = ndfc_select_chip;
chip->chip_delay = 50;
diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c
index 9fab0998524d..22fa65c12ab9 100644
--- a/drivers/mtd/nand/ppchameleonevb.c
+++ b/drivers/mtd/nand/ppchameleonevb.c
@@ -108,54 +108,68 @@ extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partitio
/*
* hardware specific access to control-lines
*/
-static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd)
+static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd,
+ unsigned int ctrl)
{
- switch (cmd) {
-
- case NAND_CTL_SETCLE:
- MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR);
- break;
- case NAND_CTL_CLRCLE:
- MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR);
- break;
- case NAND_CTL_SETALE:
- MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR);
- break;
- case NAND_CTL_CLRALE:
- MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR);
- break;
- case NAND_CTL_SETNCE:
- MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND0_PADDR);
- break;
- case NAND_CTL_CLRNCE:
- MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND0_PADDR);
- break;
+ struct nand_chip *chip = mtd->priv;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+#error Missing headerfiles. No way to fix this. -tglx
+ switch (cmd) {
+ case NAND_CTL_SETCLE:
+ MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR);
+ break;
+ case NAND_CTL_CLRCLE:
+ MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR);
+ break;
+ case NAND_CTL_SETALE:
+ MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR);
+ break;
+ case NAND_CTL_CLRALE:
+ MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR);
+ break;
+ case NAND_CTL_SETNCE:
+ MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND0_PADDR);
+ break;
+ case NAND_CTL_CLRNCE:
+ MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND0_PADDR);
+ break;
+ }
}
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, chip->IO_ADDR_W);
}
-static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd)
+static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd,
+ unsigned int ctrl)
{
- switch (cmd) {
-
- case NAND_CTL_SETCLE:
- MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR);
- break;
- case NAND_CTL_CLRCLE:
- MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR);
- break;
- case NAND_CTL_SETALE:
- MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR);
- break;
- case NAND_CTL_CLRALE:
- MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR);
- break;
- case NAND_CTL_SETNCE:
- MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR);
- break;
- case NAND_CTL_CLRNCE:
- MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR);
- break;
+ struct nand_chip *chip = mtd->priv;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+#error Missing headerfiles. No way to fix this. -tglx
+ switch (cmd) {
+ case NAND_CTL_SETCLE:
+ MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR);
+ break;
+ case NAND_CTL_CLRCLE:
+ MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR);
+ break;
+ case NAND_CTL_SETALE:
+ MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR);
+ break;
+ case NAND_CTL_CLRALE:
+ MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR);
+ break;
+ case NAND_CTL_SETNCE:
+ MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR);
+ break;
+ case NAND_CTL_CLRNCE:
+ MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR);
+ break;
+ }
}
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, chip->IO_ADDR_W);
}
#ifdef USE_READY_BUSY_PIN
@@ -251,7 +265,7 @@ static int __init ppchameleonevb_init(void)
/* insert callbacks */
this->IO_ADDR_R = ppchameleon_fio_base;
this->IO_ADDR_W = ppchameleon_fio_base;
- this->hwcontrol = ppchameleon_hwcontrol;
+ this->cmd_ctrl = ppchameleon_hwcontrol;
#ifdef USE_READY_BUSY_PIN
this->dev_ready = ppchameleon_device_ready;
#endif
@@ -351,7 +365,7 @@ static int __init ppchameleonevb_init(void)
/* insert callbacks */
this->IO_ADDR_R = ppchameleonevb_fio_base;
this->IO_ADDR_W = ppchameleonevb_fio_base;
- this->hwcontrol = ppchameleonevb_hwcontrol;
+ this->cmd_ctrl = ppchameleonevb_hwcontrol;
#ifdef USE_READY_BUSY_PIN
this->dev_ready = ppchameleonevb_device_ready;
#endif
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
index f8e631c89a60..6c97bfaea19a 100644
--- a/drivers/mtd/nand/rtc_from4.c
+++ b/drivers/mtd/nand/rtc_from4.c
@@ -208,32 +208,18 @@ static uint8_t revbits[256] = {
* Address lines (A24-A22), so no action is required here.
*
*/
-static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd)
+static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd,
+ unsigned int ctrl)
{
- struct nand_chip *this = (struct nand_chip *)(mtd->priv);
+ struct nand_chip *chip = (mtd->priv);
- switch (cmd) {
+ if (cmd == NAND_CMD_NONE)
+ return;
- case NAND_CTL_SETCLE:
- this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_CLE);
- break;
- case NAND_CTL_CLRCLE:
- this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_CLE);
- break;
-
- case NAND_CTL_SETALE:
- this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_ALE);
- break;
- case NAND_CTL_CLRALE:
- this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_ALE);
- break;
-
- case NAND_CTL_SETNCE:
- break;
- case NAND_CTL_CLRNCE:
- break;
-
- }
+ if (ctrl & NAND_CLE)
+ writeb(cmd, chip->IO_ADDR_W | RTC_FROM4_CLE);
+ else
+ writeb(cmd, chip->IO_ADDR_W | RTC_FROM4_ALE);
}
/*
@@ -559,7 +545,7 @@ static int __init rtc_from4_init(void)
this->IO_ADDR_R = rtc_from4_fio_base;
this->IO_ADDR_W = rtc_from4_fio_base;
/* Set address of hardware control function */
- this->hwcontrol = rtc_from4_hwcontrol;
+ this->cmd_ctrl = rtc_from4_hwcontrol;
/* Set address of chip select function */
this->select_chip = rtc_from4_nand_select_chip;
/* command delay time (in us) */
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 608340a25278..215227d1a65c 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -256,60 +256,36 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
*
*/
-static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd)
+static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd,
+ unsigend int ctrl)
{
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
struct nand_chip *chip = mtd->priv;
- switch (cmd) {
- case NAND_CTL_SETNCE:
- case NAND_CTL_CLRNCE:
- printk(KERN_ERR "%s: called for NCE\n", __FUNCTION__);
- break;
-
- case NAND_CTL_SETCLE:
- chip->IO_ADDR_W = info->regs + S3C2410_NFCMD;
- break;
-
- case NAND_CTL_SETALE:
- chip->IO_ADDR_W = info->regs + S3C2410_NFADDR;
- break;
-
- /* NAND_CTL_CLRCLE: */
- /* NAND_CTL_CLRALE: */
- default:
- chip->IO_ADDR_W = info->regs + S3C2410_NFDATA;
- break;
- }
+ if (cmd == NAND_CMD_NONE)
+ return;
+
+ if (cmd & NAND_CLE)
+ writeb(cmd, info->regs + S3C2410_NFCMD);
+ else
+ writeb(cmd, info->regs + S3C2410_NFADDR);
}
/* command and control functions */
-static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd)
+static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd,
+ unsigend int ctrl)
{
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
struct nand_chip *chip = mtd->priv;
- switch (cmd) {
- case NAND_CTL_SETNCE:
- case NAND_CTL_CLRNCE:
- printk(KERN_ERR "%s: called for NCE\n", __FUNCTION__);
- break;
-
- case NAND_CTL_SETCLE:
- chip->IO_ADDR_W = info->regs + S3C2440_NFCMD;
- break;
-
- case NAND_CTL_SETALE:
- chip->IO_ADDR_W = info->regs + S3C2440_NFADDR;
- break;
-
- /* NAND_CTL_CLRCLE: */
- /* NAND_CTL_CLRALE: */
- default:
- chip->IO_ADDR_W = info->regs + S3C2440_NFDATA;
- break;
- }
+ if (cmd == NAND_CMD_NONE)
+ return;
+
+ if (cmd & NAND_CLE)
+ writeb(cmd, info->regs + S3C2440_NFCMD);
+ else
+ writeb(cmd, info->regs + S3C2440_NFADDR);
}
/* s3c2410_nand_devready()
@@ -498,7 +474,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
chip->IO_ADDR_R = info->regs + S3C2410_NFDATA;
chip->IO_ADDR_W = info->regs + S3C2410_NFDATA;
- chip->hwcontrol = s3c2410_nand_hwcontrol;
+ chip->cmd_ctrl = s3c2410_nand_hwcontrol;
chip->dev_ready = s3c2410_nand_devready;
chip->write_buf = s3c2410_nand_write_buf;
chip->read_buf = s3c2410_nand_read_buf;
@@ -511,7 +487,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
if (info->is_s3c2440) {
chip->IO_ADDR_R = info->regs + S3C2440_NFDATA;
chip->IO_ADDR_W = info->regs + S3C2440_NFDATA;
- chip->hwcontrol = s3c2440_nand_hwcontrol;
+ chip->cmd_ctrl = s3c2440_nand_hwcontrol;
}
nmtd->info = info;
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index 5554d0b97c8c..45a1da724bff 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -77,31 +77,26 @@ static struct mtd_partition sharpsl_nand_default_partition_info[] = {
/*
* hardware specific access to control-lines
+ * ctrl:
+ * NAND_CNE: bit 0 -> bit 0 & 4
+ * NAND_CLE: bit 1 -> bit 1
+ * NAND_ALE: bit 2 -> bit 2
+ *
*/
-static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd)
+static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd,
+ unsigned int ctrl)
{
- switch (cmd) {
- case NAND_CTL_SETCLE:
- writeb(readb(FLASHCTL) | FLCLE, FLASHCTL);
- break;
- case NAND_CTL_CLRCLE:
- writeb(readb(FLASHCTL) & ~FLCLE, FLASHCTL);
- break;
-
- case NAND_CTL_SETALE:
- writeb(readb(FLASHCTL) | FLALE, FLASHCTL);
- break;
- case NAND_CTL_CLRALE:
- writeb(readb(FLASHCTL) & ~FLALE, FLASHCTL);
- break;
-
- case NAND_CTL_SETNCE:
- writeb(readb(FLASHCTL) & ~(FLCE0 | FLCE1), FLASHCTL);
- break;
- case NAND_CTL_CLRNCE:
- writeb(readb(FLASHCTL) | (FLCE0 | FLCE1), FLASHCTL);
- break;
+ struct nand_chip *chip = mtd->priv;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ unsigned char bits = ctrl & 0x07;
+
+ bits |= (ctrl & 0x01) << 4;
+ writeb((readb(FLASHCTL) & 0x17) | bits, FLASHCTL);
}
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, chip->IO_ADDR_W);
}
static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
@@ -196,7 +191,7 @@ static int __init sharpsl_nand_init(void)
this->IO_ADDR_R = FLASHIO;
this->IO_ADDR_W = FLASHIO;
/* Set address of hardware control function */
- this->hwcontrol = sharpsl_nand_hwcontrol;
+ this->cmd_ctrl = sharpsl_nand_hwcontrol;
this->dev_ready = sharpsl_nand_dev_ready;
/* 15 us command delay time */
this->chip_delay = 15;
diff --git a/drivers/mtd/nand/spia.c b/drivers/mtd/nand/spia.c
index 9737f1d67c3c..1f6d429b1583 100644
--- a/drivers/mtd/nand/spia.c
+++ b/drivers/mtd/nand/spia.c
@@ -82,20 +82,27 @@ static const struct mtd_partition partition_info[] = {
/*
* 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)
{
- switch (cmd) {
+ struct nand_chip *chip = mtd->priv;
- case NAND_CTL_SETCLE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |= 0x01; break;
- case NAND_CTL_CLRCLE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x01; break;
+ if (ctrl & NAND_CTRL_CHANGE) {
+ void __iomem *addr = spia_io_base + spia_pedr;
+ unsigned char bits;
- case NAND_CTL_SETALE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |= 0x02; break;
- case NAND_CTL_CLRALE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x02; break;
-
- case NAND_CTL_SETNCE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x04; break;
- case NAND_CTL_CLRNCE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |= 0x04; break;
+ 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);
}
/*
@@ -133,7 +140,7 @@ static int __init spia_init(void)
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->hwcontrol = spia_hwcontrol;
+ this->cmd_ctrl = spia_hwcontrol;
/* 15 us command delay time */
this->chip_delay = 15;
diff --git a/drivers/mtd/nand/toto.c b/drivers/mtd/nand/toto.c
index 50aa6a46911f..a9cf0190c27a 100644
--- a/drivers/mtd/nand/toto.c
+++ b/drivers/mtd/nand/toto.c
@@ -32,6 +32,8 @@
#include <asm/arch-omap1510/hardware.h>
#include <asm/arch/gpio.h>
+#define CONFIG_NAND_WORKAROUND 1
+
/*
* MTD structure for TOTO board
*/
@@ -39,25 +41,6 @@ static struct mtd_info *toto_mtd = NULL;
static unsigned long toto_io_base = OMAP_FLASH_1_BASE;
-#define CONFIG_NAND_WORKAROUND 1
-
-#define NAND_NCE 0x4000
-#define NAND_CLE 0x1000
-#define NAND_ALE 0x0002
-#define NAND_MASK (NAND_CLE | NAND_ALE | NAND_NCE)
-
-#define T_NAND_CTL_CLRALE(iob) gpiosetout(NAND_ALE, 0)
-#define T_NAND_CTL_SETALE(iob) gpiosetout(NAND_ALE, NAND_ALE)
-#ifdef CONFIG_NAND_WORKAROUND /* "some" dev boards busted, blue wired to rts2 :( */
-#define T_NAND_CTL_CLRCLE(iob) gpiosetout(NAND_CLE, 0); rts2setout(2, 2)
-#define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE); rts2setout(2, 0)
-#else
-#define T_NAND_CTL_CLRCLE(iob) gpiosetout(NAND_CLE, 0)
-#define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE)
-#endif
-#define T_NAND_CTL_SETNCE(iob) gpiosetout(NAND_NCE, 0)
-#define T_NAND_CTL_CLRNCE(iob) gpiosetout(NAND_NCE, NAND_NCE)
-
/*
* Define partitions for flash devices
*/
@@ -91,25 +74,43 @@ static struct mtd_partition partition_info32M[] = {
#define NUM_PARTITIONS32M 3
#define NUM_PARTITIONS64M 4
+
/*
* hardware specific access to control-lines
-*/
-
-static void toto_hwcontrol(struct mtd_info *mtd, int cmd)
+ *
+ * ctrl:
+ * NAND_NCE: bit 0 -> bit 14 (0x4000)
+ * NAND_CLE: bit 1 -> bit 12 (0x1000)
+ * NAND_ALE: bit 2 -> bit 1 (0x0002)
+ */
+static void toto_hwcontrol(struct mtd_info *mtd, int cmd,
+ unsigned int ctrl)
{
+ struct nand_chip *chip = mtd->priv;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ unsigned long bits;
- udelay(1); /* hopefully enough time for tc make proceding write to clear */
- switch (cmd) {
- case NAND_CTL_SETCLE: T_NAND_CTL_SETCLE(cmd); break;
- case NAND_CTL_CLRCLE: T_NAND_CTL_CLRCLE(cmd); break;
+ /* hopefully enough time for tc make proceding write to clear */
+ udelay(1);
- case NAND_CTL_SETALE: T_NAND_CTL_SETALE(cmd); break;
- case NAND_CTL_CLRALE: T_NAND_CTL_CLRALE(cmd); break;
+ bits = (~ctrl & NAND_NCE) << 14;
+ bits |= (ctrl & NAND_CLE) << 12;
+ bits |= (ctrl & NAND_ALE) >> 1;
- case NAND_CTL_SETNCE: T_NAND_CTL_SETNCE(cmd); break;
- case NAND_CTL_CLRNCE: T_NAND_CTL_CLRNCE(cmd); break;
+#warning Wild guess as gpiosetout() is nowhere defined in the kernel source - tglx
+ gpiosetout(0x5002, bits);
+
+#ifdef CONFIG_NAND_WORKAROUND
+ /* "some" dev boards busted, blue wired to rts2 :( */
+ rts2setout(2, (ctrl & NAND_CLE) << 1);
+#endif
+ /* allow time to ensure gpio state to over take memory write */
+ udelay(1);
}
- udelay(1); /* allow time to ensure gpio state to over take memory write */
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, chip->IO_ADDR_W);
}
/*
@@ -142,7 +143,7 @@ static int __init toto_init(void)
/* Set address of NAND IO lines */
this->IO_ADDR_R = toto_io_base;
this->IO_ADDR_W = toto_io_base;
- this->hwcontrol = toto_hwcontrol;
+ this->cmd_ctrl = toto_hwcontrol;
this->dev_ready = NULL;
/* 25 us command delay time */
this->chip_delay = 30;
diff --git a/drivers/mtd/nand/ts7250.c b/drivers/mtd/nand/ts7250.c
index 70bce1b0326c..a0b4b1edcb0d 100644
--- a/drivers/mtd/nand/ts7250.c
+++ b/drivers/mtd/nand/ts7250.c
@@ -83,31 +83,29 @@ static struct mtd_partition partition_info128[] = {
/*
* hardware specific access to control-lines
+ *
+ * ctrl:
+ * NAND_NCE: bit 0 -> bit 2
+ * NAND_CLE: bit 1 -> bit 1
+ * NAND_ALE: bit 2 -> bit 0
*/
-static void ts7250_hwcontrol(struct mtd_info *mtd, int cmd)
+static void ts7250_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
- unsigned long ctrl = TS72XX_NAND_CONTROL_VIRT_BASE;
-
- switch (cmd) {
- case NAND_CTL_SETCLE:
- __raw_writeb(__raw_readb(ctrl) | 0x2, ctrl);
- break;
- case NAND_CTL_CLRCLE:
- __raw_writeb(__raw_readb(ctrl) & ~0x2, ctrl);
- break;
- case NAND_CTL_SETALE:
- __raw_writeb(__raw_readb(ctrl) | 0x1, ctrl);
- break;
- case NAND_CTL_CLRALE:
- __raw_writeb(__raw_readb(ctrl) & ~0x1, ctrl);
- break;
- case NAND_CTL_SETNCE:
- __raw_writeb(__raw_readb(ctrl) | 0x4, ctrl);
- break;
- case NAND_CTL_CLRNCE:
- __raw_writeb(__raw_readb(ctrl) & ~0x4, ctrl);
- break;
+ struct nand_chip *chip = mtd->priv;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ unsigned long addr = TS72XX_NAND_CONTROL_VIRT_BASE;
+ unsigned char bits;
+
+ bits = (ctrl & NAND_CNE) << 2;
+ bits |= ctrl & NAND_CLE;
+ bits |= (ctrl & NAND_ALE) >> 2;
+
+ __raw_writeb((__raw_readb(addr) & ~0x7) | bits, addr);
}
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, chip->IO_ADDR_W);
}
/*
@@ -152,7 +150,7 @@ static int __init ts7250_init(void)
/* insert callbacks */
this->IO_ADDR_R = (void *)TS72XX_NAND_DATA_VIRT_BASE;
this->IO_ADDR_W = (void *)TS72XX_NAND_DATA_VIRT_BASE;
- this->hwcontrol = ts7250_hwcontrol;
+ this->cmd_ctrl = ts7250_hwcontrol;
this->dev_ready = ts7250_device_ready;
this->chip_delay = 15;
this->ecc.mode = NAND_ECC_SOFT;
OpenPOWER on IntegriCloud