aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@cruncher.tec.linutronix.de>2006-05-23 17:25:53 -0400
committerThomas Gleixner <tglx@cruncher.tec.linutronix.de>2006-05-23 17:25:53 -0400
commit7abd3ef9875eb2afcdcd4f450680298a2983a55e (patch)
tree64c19d2e5ecca182938acfcb8a172efb7d907d85 /drivers/mtd/nand
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/nand')
-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;
34 34
35#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) 35#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)
36 36
37#define T_NAND_CTL_CLRALE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_ALE, 0)
38#define T_NAND_CTL_SETALE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_ALE, AMS_DELTA_LATCH2_NAND_ALE)
39#define T_NAND_CTL_CLRCLE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE, 0)
40#define T_NAND_CTL_SETCLE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE, AMS_DELTA_LATCH2_NAND_CLE)
41#define T_NAND_CTL_SETNCE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NCE, 0)
42#define T_NAND_CTL_CLRNCE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NCE, AMS_DELTA_LATCH2_NAND_NCE)
43
44/* 37/*
45 * Define partitions for flash devices 38 * Define partitions for flash devices
46 */ 39 */
@@ -66,25 +59,6 @@ static struct mtd_partition partition_info[] = {
66 .size = 3 * SZ_256K }, 59 .size = 3 * SZ_256K },
67}; 60};
68 61
69/*
70 * hardware specific access to control-lines
71*/
72
73static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd)
74{
75 switch (cmd) {
76
77 case NAND_CTL_SETCLE: T_NAND_CTL_SETCLE(cmd); break;
78 case NAND_CTL_CLRCLE: T_NAND_CTL_CLRCLE(cmd); break;
79
80 case NAND_CTL_SETALE: T_NAND_CTL_SETALE(cmd); break;
81 case NAND_CTL_CLRALE: T_NAND_CTL_CLRALE(cmd); break;
82
83 case NAND_CTL_SETNCE: T_NAND_CTL_SETNCE(cmd); break;
84 case NAND_CTL_CLRNCE: T_NAND_CTL_CLRNCE(cmd); break;
85 }
86}
87
88static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte) 62static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
89{ 63{
90 struct nand_chip *this = mtd->priv; 64 struct nand_chip *this = mtd->priv;
@@ -141,6 +115,32 @@ static int ams_delta_verify_buf(struct mtd_info *mtd, const u_char *buf,
141 return 0; 115 return 0;
142} 116}
143 117
118/*
119 * Command control function
120 *
121 * ctrl:
122 * NAND_NCE: bit 0 -> bit 2
123 * NAND_CLE: bit 1 -> bit 7
124 * NAND_ALE: bit 2 -> bit 6
125 */
126static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd,
127 unsigned int ctrl)
128{
129
130 if (ctrl & NAND_CTRL_CHANGE) {
131 unsigned long bits;
132
133 bits = (~ctrl & NAND_NCE) << 2;
134 bits |= (ctrl & NAND_CLE) << 7;
135 bits |= (ctrl & NAND_ALE) << 6;
136
137 ams_delta_latch2_write(0xC2, bits);
138 }
139
140 if (cmd != NAND_CMD_NONE)
141 ams_delta_write_byte(mtd, cmd);
142}
143
144static int ams_delta_nand_ready(struct mtd_info *mtd) 144static int ams_delta_nand_ready(struct mtd_info *mtd)
145{ 145{
146 return omap_get_gpio_datain(AMS_DELTA_GPIO_PIN_NAND_RB); 146 return omap_get_gpio_datain(AMS_DELTA_GPIO_PIN_NAND_RB);
@@ -183,7 +183,7 @@ static int __init ams_delta_init(void)
183 this->write_buf = ams_delta_write_buf; 183 this->write_buf = ams_delta_write_buf;
184 this->read_buf = ams_delta_read_buf; 184 this->read_buf = ams_delta_read_buf;
185 this->verify_buf = ams_delta_verify_buf; 185 this->verify_buf = ams_delta_verify_buf;
186 this->hwcontrol = ams_delta_hwcontrol; 186 this->cmd_ctrl = ams_delta_hwcontrol;
187 if (!omap_request_gpio(AMS_DELTA_GPIO_PIN_NAND_RB)) { 187 if (!omap_request_gpio(AMS_DELTA_GPIO_PIN_NAND_RB)) {
188 this->dev_ready = ams_delta_nand_ready; 188 this->dev_ready = ams_delta_nand_ready;
189 } else { 189 } else {
@@ -200,7 +200,7 @@ static int __init ams_delta_init(void)
200 AMS_DELTA_LATCH2_NAND_NCE | 200 AMS_DELTA_LATCH2_NAND_NCE |
201 AMS_DELTA_LATCH2_NAND_NWP); 201 AMS_DELTA_LATCH2_NAND_NWP);
202 202
203 /* Scan to find existance of the device */ 203 /* Scan to find existance of the device */
204 if (nand_scan(ams_delta_mtd, 1)) { 204 if (nand_scan(ams_delta_mtd, 1)) {
205 err = -ENXIO; 205 err = -ENXIO;
206 goto out_mtd; 206 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)
269 return 0; 269 return 0;
270} 270}
271 271
272/* Select the chip by setting nCE to low */
273#define NAND_CTL_SETNCE 1
274/* Deselect the chip by setting nCE to high */
275#define NAND_CTL_CLRNCE 2
276/* Select the command latch by setting CLE to high */
277#define NAND_CTL_SETCLE 3
278/* Deselect the command latch by setting CLE to low */
279#define NAND_CTL_CLRCLE 4
280/* Select the address latch by setting ALE to high */
281#define NAND_CTL_SETALE 5
282/* Deselect the address latch by setting ALE to low */
283#define NAND_CTL_CLRALE 6
272 284
273static void au1550_hwcontrol(struct mtd_info *mtd, int cmd) 285static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
274{ 286{
@@ -349,7 +361,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
349 ulong flags; 361 ulong flags;
350 362
351 /* Begin command latch cycle */ 363 /* Begin command latch cycle */
352 this->hwcontrol(mtd, NAND_CTL_SETCLE); 364 au1550_hwcontrol(mtd, NAND_CTL_SETCLE);
353 /* 365 /*
354 * Write out the command to the device. 366 * Write out the command to the device.
355 */ 367 */
@@ -372,10 +384,10 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
372 this->write_byte(mtd, command); 384 this->write_byte(mtd, command);
373 385
374 /* Set ALE and clear CLE to start address cycle */ 386 /* Set ALE and clear CLE to start address cycle */
375 this->hwcontrol(mtd, NAND_CTL_CLRCLE); 387 au1550_hwcontrol(mtd, NAND_CTL_CLRCLE);
376 388
377 if (column != -1 || page_addr != -1) { 389 if (column != -1 || page_addr != -1) {
378 this->hwcontrol(mtd, NAND_CTL_SETALE); 390 au1550_hwcontrol(mtd, NAND_CTL_SETALE);
379 391
380 /* Serially input address */ 392 /* Serially input address */
381 if (column != -1) { 393 if (column != -1) {
@@ -400,7 +412,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
400 */ 412 */
401 ce_override = 1; 413 ce_override = 1;
402 local_irq_save(flags); 414 local_irq_save(flags);
403 this->hwcontrol(mtd, NAND_CTL_SETNCE); 415 au1550_hwcontrol(mtd, NAND_CTL_SETNCE);
404 } 416 }
405 417
406 this->write_byte(mtd, (u8)(page_addr >> 8)); 418 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
410 this->write_byte(mtd, (u8)((page_addr >> 16) & 0x0f)); 422 this->write_byte(mtd, (u8)((page_addr >> 16) & 0x0f));
411 } 423 }
412 /* Latch in address */ 424 /* Latch in address */
413 this->hwcontrol(mtd, NAND_CTL_CLRALE); 425 au1550_hwcontrol(mtd, NAND_CTL_CLRALE);
414 } 426 }
415 427
416 /* 428 /*
@@ -443,7 +455,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
443 udelay(1); 455 udelay(1);
444 456
445 /* Release -CE and re-enable interrupts. */ 457 /* Release -CE and re-enable interrupts. */
446 this->hwcontrol(mtd, NAND_CTL_CLRNCE); 458 au1550_hwcontrol(mtd, NAND_CTL_CLRNCE);
447 local_irq_restore(flags); 459 local_irq_restore(flags);
448 return; 460 return;
449 } 461 }
@@ -571,7 +583,6 @@ static int __init au1xxx_nand_init(void)
571 nand_width = au_readl(MEM_STCFG3) & (1 << 22); 583 nand_width = au_readl(MEM_STCFG3) & (1 << 22);
572 584
573 /* Set address of hardware control function */ 585 /* Set address of hardware control function */
574 this->hwcontrol = au1550_hwcontrol;
575 this->dev_ready = au1550_device_ready; 586 this->dev_ready = au1550_device_ready;
576 this->select_chip = au1550_select_chip; 587 this->select_chip = au1550_select_chip;
577 this->cmdfunc = au1550_command; 588 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 @@
4 * Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de> 4 * Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de>
5 * 5 *
6 * Derived from drivers/mtd/spia.c 6 * Derived from drivers/mtd/spia.c
7 * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) 7 * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
8 * 8 *
9 * $Id: autcpu12.c,v 1.23 2005/11/07 11:14:30 gleixner Exp $ 9 * $Id: autcpu12.c,v 1.23 2005/11/07 11:14:30 gleixner Exp $
10 * 10 *
@@ -42,11 +42,6 @@
42 * MTD structure for AUTCPU12 board 42 * MTD structure for AUTCPU12 board
43 */ 43 */
44static struct mtd_info *autcpu12_mtd = NULL; 44static struct mtd_info *autcpu12_mtd = NULL;
45
46static int autcpu12_io_base = CS89712_VIRT_BASE;
47static int autcpu12_fio_pbase = AUTCPU12_PHYS_SMC;
48static int autcpu12_fio_ctrl = AUTCPU12_SMC_SELECT_OFFSET;
49static int autcpu12_pedr = AUTCPU12_SMC_PORT_OFFSET;
50static void __iomem *autcpu12_fio_base; 45static void __iomem *autcpu12_fio_base;
51 46
52/* 47/*
@@ -94,31 +89,42 @@ static struct mtd_partition partition_info128k[] = {
94#define NUM_PARTITIONS128K 2 89#define NUM_PARTITIONS128K 2
95/* 90/*
96 * hardware specific access to control-lines 91 * hardware specific access to control-lines
97*/ 92 *
98 93 * ALE bit 4 autcpu12_pedr
99static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd) 94 * CLE bit 5 autcpu12_pedr
95 * NCE bit 0 fio_ctrl
96 *
97 */
98static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd,
99 unsigned int ctrl)
100{ 100{
101 switch (cmd) { 101 struct nand_chip *chip = mtd->priv;
102 102
103 case NAND_CTL_SETCLE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) |= AUTCPU12_SMC_CLE; break; 103 if (ctrl & NAND_CTRL_CHANGE) {
104 case NAND_CTL_CLRCLE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) &= ~AUTCPU12_SMC_CLE; break; 104 void __iomem *addr
105 unsigned char bits;
105 106
106 case NAND_CTL_SETALE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) |= AUTCPU12_SMC_ALE; break; 107 addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET;
107 case NAND_CTL_CLRALE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) &= ~AUTCPU12_SMC_ALE; break; 108 bits = (ctrl & NAND_CLE) << 4;
109 bits |= (ctrl & NAND_ALE) << 2;
110 writeb((readb(addr) & ~0x30) | bits, addr);
108 111
109 case NAND_CTL_SETNCE: (*(volatile unsigned char *) (autcpu12_fio_base + autcpu12_fio_ctrl)) = 0x01; break; 112 addr = autcpu12_fio_base + AUTCPU12_SMC_SELECT_OFFSET;
110 case NAND_CTL_CLRNCE: (*(volatile unsigned char *) (autcpu12_fio_base + autcpu12_fio_ctrl)) = 0x00; break; 113 writeb((readb(addr) & ~0x1) | (ctrl & NAND_NCE), addr);
111 } 114 }
115
116 if (cmd != NAND_CMD_NONE)
117 writeb(cmd, chip->IO_ADDR_W);
112} 118}
113 119
114/* 120/*
115* read device ready pin 121 * read device ready pin
116*/ 122 */
117int autcpu12_device_ready(struct mtd_info *mtd) 123int autcpu12_device_ready(struct mtd_info *mtd)
118{ 124{
125 void __iomem *addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET;
119 126
120 return ((*(volatile unsigned char *)(autcpu12_io_base + autcpu12_pedr)) & AUTCPU12_SMC_RDY) ? 1 : 0; 127 return readb(addr) & AUTCPU12_SMC_RDY;
121
122} 128}
123 129
124/* 130/*
@@ -130,7 +136,8 @@ static int __init autcpu12_init(void)
130 int err = 0; 136 int err = 0;
131 137
132 /* Allocate memory for MTD device structure and private data */ 138 /* Allocate memory for MTD device structure and private data */
133 autcpu12_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); 139 autcpu12_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip),
140 GFP_KERNEL);
134 if (!autcpu12_mtd) { 141 if (!autcpu12_mtd) {
135 printk("Unable to allocate AUTCPU12 NAND MTD device structure.\n"); 142 printk("Unable to allocate AUTCPU12 NAND MTD device structure.\n");
136 err = -ENOMEM; 143 err = -ENOMEM;
@@ -138,7 +145,7 @@ static int __init autcpu12_init(void)
138 } 145 }
139 146
140 /* map physical adress */ 147 /* map physical adress */
141 autcpu12_fio_base = ioremap(autcpu12_fio_pbase, SZ_1K); 148 autcpu12_fio_base = ioremap(AUTCPU12_PHYS_SMC, SZ_1K);
142 if (!autcpu12_fio_base) { 149 if (!autcpu12_fio_base) {
143 printk("Ioremap autcpu12 SmartMedia Card failed\n"); 150 printk("Ioremap autcpu12 SmartMedia Card failed\n");
144 err = -EIO; 151 err = -EIO;
@@ -159,7 +166,7 @@ static int __init autcpu12_init(void)
159 /* Set address of NAND IO lines */ 166 /* Set address of NAND IO lines */
160 this->IO_ADDR_R = autcpu12_fio_base; 167 this->IO_ADDR_R = autcpu12_fio_base;
161 this->IO_ADDR_W = autcpu12_fio_base; 168 this->IO_ADDR_W = autcpu12_fio_base;
162 this->hwcontrol = autcpu12_hwcontrol; 169 this->cmd_ctrl = autcpu12_hwcontrol;
163 this->dev_ready = autcpu12_device_ready; 170 this->dev_ready = autcpu12_device_ready;
164 /* 20 us command delay time */ 171 /* 20 us command delay time */
165 this->chip_delay = 20; 172 this->chip_delay = 20;
@@ -179,10 +186,22 @@ static int __init autcpu12_init(void)
179 186
180 /* Register the partitions */ 187 /* Register the partitions */
181 switch (autcpu12_mtd->size) { 188 switch (autcpu12_mtd->size) {
182 case SZ_16M: add_mtd_partitions(autcpu12_mtd, partition_info16k, NUM_PARTITIONS16K); break; 189 case SZ_16M:
183 case SZ_32M: add_mtd_partitions(autcpu12_mtd, partition_info32k, NUM_PARTITIONS32K); break; 190 add_mtd_partitions(autcpu12_mtd, partition_info16k,
184 case SZ_64M: add_mtd_partitions(autcpu12_mtd, partition_info64k, NUM_PARTITIONS64K); break; 191 NUM_PARTITIONS16K);
185 case SZ_128M: add_mtd_partitions(autcpu12_mtd, partition_info128k, NUM_PARTITIONS128K); break; 192 break;
193 case SZ_32M:
194 add_mtd_partitions(autcpu12_mtd, partition_info32k,
195 NUM_PARTITIONS32K);
196 break;
197 case SZ_64M:
198 add_mtd_partitions(autcpu12_mtd, partition_info64k,
199 NUM_PARTITIONS64K);
200 break;
201 case SZ_128M:
202 add_mtd_partitions(autcpu12_mtd, partition_info128k,
203 NUM_PARTITIONS128K);
204 break;
186 default: 205 default:
187 printk("Unsupported SmartMedia device\n"); 206 printk("Unsupported SmartMedia device\n");
188 err = -ENXIO; 207 err = -ENXIO;
@@ -191,7 +210,7 @@ static int __init autcpu12_init(void)
191 goto out; 210 goto out;
192 211
193 out_ior: 212 out_ior:
194 iounmap((void *)autcpu12_fio_base); 213 iounmap(autcpu12_fio_base);
195 out_mtd: 214 out_mtd:
196 kfree(autcpu12_mtd); 215 kfree(autcpu12_mtd);
197 out: 216 out:
@@ -209,7 +228,7 @@ static void __exit autcpu12_cleanup(void)
209 nand_release(autcpu12_mtd); 228 nand_release(autcpu12_mtd);
210 229
211 /* unmap physical adress */ 230 /* unmap physical adress */
212 iounmap((void *)autcpu12_fio_base); 231 iounmap(autcpu12_fio_base);
213 232
214 /* Free the MTD device structure */ 233 /* Free the MTD device structure */
215 kfree(autcpu12_mtd); 234 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)
131 writeb(byte, this->IO_ADDR_W + 0x801); 131 writeb(byte, this->IO_ADDR_W + 0x801);
132} 132}
133 133
134static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd) 134static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd,
135 unsigned int ctrl)
135{ 136{
136 struct nand_chip *this = mtd->priv; 137 struct nand_chip *this = mtd->priv;
137 void __iomem *mmio_base = this->IO_ADDR_R; 138 void __iomem *mmio_base = this->IO_ADDR_R;
138 unsigned char ctl; 139 if (ctrl & NAND_CTRL_CHANGE) {
139 140 unsigned char ctl = (ctrl & ~NAND_CTRL_CHANGE ) ^ 0x01;
140 switch (cmd) { 141 writeb(ctl, mmio_base + MM_NAND_CTL);
141 case NAND_CTL_SETCLE:
142 ctl = CS_NAND_CTL_CLE;
143 break;
144
145 case NAND_CTL_CLRCLE:
146 case NAND_CTL_CLRALE:
147 case NAND_CTL_SETNCE:
148 ctl = 0;
149 break;
150
151 case NAND_CTL_SETALE:
152 ctl = CS_NAND_CTL_ALE;
153 break;
154
155 default:
156 case NAND_CTL_CLRNCE:
157 ctl = CS_NAND_CTL_CE;
158 break;
159 } 142 }
160 writeb(ctl, mmio_base + MM_NAND_CTL); 143 if (cmd != NAND_CMD_NONE)
144 cs553x_write_byte(mtd, cmd);
161} 145}
162 146
163static int cs553x_device_ready(struct mtd_info *mtd) 147static 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)
233 goto out_mtd; 217 goto out_mtd;
234 } 218 }
235 219
236 this->hwcontrol = cs553x_hwcontrol; 220 this->cmd_ctrl = cs553x_hwcontrol;
237 this->dev_ready = cs553x_device_ready; 221 this->dev_ready = cs553x_device_ready;
238 this->read_byte = cs553x_read_byte; 222 this->read_byte = cs553x_read_byte;
239 this->write_byte = cs553x_write_byte; 223 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 };
95#define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil) 95#define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil)
96#define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k) 96#define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k)
97 97
98static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd); 98static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
99 unsigned int bitmask);
99static void doc200x_select_chip(struct mtd_info *mtd, int chip); 100static void doc200x_select_chip(struct mtd_info *mtd, int chip);
100 101
101static int debug = 0; 102static int debug = 0;
@@ -402,12 +403,10 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
402 uint16_t ret; 403 uint16_t ret;
403 404
404 doc200x_select_chip(mtd, nr); 405 doc200x_select_chip(mtd, nr);
405 doc200x_hwcontrol(mtd, NAND_CTL_SETCLE); 406 doc200x_hwcontrol(mtd, NAND_CMD_READID,
406 this->write_byte(mtd, NAND_CMD_READID); 407 NAND_CTRL_CLE | NAND_CTRL_CHANGE);
407 doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE); 408 doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
408 doc200x_hwcontrol(mtd, NAND_CTL_SETALE); 409 doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
409 this->write_byte(mtd, 0);
410 doc200x_hwcontrol(mtd, NAND_CTL_CLRALE);
411 410
412 /* We cant' use dev_ready here, but at least we wait for the 411 /* We cant' use dev_ready here, but at least we wait for the
413 * command to complete 412 * command to complete
@@ -425,12 +424,11 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
425 } ident; 424 } ident;
426 void __iomem *docptr = doc->virtadr; 425 void __iomem *docptr = doc->virtadr;
427 426
428 doc200x_hwcontrol(mtd, NAND_CTL_SETCLE); 427 doc200x_hwcontrol(mtd, NAND_CMD_READID,
429 doc2000_write_byte(mtd, NAND_CMD_READID); 428 NAND_CTRL_CLE | NAND_CTRL_CHANGE);
430 doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE); 429 doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
431 doc200x_hwcontrol(mtd, NAND_CTL_SETALE); 430 doc200x_hwcontrol(mtd, NAND_CMD_NONE,
432 doc2000_write_byte(mtd, 0); 431 NAND_NCE | NAND_CTRL_CHANGE);
433 doc200x_hwcontrol(mtd, NAND_CTL_CLRALE);
434 432
435 udelay(50); 433 udelay(50);
436 434
@@ -690,54 +688,37 @@ static void doc200x_select_chip(struct mtd_info *mtd, int chip)
690 chip -= (floor * doc->chips_per_floor); 688 chip -= (floor * doc->chips_per_floor);
691 689
692 /* 11.4.4 -- deassert CE before changing chip */ 690 /* 11.4.4 -- deassert CE before changing chip */
693 doc200x_hwcontrol(mtd, NAND_CTL_CLRNCE); 691 doc200x_hwcontrol(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
694 692
695 WriteDOC(floor, docptr, FloorSelect); 693 WriteDOC(floor, docptr, FloorSelect);
696 WriteDOC(chip, docptr, CDSNDeviceSelect); 694 WriteDOC(chip, docptr, CDSNDeviceSelect);
697 695
698 doc200x_hwcontrol(mtd, NAND_CTL_SETNCE); 696 doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
699 697
700 doc->curchip = chip; 698 doc->curchip = chip;
701 doc->curfloor = floor; 699 doc->curfloor = floor;
702} 700}
703 701
704static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd) 702#define CDSN_CTRL_MSK (CDSN_CTRL_CE | CDSN_CTRL_CLE | CDSN_CTRL_ALE)
703
704static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
705 unsigned int ctrl)
705{ 706{
706 struct nand_chip *this = mtd->priv; 707 struct nand_chip *this = mtd->priv;
707 struct doc_priv *doc = this->priv; 708 struct doc_priv *doc = this->priv;
708 void __iomem *docptr = doc->virtadr; 709 void __iomem *docptr = doc->virtadr;
709 710
710 switch (cmd) { 711 if (ctrl & NAND_CTRL_CHANGE) {
711 case NAND_CTL_SETNCE: 712 doc->CDSNControl &= ~CDSN_CTRL_MSK;
712 doc->CDSNControl |= CDSN_CTRL_CE; 713 doc->CDSNControl |= ctrl & CDSN_CTRL_MSK;
713 break; 714 if (debug)
714 case NAND_CTL_CLRNCE: 715 printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl);
715 doc->CDSNControl &= ~CDSN_CTRL_CE; 716 WriteDOC(doc->CDSNControl, docptr, CDSNControl);
716 break; 717 /* 11.4.3 -- 4 NOPs after CSDNControl write */
717 case NAND_CTL_SETCLE: 718 DoC_Delay(doc, 4);
718 doc->CDSNControl |= CDSN_CTRL_CLE;
719 break;
720 case NAND_CTL_CLRCLE:
721 doc->CDSNControl &= ~CDSN_CTRL_CLE;
722 break;
723 case NAND_CTL_SETALE:
724 doc->CDSNControl |= CDSN_CTRL_ALE;
725 break;
726 case NAND_CTL_CLRALE:
727 doc->CDSNControl &= ~CDSN_CTRL_ALE;
728 break;
729 case NAND_CTL_SETWP:
730 doc->CDSNControl |= CDSN_CTRL_WP;
731 break;
732 case NAND_CTL_CLRWP:
733 doc->CDSNControl &= ~CDSN_CTRL_WP;
734 break;
735 } 719 }
736 if (debug) 720 if (cmd != NAND_CMD_NONE)
737 printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl); 721 this->write_byte(mtd, cmd);
738 WriteDOC(doc->CDSNControl, docptr, CDSNControl);
739 /* 11.4.3 -- 4 NOPs after CSDNControl write */
740 DoC_Delay(doc, 4);
741} 722}
742 723
743static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int column, int page_addr) 724static 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)
1510 this->read_buf = doc2001plus_readbuf; 1491 this->read_buf = doc2001plus_readbuf;
1511 this->verify_buf = doc2001plus_verifybuf; 1492 this->verify_buf = doc2001plus_verifybuf;
1512 this->scan_bbt = inftl_scan_bbt; 1493 this->scan_bbt = inftl_scan_bbt;
1513 this->hwcontrol = NULL; 1494 this->cmd_ctrl = NULL;
1514 this->select_chip = doc2001plus_select_chip; 1495 this->select_chip = doc2001plus_select_chip;
1515 this->cmdfunc = doc2001plus_command; 1496 this->cmdfunc = doc2001plus_command;
1516 this->ecc.hwctl = doc2001plus_enable_hwecc; 1497 this->ecc.hwctl = doc2001plus_enable_hwecc;
@@ -1670,7 +1651,7 @@ static int __init doc_probe(unsigned long physadr)
1670 1651
1671 nand->priv = doc; 1652 nand->priv = doc;
1672 nand->select_chip = doc200x_select_chip; 1653 nand->select_chip = doc200x_select_chip;
1673 nand->hwcontrol = doc200x_hwcontrol; 1654 nand->cmd_ctrl = doc200x_hwcontrol;
1674 nand->dev_ready = doc200x_dev_ready; 1655 nand->dev_ready = doc200x_dev_ready;
1675 nand->waitfunc = doc200x_wait; 1656 nand->waitfunc = doc200x_wait;
1676 nand->block_bad = doc200x_block_bad; 1657 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[] = {
73 73
74/* 74/*
75 * hardware specific access to control-lines 75 * hardware specific access to control-lines
76 *
77 * NAND_NCE: bit 0 -> bit 7
78 * NAND_CLE: bit 1 -> bit 4
79 * NAND_ALE: bit 2 -> bit 5
76 */ 80 */
77static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd) 81static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
78{ 82{
79 switch (cmd) { 83 struct nand_chip *chip = mtd->priv;
80 84
81 case NAND_CTL_SETCLE: 85 if (ctrl & NAND_CTRL_CHANGE) {
82 clps_writeb(clps_readb(ep7312_pxdr) | 0x10, ep7312_pxdr); 86 unsigned char bits;
83 break; 87
84 case NAND_CTL_CLRCLE: 88 bits = (ctrl & (NAND_CLE | NAND_ALE)) << 3;
85 clps_writeb(clps_readb(ep7312_pxdr) & ~0x10, ep7312_pxdr); 89 bits = (ctrl & NAND_NCE) << 7;
86 break; 90
87 91 clps_writeb((clps_readb(ep7312_pxdr) & 0xB0) | 0x10,
88 case NAND_CTL_SETALE: 92 ep7312_pxdr);
89 clps_writeb(clps_readb(ep7312_pxdr) | 0x20, ep7312_pxdr);
90 break;
91 case NAND_CTL_CLRALE:
92 clps_writeb(clps_readb(ep7312_pxdr) & ~0x20, ep7312_pxdr);
93 break;
94
95 case NAND_CTL_SETNCE:
96 clps_writeb((clps_readb(ep7312_pxdr) | 0x80) & ~0x40, ep7312_pxdr);
97 break;
98 case NAND_CTL_CLRNCE:
99 clps_writeb((clps_readb(ep7312_pxdr) | 0x80) | 0x40, ep7312_pxdr);
100 break;
101 } 93 }
94 if (cmd != NAND_CMD_NONE)
95 writeb(cmd, chip->IO_ADDR_W);
102} 96}
103 97
104/* 98/*
@@ -159,7 +153,7 @@ static int __init ep7312_init(void)
159 /* insert callbacks */ 153 /* insert callbacks */
160 this->IO_ADDR_R = ep7312_fio_base; 154 this->IO_ADDR_R = ep7312_fio_base;
161 this->IO_ADDR_W = ep7312_fio_base; 155 this->IO_ADDR_W = ep7312_fio_base;
162 this->hwcontrol = ep7312_hwcontrol; 156 this->cmd_ctrl = ep7312_hwcontrol;
163 this->dev_ready = ep7312_device_ready; 157 this->dev_ready = ep7312_device_ready;
164 /* 15 us command delay time */ 158 /* 15 us command delay time */
165 this->chip_delay = 15; 159 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[] = {
56 56
57/* 57/*
58 * hardware specific access to control-lines 58 * hardware specific access to control-lines
59 *
60 * NAND_NCE: bit 0 - don't care
61 * NAND_CLE: bit 1 - address bit 2
62 * NAND_ALE: bit 2 - address bit 3
59 */ 63 */
60static void h1910_hwcontrol(struct mtd_info *mtd, int cmd) 64static void h1910_hwcontrol(struct mtd_info *mtd, int cmd,
65 unsigned int ctrl)
61{ 66{
62 struct nand_chip *this = (struct nand_chip *)(mtd->priv); 67 struct nand_chip *chip = mtd->priv;
63 68
64 switch (cmd) { 69 if (cmd != NAND_CMD_NONE)
65 70 writeb(cmd, chip->IO_ADDR_W | ((ctrl & 0x6) << 1));
66 case NAND_CTL_SETCLE:
67 this->IO_ADDR_R |= (1 << 2);
68 this->IO_ADDR_W |= (1 << 2);
69 break;
70 case NAND_CTL_CLRCLE:
71 this->IO_ADDR_R &= ~(1 << 2);
72 this->IO_ADDR_W &= ~(1 << 2);
73 break;
74
75 case NAND_CTL_SETALE:
76 this->IO_ADDR_R |= (1 << 3);
77 this->IO_ADDR_W |= (1 << 3);
78 break;
79 case NAND_CTL_CLRALE:
80 this->IO_ADDR_R &= ~(1 << 3);
81 this->IO_ADDR_W &= ~(1 << 3);
82 break;
83
84 case NAND_CTL_SETNCE:
85 break;
86 case NAND_CTL_CLRNCE:
87 break;
88 }
89} 71}
90 72
91/* 73/*
@@ -145,7 +127,7 @@ static int __init h1910_init(void)
145 /* insert callbacks */ 127 /* insert callbacks */
146 this->IO_ADDR_R = nandaddr; 128 this->IO_ADDR_R = nandaddr;
147 this->IO_ADDR_W = nandaddr; 129 this->IO_ADDR_W = nandaddr;
148 this->hwcontrol = h1910_hwcontrol; 130 this->cmd_ctrl = h1910_hwcontrol;
149 this->dev_ready = NULL; /* unknown whether that was correct or not so we will just do it like this */ 131 this->dev_ready = NULL; /* unknown whether that was correct or not so we will just do it like this */
150 /* 15 us command delay time */ 132 /* 15 us command delay time */
151 this->chip_delay = 50; 133 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)
276 struct nand_chip *this = mtd->priv; 276 struct nand_chip *this = mtd->priv;
277 switch (chip) { 277 switch (chip) {
278 case -1: 278 case -1:
279 this->hwcontrol(mtd, NAND_CTL_CLRNCE); 279 this->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
280 break; 280 break;
281 case 0: 281 case 0:
282 this->hwcontrol(mtd, NAND_CTL_SETNCE); 282 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
283 break; 283 break;
284 284
285 default: 285 default:
@@ -548,13 +548,12 @@ static void nand_wait_ready(struct mtd_info *mtd)
548 * Send command to NAND device. This function is used for small page 548 * Send command to NAND device. This function is used for small page
549 * devices (256/512 Bytes per page) 549 * devices (256/512 Bytes per page)
550 */ 550 */
551static void nand_command(struct mtd_info *mtd, unsigned command, int column, 551static void nand_command(struct mtd_info *mtd, unsigned int command,
552 int page_addr) 552 int column, int page_addr)
553{ 553{
554 register struct nand_chip *this = mtd->priv; 554 register struct nand_chip *this = mtd->priv;
555 int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
555 556
556 /* Begin command latch cycle */
557 this->hwcontrol(mtd, NAND_CTL_SETCLE);
558 /* 557 /*
559 * Write out the command to the device. 558 * Write out the command to the device.
560 */ 559 */
@@ -572,33 +571,32 @@ static void nand_command(struct mtd_info *mtd, unsigned command, int column,
572 column -= 256; 571 column -= 256;
573 readcmd = NAND_CMD_READ1; 572 readcmd = NAND_CMD_READ1;
574 } 573 }
575 this->write_byte(mtd, readcmd); 574 this->cmd_ctrl(mtd, readcmd, ctrl);
575 ctrl &= ~NAND_CTRL_CHANGE;
576 } 576 }
577 this->write_byte(mtd, command); 577 this->cmd_ctrl(mtd, command, ctrl);
578 578
579 /* Set ALE and clear CLE to start address cycle */ 579 /*
580 this->hwcontrol(mtd, NAND_CTL_CLRCLE); 580 * Address cycle, when necessary
581 581 */
582 if (column != -1 || page_addr != -1) { 582 ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
583 this->hwcontrol(mtd, NAND_CTL_SETALE); 583 /* Serially input address */
584 584 if (column != -1) {
585 /* Serially input address */ 585 /* Adjust columns for 16 bit buswidth */
586 if (column != -1) { 586 if (this->options & NAND_BUSWIDTH_16)
587 /* Adjust columns for 16 bit buswidth */ 587 column >>= 1;
588 if (this->options & NAND_BUSWIDTH_16) 588 this->cmd_ctrl(mtd, column, ctrl);
589 column >>= 1; 589 ctrl &= ~NAND_CTRL_CHANGE;
590 this->write_byte(mtd, column); 590 }
591 } 591 if (page_addr != -1) {
592 if (page_addr != -1) { 592 this->cmd_ctrl(mtd, page_addr, ctrl);
593 this->write_byte(mtd, (uint8_t)(page_addr & 0xff)); 593 ctrl &= ~NAND_CTRL_CHANGE;
594 this->write_byte(mtd, (uint8_t)((page_addr >> 8) & 0xff)); 594 this->cmd_ctrl(mtd, page_addr >> 8, ctrl);
595 /* One more address cycle for devices > 32MiB */ 595 /* One more address cycle for devices > 32MiB */
596 if (this->chipsize > (32 << 20)) 596 if (this->chipsize > (32 << 20))
597 this->write_byte(mtd, (uint8_t)((page_addr >> 16) & 0x0f)); 597 this->cmd_ctrl(mtd, page_addr >> 16, ctrl);
598 }
599 /* Latch in address */
600 this->hwcontrol(mtd, NAND_CTL_CLRALE);
601 } 598 }
599 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
602 600
603 /* 601 /*
604 * program and erase have their own busy handlers 602 * program and erase have their own busy handlers
@@ -611,15 +609,16 @@ static void nand_command(struct mtd_info *mtd, unsigned command, int column,
611 case NAND_CMD_ERASE2: 609 case NAND_CMD_ERASE2:
612 case NAND_CMD_SEQIN: 610 case NAND_CMD_SEQIN:
613 case NAND_CMD_STATUS: 611 case NAND_CMD_STATUS:
612 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
614 return; 613 return;
615 614
616 case NAND_CMD_RESET: 615 case NAND_CMD_RESET:
617 if (this->dev_ready) 616 if (this->dev_ready)
618 break; 617 break;
619 udelay(this->chip_delay); 618 udelay(this->chip_delay);
620 this->hwcontrol(mtd, NAND_CTL_SETCLE); 619 this->cmd_ctrl(mtd, NAND_CMD_STATUS,
621 this->write_byte(mtd, NAND_CMD_STATUS); 620 NAND_CTRL_CLE | NAND_CTRL_CHANGE);
622 this->hwcontrol(mtd, NAND_CTL_CLRCLE); 621 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
623 while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ; 622 while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ;
624 return; 623 return;
625 624
@@ -648,12 +647,13 @@ static void nand_command(struct mtd_info *mtd, unsigned command, int column,
648 * @column: the column address for this command, -1 if none 647 * @column: the column address for this command, -1 if none
649 * @page_addr: the page address for this command, -1 if none 648 * @page_addr: the page address for this command, -1 if none
650 * 649 *
651 * Send command to NAND device. This is the version for the new large page devices 650 * Send command to NAND device. This is the version for the new large page
652 * We dont have the separate regions as we have in the small page devices. 651 * devices We dont have the separate regions as we have in the small page
653 * We must emulate NAND_CMD_READOOB to keep the code compatible. 652 * devices. We must emulate NAND_CMD_READOOB to keep the code compatible.
654 * 653 *
655 */ 654 */
656static void nand_command_lp(struct mtd_info *mtd, unsigned command, int column, int page_addr) 655static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
656 int column, int page_addr)
657{ 657{
658 register struct nand_chip *this = mtd->priv; 658 register struct nand_chip *this = mtd->priv;
659 659
@@ -663,34 +663,33 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned command, int column,
663 command = NAND_CMD_READ0; 663 command = NAND_CMD_READ0;
664 } 664 }
665 665
666 /* Begin command latch cycle */ 666 /* Command latch cycle */
667 this->hwcontrol(mtd, NAND_CTL_SETCLE); 667 this->cmd_ctrl(mtd, command & 0xff,
668 /* Write out the command to the device. */ 668 NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
669 this->write_byte(mtd, (command & 0xff));
670 /* End command latch cycle */
671 this->hwcontrol(mtd, NAND_CTL_CLRCLE);
672 669
673 if (column != -1 || page_addr != -1) { 670 if (column != -1 || page_addr != -1) {
674 this->hwcontrol(mtd, NAND_CTL_SETALE); 671 int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
675 672
676 /* Serially input address */ 673 /* Serially input address */
677 if (column != -1) { 674 if (column != -1) {
678 /* Adjust columns for 16 bit buswidth */ 675 /* Adjust columns for 16 bit buswidth */
679 if (this->options & NAND_BUSWIDTH_16) 676 if (this->options & NAND_BUSWIDTH_16)
680 column >>= 1; 677 column >>= 1;
681 this->write_byte(mtd, column & 0xff); 678 this->cmd_ctrl(mtd, column, ctrl);
682 this->write_byte(mtd, column >> 8); 679 ctrl &= ~NAND_CTRL_CHANGE;
680 this->cmd_ctrl(mtd, column >> 8, ctrl);
683 } 681 }
684 if (page_addr != -1) { 682 if (page_addr != -1) {
685 this->write_byte(mtd, (uint8_t)(page_addr & 0xff)); 683 this->cmd_ctrl(mtd, page_addr, ctrl);
686 this->write_byte(mtd, (uint8_t)((page_addr >> 8) & 0xff)); 684 this->cmd_ctrl(mtd, page_addr >> 8,
685 NAND_NCE | NAND_ALE);
687 /* One more address cycle for devices > 128MiB */ 686 /* One more address cycle for devices > 128MiB */
688 if (this->chipsize > (128 << 20)) 687 if (this->chipsize > (128 << 20))
689 this->write_byte(mtd, (uint8_t)((page_addr >> 16) & 0xff)); 688 this->cmd_ctrl(mtd, page_addr >> 16,
689 NAND_NCE | NAND_ALE);
690 } 690 }
691 /* Latch in address */
692 this->hwcontrol(mtd, NAND_CTL_CLRALE);
693 } 691 }
692 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
694 693
695 /* 694 /*
696 * program and erase have their own busy handlers 695 * 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,
722 if (this->dev_ready) 721 if (this->dev_ready)
723 break; 722 break;
724 udelay(this->chip_delay); 723 udelay(this->chip_delay);
725 this->hwcontrol(mtd, NAND_CTL_SETCLE); 724 this->cmd_ctrl(mtd, NAND_CMD_STATUS, NAND_NCE | NAND_CLE);
726 this->write_byte(mtd, NAND_CMD_STATUS); 725 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
727 this->hwcontrol(mtd, NAND_CTL_CLRCLE);
728 while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ; 726 while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ;
729 return; 727 return;
730 728
731 case NAND_CMD_READ0: 729 case NAND_CMD_READ0:
732 /* Begin command latch cycle */ 730 this->cmd_ctrl(mtd, NAND_CMD_READSTART, NAND_NCE | NAND_CLE);
733 this->hwcontrol(mtd, NAND_CTL_SETCLE); 731 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
734 /* Write out the start read command */
735 this->write_byte(mtd, NAND_CMD_READSTART);
736 /* End command latch cycle */
737 this->hwcontrol(mtd, NAND_CTL_CLRCLE);
738 /* Fall through into ready check */
739 732
740 /* This applies to read commands */ 733 /* This applies to read commands */
741 default: 734 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)
1071 } 1071 }
1072} 1072}
1073 1073
1074static void
1075ns_hwcontrol(struct mtd_info *mtd, int cmd)
1076{
1077 struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
1078
1079 switch (cmd) {
1080
1081 /* set CLE line high */
1082 case NAND_CTL_SETCLE:
1083 NS_DBG("ns_hwcontrol: start command latch cycles\n");
1084 ns->lines.cle = 1;
1085 break;
1086
1087 /* set CLE line low */
1088 case NAND_CTL_CLRCLE:
1089 NS_DBG("ns_hwcontrol: stop command latch cycles\n");
1090 ns->lines.cle = 0;
1091 break;
1092
1093 /* set ALE line high */
1094 case NAND_CTL_SETALE:
1095 NS_DBG("ns_hwcontrol: start address latch cycles\n");
1096 ns->lines.ale = 1;
1097 break;
1098
1099 /* set ALE line low */
1100 case NAND_CTL_CLRALE:
1101 NS_DBG("ns_hwcontrol: stop address latch cycles\n");
1102 ns->lines.ale = 0;
1103 break;
1104
1105 /* set WP line high */
1106 case NAND_CTL_SETWP:
1107 NS_DBG("ns_hwcontrol: enable write protection\n");
1108 ns->lines.wp = 1;
1109 break;
1110
1111 /* set WP line low */
1112 case NAND_CTL_CLRWP:
1113 NS_DBG("ns_hwcontrol: disable write protection\n");
1114 ns->lines.wp = 0;
1115 break;
1116
1117 /* set CE line low */
1118 case NAND_CTL_SETNCE:
1119 NS_DBG("ns_hwcontrol: enable chip\n");
1120 ns->lines.ce = 1;
1121 break;
1122
1123 /* set CE line high */
1124 case NAND_CTL_CLRNCE:
1125 NS_DBG("ns_hwcontrol: disable chip\n");
1126 ns->lines.ce = 0;
1127 break;
1128
1129 default:
1130 NS_ERR("hwcontrol: unknown command\n");
1131 }
1132
1133 return;
1134}
1135
1136static u_char 1074static u_char
1137ns_nand_read_byte(struct mtd_info *mtd) 1075ns_nand_read_byte(struct mtd_info *mtd)
1138{ 1076{
@@ -1359,6 +1297,18 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
1359 return; 1297 return;
1360} 1298}
1361 1299
1300static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask)
1301{
1302 struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
1303
1304 ns->lines.cle = bitmask & NAND_CLE ? 1 : 0;
1305 ns->lines.ale = bitmask & NAND_ALE ? 1 : 0;
1306 ns->lines.ce = bitmask & NAND_NCE ? 1 : 0;
1307
1308 if (cmd != NAND_CMD_NONE)
1309 ns_nand_write_byte(mtd, cmd);
1310}
1311
1362static int 1312static int
1363ns_device_ready(struct mtd_info *mtd) 1313ns_device_ready(struct mtd_info *mtd)
1364{ 1314{
@@ -1514,7 +1464,7 @@ static int __init ns_init_module(void)
1514 /* 1464 /*
1515 * Register simulator's callbacks. 1465 * Register simulator's callbacks.
1516 */ 1466 */
1517 chip->hwcontrol = ns_hwcontrol; 1467 chip->cmd_ctrl = ns_hwcontrol;
1518 chip->read_byte = ns_nand_read_byte; 1468 chip->read_byte = ns_nand_read_byte;
1519 chip->dev_ready = ns_device_ready; 1469 chip->dev_ready = ns_device_ready;
1520 chip->write_byte = ns_nand_write_byte; 1470 chip->write_byte = ns_nand_write_byte;
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)
60 writel(ccr, ndfc->ndfcbase + NDFC_CCR); 60 writel(ccr, ndfc->ndfcbase + NDFC_CCR);
61} 61}
62 62
63static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd) 63static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
64{ 64{
65 struct ndfc_controller *ndfc = &ndfc_ctrl;
66 struct nand_chip *chip = mtd->priv; 65 struct nand_chip *chip = mtd->priv;
67 66
68 switch (cmd) { 67 if (cmd == NAND_CMD_NONE)
69 case NAND_CTL_SETCLE: 68 return;
70 chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_CMD; 69
71 break; 70 if (ctrl & NAND_CLE)
72 case NAND_CTL_SETALE: 71 writel(cmd & 0xFF, chip->IO_ADDR_W + NDFC_CMD);
73 chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_ALE; 72 else
74 break; 73 writel(cmd & 0xFF, chip->IO_ADDR_W + NDFC_ALE);
75 default:
76 chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA;
77 break;
78 }
79} 74}
80 75
81static int ndfc_ready(struct mtd_info *mtd) 76static int ndfc_ready(struct mtd_info *mtd)
@@ -158,7 +153,7 @@ static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
158 153
159 chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA; 154 chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
160 chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA; 155 chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA;
161 chip->hwcontrol = ndfc_hwcontrol; 156 chip->cmd_ctrl = ndfc_hwcontrol;
162 chip->dev_ready = ndfc_ready; 157 chip->dev_ready = ndfc_ready;
163 chip->select_chip = ndfc_select_chip; 158 chip->select_chip = ndfc_select_chip;
164 chip->chip_delay = 50; 159 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
108/* 108/*
109 * hardware specific access to control-lines 109 * hardware specific access to control-lines
110 */ 110 */
111static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd) 111static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd,
112 unsigned int ctrl)
112{ 113{
113 switch (cmd) { 114 struct nand_chip *chip = mtd->priv;
114 115
115 case NAND_CTL_SETCLE: 116 if (ctrl & NAND_CTRL_CHANGE) {
116 MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR); 117#error Missing headerfiles. No way to fix this. -tglx
117 break; 118 switch (cmd) {
118 case NAND_CTL_CLRCLE: 119 case NAND_CTL_SETCLE:
119 MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR); 120 MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR);
120 break; 121 break;
121 case NAND_CTL_SETALE: 122 case NAND_CTL_CLRCLE:
122 MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR); 123 MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR);
123 break; 124 break;
124 case NAND_CTL_CLRALE: 125 case NAND_CTL_SETALE:
125 MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR); 126 MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR);
126 break; 127 break;
127 case NAND_CTL_SETNCE: 128 case NAND_CTL_CLRALE:
128 MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND0_PADDR); 129 MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR);
129 break; 130 break;
130 case NAND_CTL_CLRNCE: 131 case NAND_CTL_SETNCE:
131 MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND0_PADDR); 132 MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND0_PADDR);
132 break; 133 break;
134 case NAND_CTL_CLRNCE:
135 MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND0_PADDR);
136 break;
137 }
133 } 138 }
139 if (cmd != NAND_CMD_NONE)
140 writeb(cmd, chip->IO_ADDR_W);
134} 141}
135 142
136static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd) 143static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd,
144 unsigned int ctrl)
137{ 145{
138 switch (cmd) { 146 struct nand_chip *chip = mtd->priv;
139 147
140 case NAND_CTL_SETCLE: 148 if (ctrl & NAND_CTRL_CHANGE) {
141 MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR); 149#error Missing headerfiles. No way to fix this. -tglx
142 break; 150 switch (cmd) {
143 case NAND_CTL_CLRCLE: 151 case NAND_CTL_SETCLE:
144 MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR); 152 MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR);
145 break; 153 break;
146 case NAND_CTL_SETALE: 154 case NAND_CTL_CLRCLE:
147 MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR); 155 MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR);
148 break; 156 break;
149 case NAND_CTL_CLRALE: 157 case NAND_CTL_SETALE:
150 MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR); 158 MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR);
151 break; 159 break;
152 case NAND_CTL_SETNCE: 160 case NAND_CTL_CLRALE:
153 MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR); 161 MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR);
154 break; 162 break;
155 case NAND_CTL_CLRNCE: 163 case NAND_CTL_SETNCE:
156 MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR); 164 MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR);
157 break; 165 break;
166 case NAND_CTL_CLRNCE:
167 MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR);
168 break;
169 }
158 } 170 }
171 if (cmd != NAND_CMD_NONE)
172 writeb(cmd, chip->IO_ADDR_W);
159} 173}
160 174
161#ifdef USE_READY_BUSY_PIN 175#ifdef USE_READY_BUSY_PIN
@@ -251,7 +265,7 @@ static int __init ppchameleonevb_init(void)
251 /* insert callbacks */ 265 /* insert callbacks */
252 this->IO_ADDR_R = ppchameleon_fio_base; 266 this->IO_ADDR_R = ppchameleon_fio_base;
253 this->IO_ADDR_W = ppchameleon_fio_base; 267 this->IO_ADDR_W = ppchameleon_fio_base;
254 this->hwcontrol = ppchameleon_hwcontrol; 268 this->cmd_ctrl = ppchameleon_hwcontrol;
255#ifdef USE_READY_BUSY_PIN 269#ifdef USE_READY_BUSY_PIN
256 this->dev_ready = ppchameleon_device_ready; 270 this->dev_ready = ppchameleon_device_ready;
257#endif 271#endif
@@ -351,7 +365,7 @@ static int __init ppchameleonevb_init(void)
351 /* insert callbacks */ 365 /* insert callbacks */
352 this->IO_ADDR_R = ppchameleonevb_fio_base; 366 this->IO_ADDR_R = ppchameleonevb_fio_base;
353 this->IO_ADDR_W = ppchameleonevb_fio_base; 367 this->IO_ADDR_W = ppchameleonevb_fio_base;
354 this->hwcontrol = ppchameleonevb_hwcontrol; 368 this->cmd_ctrl = ppchameleonevb_hwcontrol;
355#ifdef USE_READY_BUSY_PIN 369#ifdef USE_READY_BUSY_PIN
356 this->dev_ready = ppchameleonevb_device_ready; 370 this->dev_ready = ppchameleonevb_device_ready;
357#endif 371#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] = {
208 * Address lines (A24-A22), so no action is required here. 208 * Address lines (A24-A22), so no action is required here.
209 * 209 *
210 */ 210 */
211static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd) 211static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd,
212 unsigned int ctrl)
212{ 213{
213 struct nand_chip *this = (struct nand_chip *)(mtd->priv); 214 struct nand_chip *chip = (mtd->priv);
214 215
215 switch (cmd) { 216 if (cmd == NAND_CMD_NONE)
217 return;
216 218
217 case NAND_CTL_SETCLE: 219 if (ctrl & NAND_CLE)
218 this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_CLE); 220 writeb(cmd, chip->IO_ADDR_W | RTC_FROM4_CLE);
219 break; 221 else
220 case NAND_CTL_CLRCLE: 222 writeb(cmd, chip->IO_ADDR_W | RTC_FROM4_ALE);
221 this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_CLE);
222 break;
223
224 case NAND_CTL_SETALE:
225 this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_ALE);
226 break;
227 case NAND_CTL_CLRALE:
228 this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_ALE);
229 break;
230
231 case NAND_CTL_SETNCE:
232 break;
233 case NAND_CTL_CLRNCE:
234 break;
235
236 }
237} 223}
238 224
239/* 225/*
@@ -559,7 +545,7 @@ static int __init rtc_from4_init(void)
559 this->IO_ADDR_R = rtc_from4_fio_base; 545 this->IO_ADDR_R = rtc_from4_fio_base;
560 this->IO_ADDR_W = rtc_from4_fio_base; 546 this->IO_ADDR_W = rtc_from4_fio_base;
561 /* Set address of hardware control function */ 547 /* Set address of hardware control function */
562 this->hwcontrol = rtc_from4_hwcontrol; 548 this->cmd_ctrl = rtc_from4_hwcontrol;
563 /* Set address of chip select function */ 549 /* Set address of chip select function */
564 this->select_chip = rtc_from4_nand_select_chip; 550 this->select_chip = rtc_from4_nand_select_chip;
565 /* command delay time (in us) */ 551 /* 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)
256 * 256 *
257*/ 257*/
258 258
259static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd) 259static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd,
260 unsigend int ctrl)
260{ 261{
261 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); 262 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
262 struct nand_chip *chip = mtd->priv; 263 struct nand_chip *chip = mtd->priv;
263 264
264 switch (cmd) { 265 if (cmd == NAND_CMD_NONE)
265 case NAND_CTL_SETNCE: 266 return;
266 case NAND_CTL_CLRNCE: 267
267 printk(KERN_ERR "%s: called for NCE\n", __FUNCTION__); 268 if (cmd & NAND_CLE)
268 break; 269 writeb(cmd, info->regs + S3C2410_NFCMD);
269 270 else
270 case NAND_CTL_SETCLE: 271 writeb(cmd, info->regs + S3C2410_NFADDR);
271 chip->IO_ADDR_W = info->regs + S3C2410_NFCMD;
272 break;
273
274 case NAND_CTL_SETALE:
275 chip->IO_ADDR_W = info->regs + S3C2410_NFADDR;
276 break;
277
278 /* NAND_CTL_CLRCLE: */
279 /* NAND_CTL_CLRALE: */
280 default:
281 chip->IO_ADDR_W = info->regs + S3C2410_NFDATA;
282 break;
283 }
284} 272}
285 273
286/* command and control functions */ 274/* command and control functions */
287 275
288static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd) 276static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd,
277 unsigend int ctrl)
289{ 278{
290 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); 279 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
291 struct nand_chip *chip = mtd->priv; 280 struct nand_chip *chip = mtd->priv;
292 281
293 switch (cmd) { 282 if (cmd == NAND_CMD_NONE)
294 case NAND_CTL_SETNCE: 283 return;
295 case NAND_CTL_CLRNCE: 284
296 printk(KERN_ERR "%s: called for NCE\n", __FUNCTION__); 285 if (cmd & NAND_CLE)
297 break; 286 writeb(cmd, info->regs + S3C2440_NFCMD);
298 287 else
299 case NAND_CTL_SETCLE: 288 writeb(cmd, info->regs + S3C2440_NFADDR);
300 chip->IO_ADDR_W = info->regs + S3C2440_NFCMD;
301 break;
302
303 case NAND_CTL_SETALE:
304 chip->IO_ADDR_W = info->regs + S3C2440_NFADDR;
305 break;
306
307 /* NAND_CTL_CLRCLE: */
308 /* NAND_CTL_CLRALE: */
309 default:
310 chip->IO_ADDR_W = info->regs + S3C2440_NFDATA;
311 break;
312 }
313} 289}
314 290
315/* s3c2410_nand_devready() 291/* s3c2410_nand_devready()
@@ -498,7 +474,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
498 474
499 chip->IO_ADDR_R = info->regs + S3C2410_NFDATA; 475 chip->IO_ADDR_R = info->regs + S3C2410_NFDATA;
500 chip->IO_ADDR_W = info->regs + S3C2410_NFDATA; 476 chip->IO_ADDR_W = info->regs + S3C2410_NFDATA;
501 chip->hwcontrol = s3c2410_nand_hwcontrol; 477 chip->cmd_ctrl = s3c2410_nand_hwcontrol;
502 chip->dev_ready = s3c2410_nand_devready; 478 chip->dev_ready = s3c2410_nand_devready;
503 chip->write_buf = s3c2410_nand_write_buf; 479 chip->write_buf = s3c2410_nand_write_buf;
504 chip->read_buf = s3c2410_nand_read_buf; 480 chip->read_buf = s3c2410_nand_read_buf;
@@ -511,7 +487,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
511 if (info->is_s3c2440) { 487 if (info->is_s3c2440) {
512 chip->IO_ADDR_R = info->regs + S3C2440_NFDATA; 488 chip->IO_ADDR_R = info->regs + S3C2440_NFDATA;
513 chip->IO_ADDR_W = info->regs + S3C2440_NFDATA; 489 chip->IO_ADDR_W = info->regs + S3C2440_NFDATA;
514 chip->hwcontrol = s3c2440_nand_hwcontrol; 490 chip->cmd_ctrl = s3c2440_nand_hwcontrol;
515 } 491 }
516 492
517 nmtd->info = info; 493 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[] = {
77 77
78/* 78/*
79 * hardware specific access to control-lines 79 * hardware specific access to control-lines
80 * ctrl:
81 * NAND_CNE: bit 0 -> bit 0 & 4
82 * NAND_CLE: bit 1 -> bit 1
83 * NAND_ALE: bit 2 -> bit 2
84 *
80 */ 85 */
81static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd) 86static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd,
87 unsigned int ctrl)
82{ 88{
83 switch (cmd) { 89 struct nand_chip *chip = mtd->priv;
84 case NAND_CTL_SETCLE: 90
85 writeb(readb(FLASHCTL) | FLCLE, FLASHCTL); 91 if (ctrl & NAND_CTRL_CHANGE) {
86 break; 92 unsigned char bits = ctrl & 0x07;
87 case NAND_CTL_CLRCLE: 93
88 writeb(readb(FLASHCTL) & ~FLCLE, FLASHCTL); 94 bits |= (ctrl & 0x01) << 4;
89 break; 95 writeb((readb(FLASHCTL) & 0x17) | bits, FLASHCTL);
90
91 case NAND_CTL_SETALE:
92 writeb(readb(FLASHCTL) | FLALE, FLASHCTL);
93 break;
94 case NAND_CTL_CLRALE:
95 writeb(readb(FLASHCTL) & ~FLALE, FLASHCTL);
96 break;
97
98 case NAND_CTL_SETNCE:
99 writeb(readb(FLASHCTL) & ~(FLCE0 | FLCE1), FLASHCTL);
100 break;
101 case NAND_CTL_CLRNCE:
102 writeb(readb(FLASHCTL) | (FLCE0 | FLCE1), FLASHCTL);
103 break;
104 } 96 }
97
98 if (cmd != NAND_CMD_NONE)
99 writeb(cmd, chip->IO_ADDR_W);
105} 100}
106 101
107static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; 102static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
@@ -196,7 +191,7 @@ static int __init sharpsl_nand_init(void)
196 this->IO_ADDR_R = FLASHIO; 191 this->IO_ADDR_R = FLASHIO;
197 this->IO_ADDR_W = FLASHIO; 192 this->IO_ADDR_W = FLASHIO;
198 /* Set address of hardware control function */ 193 /* Set address of hardware control function */
199 this->hwcontrol = sharpsl_nand_hwcontrol; 194 this->cmd_ctrl = sharpsl_nand_hwcontrol;
200 this->dev_ready = sharpsl_nand_dev_ready; 195 this->dev_ready = sharpsl_nand_dev_ready;
201 /* 15 us command delay time */ 196 /* 15 us command delay time */
202 this->chip_delay = 15; 197 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[] = {
82 82
83/* 83/*
84 * hardware specific access to control-lines 84 * hardware specific access to control-lines
85*/ 85 *
86 * ctrl:
87 * NAND_CNE: bit 0 -> bit 2
88 * NAND_CLE: bit 1 -> bit 0
89 * NAND_ALE: bit 2 -> bit 1
90 */
86static void spia_hwcontrol(struct mtd_info *mtd, int cmd) 91static void spia_hwcontrol(struct mtd_info *mtd, int cmd)
87{ 92{
88 switch (cmd) { 93 struct nand_chip *chip = mtd->priv;
89 94
90 case NAND_CTL_SETCLE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |= 0x01; break; 95 if (ctrl & NAND_CTRL_CHANGE) {
91 case NAND_CTL_CLRCLE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x01; break; 96 void __iomem *addr = spia_io_base + spia_pedr;
97 unsigned char bits;
92 98
93 case NAND_CTL_SETALE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |= 0x02; break; 99 bits = (ctrl & NAND_CNE) << 2;
94 case NAND_CTL_CLRALE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x02; break; 100 bits |= (ctrl & NAND_CLE | NAND_ALE) >> 1;
95 101 writeb((readb(addr) & ~0x7) | bits, addr);
96 case NAND_CTL_SETNCE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x04; break;
97 case NAND_CTL_CLRNCE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |= 0x04; break;
98 } 102 }
103
104 if (cmd != NAND_CMD_NONE)
105 writeb(cmd, chip->IO_ADDR_W);
99} 106}
100 107
101/* 108/*
@@ -133,7 +140,7 @@ static int __init spia_init(void)
133 this->IO_ADDR_R = (void __iomem *)spia_fio_base; 140 this->IO_ADDR_R = (void __iomem *)spia_fio_base;
134 this->IO_ADDR_W = (void __iomem *)spia_fio_base; 141 this->IO_ADDR_W = (void __iomem *)spia_fio_base;
135 /* Set address of hardware control function */ 142 /* Set address of hardware control function */
136 this->hwcontrol = spia_hwcontrol; 143 this->cmd_ctrl = spia_hwcontrol;
137 /* 15 us command delay time */ 144 /* 15 us command delay time */
138 this->chip_delay = 15; 145 this->chip_delay = 15;
139 146
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 @@
32#include <asm/arch-omap1510/hardware.h> 32#include <asm/arch-omap1510/hardware.h>
33#include <asm/arch/gpio.h> 33#include <asm/arch/gpio.h>
34 34
35#define CONFIG_NAND_WORKAROUND 1
36
35/* 37/*
36 * MTD structure for TOTO board 38 * MTD structure for TOTO board
37 */ 39 */
@@ -39,25 +41,6 @@ static struct mtd_info *toto_mtd = NULL;
39 41
40static unsigned long toto_io_base = OMAP_FLASH_1_BASE; 42static unsigned long toto_io_base = OMAP_FLASH_1_BASE;
41 43
42#define CONFIG_NAND_WORKAROUND 1
43
44#define NAND_NCE 0x4000
45#define NAND_CLE 0x1000
46#define NAND_ALE 0x0002
47#define NAND_MASK (NAND_CLE | NAND_ALE | NAND_NCE)
48
49#define T_NAND_CTL_CLRALE(iob) gpiosetout(NAND_ALE, 0)
50#define T_NAND_CTL_SETALE(iob) gpiosetout(NAND_ALE, NAND_ALE)
51#ifdef CONFIG_NAND_WORKAROUND /* "some" dev boards busted, blue wired to rts2 :( */
52#define T_NAND_CTL_CLRCLE(iob) gpiosetout(NAND_CLE, 0); rts2setout(2, 2)
53#define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE); rts2setout(2, 0)
54#else
55#define T_NAND_CTL_CLRCLE(iob) gpiosetout(NAND_CLE, 0)
56#define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE)
57#endif
58#define T_NAND_CTL_SETNCE(iob) gpiosetout(NAND_NCE, 0)
59#define T_NAND_CTL_CLRNCE(iob) gpiosetout(NAND_NCE, NAND_NCE)
60
61/* 44/*
62 * Define partitions for flash devices 45 * Define partitions for flash devices
63 */ 46 */
@@ -91,25 +74,43 @@ static struct mtd_partition partition_info32M[] = {
91 74
92#define NUM_PARTITIONS32M 3 75#define NUM_PARTITIONS32M 3
93#define NUM_PARTITIONS64M 4 76#define NUM_PARTITIONS64M 4
77
94/* 78/*
95 * hardware specific access to control-lines 79 * hardware specific access to control-lines
96*/ 80 *
97 81 * ctrl:
98static void toto_hwcontrol(struct mtd_info *mtd, int cmd) 82 * NAND_NCE: bit 0 -> bit 14 (0x4000)
83 * NAND_CLE: bit 1 -> bit 12 (0x1000)
84 * NAND_ALE: bit 2 -> bit 1 (0x0002)
85 */
86static void toto_hwcontrol(struct mtd_info *mtd, int cmd,
87 unsigned int ctrl)
99{ 88{
89 struct nand_chip *chip = mtd->priv;
90
91 if (ctrl & NAND_CTRL_CHANGE) {
92 unsigned long bits;
100 93
101 udelay(1); /* hopefully enough time for tc make proceding write to clear */ 94 /* hopefully enough time for tc make proceding write to clear */
102 switch (cmd) { 95 udelay(1);
103 case NAND_CTL_SETCLE: T_NAND_CTL_SETCLE(cmd); break;
104 case NAND_CTL_CLRCLE: T_NAND_CTL_CLRCLE(cmd); break;
105 96
106 case NAND_CTL_SETALE: T_NAND_CTL_SETALE(cmd); break; 97 bits = (~ctrl & NAND_NCE) << 14;
107 case NAND_CTL_CLRALE: T_NAND_CTL_CLRALE(cmd); break; 98 bits |= (ctrl & NAND_CLE) << 12;
99 bits |= (ctrl & NAND_ALE) >> 1;
108 100
109 case NAND_CTL_SETNCE: T_NAND_CTL_SETNCE(cmd); break; 101#warning Wild guess as gpiosetout() is nowhere defined in the kernel source - tglx
110 case NAND_CTL_CLRNCE: T_NAND_CTL_CLRNCE(cmd); break; 102 gpiosetout(0x5002, bits);
103
104#ifdef CONFIG_NAND_WORKAROUND
105 /* "some" dev boards busted, blue wired to rts2 :( */
106 rts2setout(2, (ctrl & NAND_CLE) << 1);
107#endif
108 /* allow time to ensure gpio state to over take memory write */
109 udelay(1);
111 } 110 }
112 udelay(1); /* allow time to ensure gpio state to over take memory write */ 111
112 if (cmd != NAND_CMD_NONE)
113 writeb(cmd, chip->IO_ADDR_W);
113} 114}
114 115
115/* 116/*
@@ -142,7 +143,7 @@ static int __init toto_init(void)
142 /* Set address of NAND IO lines */ 143 /* Set address of NAND IO lines */
143 this->IO_ADDR_R = toto_io_base; 144 this->IO_ADDR_R = toto_io_base;
144 this->IO_ADDR_W = toto_io_base; 145 this->IO_ADDR_W = toto_io_base;
145 this->hwcontrol = toto_hwcontrol; 146 this->cmd_ctrl = toto_hwcontrol;
146 this->dev_ready = NULL; 147 this->dev_ready = NULL;
147 /* 25 us command delay time */ 148 /* 25 us command delay time */
148 this->chip_delay = 30; 149 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[] = {
83 83
84/* 84/*
85 * hardware specific access to control-lines 85 * hardware specific access to control-lines
86 *
87 * ctrl:
88 * NAND_NCE: bit 0 -> bit 2
89 * NAND_CLE: bit 1 -> bit 1
90 * NAND_ALE: bit 2 -> bit 0
86 */ 91 */
87static void ts7250_hwcontrol(struct mtd_info *mtd, int cmd) 92static void ts7250_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
88{ 93{
89 unsigned long ctrl = TS72XX_NAND_CONTROL_VIRT_BASE; 94 struct nand_chip *chip = mtd->priv;
90 95
91 switch (cmd) { 96 if (ctrl & NAND_CTRL_CHANGE) {
92 case NAND_CTL_SETCLE: 97 unsigned long addr = TS72XX_NAND_CONTROL_VIRT_BASE;
93 __raw_writeb(__raw_readb(ctrl) | 0x2, ctrl); 98 unsigned char bits;
94 break; 99
95 case NAND_CTL_CLRCLE: 100 bits = (ctrl & NAND_CNE) << 2;
96 __raw_writeb(__raw_readb(ctrl) & ~0x2, ctrl); 101 bits |= ctrl & NAND_CLE;
97 break; 102 bits |= (ctrl & NAND_ALE) >> 2;
98 case NAND_CTL_SETALE: 103
99 __raw_writeb(__raw_readb(ctrl) | 0x1, ctrl); 104 __raw_writeb((__raw_readb(addr) & ~0x7) | bits, addr);
100 break;
101 case NAND_CTL_CLRALE:
102 __raw_writeb(__raw_readb(ctrl) & ~0x1, ctrl);
103 break;
104 case NAND_CTL_SETNCE:
105 __raw_writeb(__raw_readb(ctrl) | 0x4, ctrl);
106 break;
107 case NAND_CTL_CLRNCE:
108 __raw_writeb(__raw_readb(ctrl) & ~0x4, ctrl);
109 break;
110 } 105 }
106
107 if (cmd != NAND_CMD_NONE)
108 writeb(cmd, chip->IO_ADDR_W);
111} 109}
112 110
113/* 111/*
@@ -152,7 +150,7 @@ static int __init ts7250_init(void)
152 /* insert callbacks */ 150 /* insert callbacks */
153 this->IO_ADDR_R = (void *)TS72XX_NAND_DATA_VIRT_BASE; 151 this->IO_ADDR_R = (void *)TS72XX_NAND_DATA_VIRT_BASE;
154 this->IO_ADDR_W = (void *)TS72XX_NAND_DATA_VIRT_BASE; 152 this->IO_ADDR_W = (void *)TS72XX_NAND_DATA_VIRT_BASE;
155 this->hwcontrol = ts7250_hwcontrol; 153 this->cmd_ctrl = ts7250_hwcontrol;
156 this->dev_ready = ts7250_device_ready; 154 this->dev_ready = ts7250_device_ready;
157 this->chip_delay = 15; 155 this->chip_delay = 15;
158 this->ecc.mode = NAND_ECC_SOFT; 156 this->ecc.mode = NAND_ECC_SOFT;