Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

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