summaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@cruncher.tec.linutronix.de>2006-05-23 23:25:53 +0200
committerThomas Gleixner <tglx@cruncher.tec.linutronix.de>2006-05-23 23:25:53 +0200
commit7abd3ef9875eb2afcdcd4f450680298a2983a55e (patch)
tree64c19d2e5ecca182938acfcb8a172efb7d907d85 /drivers/mtd
parent3821720d51b5f304d2c33021a82c8da70f6d6ac9 (diff)
[MTD] Refactor NAND hwcontrol to cmd_ctrl
The hwcontrol function enforced a step by step state machine for any kind of hardware chip access. Let the hardware driver know which control bits are set and inform it about a change of the control lines. Let the hardware driver write out the command and address bytes directly. This gives a peformance advantage for address bus controlled chips and simplifies the quirks in the hardware drivers. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/ams-delta.c56
-rw-r--r--drivers/mtd/nand/au1550nd.c25
-rw-r--r--drivers/mtd/nand/autcpu12.c77
-rw-r--r--drivers/mtd/nand/cs553x_nand.c32
-rw-r--r--drivers/mtd/nand/diskonchip.c77
-rw-r--r--drivers/mtd/nand/edb7312.c42
-rw-r--r--drivers/mtd/nand/h1910.c40
-rw-r--r--drivers/mtd/nand/nand_base.c115
-rw-r--r--drivers/mtd/nand/nandsim.c76
-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
17 files changed, 413 insertions, 527 deletions
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
index aeaf2dece095..c0e96860686e 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);
@@ -183,7 +183,7 @@ static int __init ams_delta_init(void)
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 +200,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..275453ea7a71 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -269,6 +269,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 +361,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.
*/
@@ -372,10 +384,10 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
this->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) {
@@ -400,7 +412,7 @@ 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));
@@ -410,7 +422,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
this->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 +455,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 +583,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;
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..cd3d7eb132f9 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,7 +217,7 @@ 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;
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index f77298f3af60..e4bb6b429f87 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,37 @@ 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 (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)
+ this->write_byte(mtd, cmd);
}
static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
@@ -1510,7 +1491,7 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd)
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->ecc.hwctl = doc2001plus_enable_hwecc;
@@ -1670,7 +1651,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 aa2e14538bf4..f6997fb77b91 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -276,10 +276,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:
@@ -548,13 +548,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.
*/
@@ -572,33 +571,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);
+ this->cmd_ctrl(mtd, command, ctrl);
- /* 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);
-
- /* 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
@@ -611,15 +609,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;
@@ -648,12 +647,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;
@@ -663,34 +663,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
@@ -722,20 +721,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:
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 22af9b29d2bf..ecf727b32dec 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_hw