aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/au1550nd.c
diff options
context:
space:
mode:
authorKaiGai Kohei <kaigai@ak.jp.nec.com>2006-05-18 11:43:53 -0400
committerKaiGai Kohei <kaigai@ak.jp.nec.com>2006-05-18 11:43:53 -0400
commit20a92fc74c5c91c7bc5693d51acc2b99aceb0465 (patch)
tree41bf535f38ff1a29c560bcf622e9b4ef03c2c106 /drivers/mtd/nand/au1550nd.c
parent21b9879bf2817aca343cdda11ade6a87f5373e74 (diff)
parentf6a673b3f4f93c1c50e1b18f29254b0531b722a8 (diff)
Merge git://git.infradead.org/mtd-2.6
Diffstat (limited to 'drivers/mtd/nand/au1550nd.c')
-rw-r--r--drivers/mtd/nand/au1550nd.c287
1 files changed, 213 insertions, 74 deletions
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index bde3550910a2..d9a0143e1d3a 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -14,6 +14,7 @@
14#include <linux/slab.h> 14#include <linux/slab.h>
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/interrupt.h>
17#include <linux/mtd/mtd.h> 18#include <linux/mtd/mtd.h>
18#include <linux/mtd/nand.h> 19#include <linux/mtd/nand.h>
19#include <linux/mtd/partitions.h> 20#include <linux/mtd/partitions.h>
@@ -38,22 +39,20 @@
38 */ 39 */
39static struct mtd_info *au1550_mtd = NULL; 40static struct mtd_info *au1550_mtd = NULL;
40static void __iomem *p_nand; 41static void __iomem *p_nand;
41static int nand_width = 1; /* default x8*/ 42static int nand_width = 1; /* default x8 */
42 43
43/* 44/*
44 * Define partitions for flash device 45 * Define partitions for flash device
45 */ 46 */
46static const struct mtd_partition partition_info[] = { 47static const struct mtd_partition partition_info[] = {
47 { 48 {
48 .name = "NAND FS 0", 49 .name = "NAND FS 0",
49 .offset = 0, 50 .offset = 0,
50 .size = 8*1024*1024 51 .size = 8 * 1024 * 1024},
51 },
52 { 52 {
53 .name = "NAND FS 1", 53 .name = "NAND FS 1",
54 .offset = MTDPART_OFS_APPEND, 54 .offset = MTDPART_OFS_APPEND,
55 .size = MTDPART_SIZ_FULL 55 .size = MTDPART_SIZ_FULL}
56 }
57}; 56};
58 57
59/** 58/**
@@ -157,7 +156,7 @@ static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
157 int i; 156 int i;
158 struct nand_chip *this = mtd->priv; 157 struct nand_chip *this = mtd->priv;
159 158
160 for (i=0; i<len; i++) { 159 for (i = 0; i < len; i++) {
161 writeb(buf[i], this->IO_ADDR_W); 160 writeb(buf[i], this->IO_ADDR_W);
162 au_sync(); 161 au_sync();
163 } 162 }
@@ -176,7 +175,7 @@ static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
176 int i; 175 int i;
177 struct nand_chip *this = mtd->priv; 176 struct nand_chip *this = mtd->priv;
178 177
179 for (i=0; i<len; i++) { 178 for (i = 0; i < len; i++) {
180 buf[i] = readb(this->IO_ADDR_R); 179 buf[i] = readb(this->IO_ADDR_R);
181 au_sync(); 180 au_sync();
182 } 181 }
@@ -195,7 +194,7 @@ static int au_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
195 int i; 194 int i;
196 struct nand_chip *this = mtd->priv; 195 struct nand_chip *this = mtd->priv;
197 196
198 for (i=0; i<len; i++) { 197 for (i = 0; i < len; i++) {
199 if (buf[i] != readb(this->IO_ADDR_R)) 198 if (buf[i] != readb(this->IO_ADDR_R))
200 return -EFAULT; 199 return -EFAULT;
201 au_sync(); 200 au_sync();
@@ -219,7 +218,7 @@ static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
219 u16 *p = (u16 *) buf; 218 u16 *p = (u16 *) buf;
220 len >>= 1; 219 len >>= 1;
221 220
222 for (i=0; i<len; i++) { 221 for (i = 0; i < len; i++) {
223 writew(p[i], this->IO_ADDR_W); 222 writew(p[i], this->IO_ADDR_W);
224 au_sync(); 223 au_sync();
225 } 224 }
@@ -241,7 +240,7 @@ static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
241 u16 *p = (u16 *) buf; 240 u16 *p = (u16 *) buf;
242 len >>= 1; 241 len >>= 1;
243 242
244 for (i=0; i<len; i++) { 243 for (i = 0; i < len; i++) {
245 p[i] = readw(this->IO_ADDR_R); 244 p[i] = readw(this->IO_ADDR_R);
246 au_sync(); 245 au_sync();
247 } 246 }
@@ -262,7 +261,7 @@ static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
262 u16 *p = (u16 *) buf; 261 u16 *p = (u16 *) buf;
263 len >>= 1; 262 len >>= 1;
264 263
265 for (i=0; i<len; i++) { 264 for (i = 0; i < len; i++) {
266 if (p[i] != readw(this->IO_ADDR_R)) 265 if (p[i] != readw(this->IO_ADDR_R))
267 return -EFAULT; 266 return -EFAULT;
268 au_sync(); 267 au_sync();
@@ -275,27 +274,35 @@ static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
275{ 274{
276 register struct nand_chip *this = mtd->priv; 275 register struct nand_chip *this = mtd->priv;
277 276
278 switch(cmd){ 277 switch (cmd) {
278
279 case NAND_CTL_SETCLE:
280 this->IO_ADDR_W = p_nand + MEM_STNAND_CMD;
281 break;
279 282
280 case NAND_CTL_SETCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_CMD; break; 283 case NAND_CTL_CLRCLE:
281 case NAND_CTL_CLRCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; break; 284 this->IO_ADDR_W = p_nand + MEM_STNAND_DATA;
285 break;
286
287 case NAND_CTL_SETALE:
288 this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR;
289 break;
282 290
283 case NAND_CTL_SETALE: this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR; break;
284 case NAND_CTL_CLRALE: 291 case NAND_CTL_CLRALE:
285 this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; 292 this->IO_ADDR_W = p_nand + MEM_STNAND_DATA;
286 /* FIXME: Nobody knows why this is neccecary, 293 /* FIXME: Nobody knows why this is necessary,
287 * but it works only that way */ 294 * but it works only that way */
288 udelay(1); 295 udelay(1);
289 break; 296 break;
290 297
291 case NAND_CTL_SETNCE: 298 case NAND_CTL_SETNCE:
292 /* assert (force assert) chip enable */ 299 /* assert (force assert) chip enable */
293 au_writel((1<<(4+NAND_CS)) , MEM_STNDCTL); break; 300 au_writel((1 << (4 + NAND_CS)), MEM_STNDCTL);
294 break; 301 break;
295 302
296 case NAND_CTL_CLRNCE: 303 case NAND_CTL_CLRNCE:
297 /* deassert chip enable */ 304 /* deassert chip enable */
298 au_writel(0, MEM_STNDCTL); break; 305 au_writel(0, MEM_STNDCTL);
299 break; 306 break;
300 } 307 }
301 308
@@ -312,69 +319,200 @@ int au1550_device_ready(struct mtd_info *mtd)
312 return ret; 319 return ret;
313} 320}
314 321
322/**
323 * au1550_select_chip - control -CE line
324 * Forbid driving -CE manually permitting the NAND controller to do this.
325 * Keeping -CE asserted during the whole sector reads interferes with the
326 * NOR flash and PCMCIA drivers as it causes contention on the static bus.
327 * We only have to hold -CE low for the NAND read commands since the flash
328 * chip needs it to be asserted during chip not ready time but the NAND
329 * controller keeps it released.
330 *
331 * @mtd: MTD device structure
332 * @chip: chipnumber to select, -1 for deselect
333 */
334static void au1550_select_chip(struct mtd_info *mtd, int chip)
335{
336}
337
338/**
339 * au1550_command - Send command to NAND device
340 * @mtd: MTD device structure
341 * @command: the command to be sent
342 * @column: the column address for this command, -1 if none
343 * @page_addr: the page address for this command, -1 if none
344 */
345static void au1550_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
346{
347 register struct nand_chip *this = mtd->priv;
348 int ce_override = 0, i;
349 ulong flags;
350
351 /* Begin command latch cycle */
352 this->hwcontrol(mtd, NAND_CTL_SETCLE);
353 /*
354 * Write out the command to the device.
355 */
356 if (command == NAND_CMD_SEQIN) {
357 int readcmd;
358
359 if (column >= mtd->oobblock) {
360 /* OOB area */
361 column -= mtd->oobblock;
362 readcmd = NAND_CMD_READOOB;
363 } else if (column < 256) {
364 /* First 256 bytes --> READ0 */
365 readcmd = NAND_CMD_READ0;
366 } else {
367 column -= 256;
368 readcmd = NAND_CMD_READ1;
369 }
370 this->write_byte(mtd, readcmd);
371 }
372 this->write_byte(mtd, command);
373
374 /* Set ALE and clear CLE to start address cycle */
375 this->hwcontrol(mtd, NAND_CTL_CLRCLE);
376
377 if (column != -1 || page_addr != -1) {
378 this->hwcontrol(mtd, NAND_CTL_SETALE);
379
380 /* Serially input address */
381 if (column != -1) {
382 /* Adjust columns for 16 bit buswidth */
383 if (this->options & NAND_BUSWIDTH_16)
384 column >>= 1;
385 this->write_byte(mtd, column);
386 }
387 if (page_addr != -1) {
388 this->write_byte(mtd, (u8)(page_addr & 0xff));
389
390 if (command == NAND_CMD_READ0 ||
391 command == NAND_CMD_READ1 ||
392 command == NAND_CMD_READOOB) {
393 /*
394 * NAND controller will release -CE after
395 * the last address byte is written, so we'll
396 * have to forcibly assert it. No interrupts
397 * are allowed while we do this as we don't
398 * want the NOR flash or PCMCIA drivers to
399 * steal our precious bytes of data...
400 */
401 ce_override = 1;
402 local_irq_save(flags);
403 this->hwcontrol(mtd, NAND_CTL_SETNCE);
404 }
405
406 this->write_byte(mtd, (u8)(page_addr >> 8));
407
408 /* One more address cycle for devices > 32MiB */
409 if (this->chipsize > (32 << 20))
410 this->write_byte(mtd, (u8)((page_addr >> 16) & 0x0f));
411 }
412 /* Latch in address */
413 this->hwcontrol(mtd, NAND_CTL_CLRALE);
414 }
415
416 /*
417 * Program and erase have their own busy handlers.
418 * Status and sequential in need no delay.
419 */
420 switch (command) {
421
422 case NAND_CMD_PAGEPROG:
423 case NAND_CMD_ERASE1:
424 case NAND_CMD_ERASE2:
425 case NAND_CMD_SEQIN:
426 case NAND_CMD_STATUS:
427 return;
428
429 case NAND_CMD_RESET:
430 break;
431
432 case NAND_CMD_READ0:
433 case NAND_CMD_READ1:
434 case NAND_CMD_READOOB:
435 /* Check if we're really driving -CE low (just in case) */
436 if (unlikely(!ce_override))
437 break;
438
439 /* Apply a short delay always to ensure that we do wait tWB. */
440 ndelay(100);
441 /* Wait for a chip to become ready... */
442 for (i = this->chip_delay; !this->dev_ready(mtd) && i > 0; --i)
443 udelay(1);
444
445 /* Release -CE and re-enable interrupts. */
446 this->hwcontrol(mtd, NAND_CTL_CLRNCE);
447 local_irq_restore(flags);
448 return;
449 }
450 /* Apply this short delay always to ensure that we do wait tWB. */
451 ndelay(100);
452
453 while(!this->dev_ready(mtd));
454}
455
456
315/* 457/*
316 * Main initialization routine 458 * Main initialization routine
317 */ 459 */
318int __init au1xxx_nand_init (void) 460static int __init au1xxx_nand_init(void)
319{ 461{
320 struct nand_chip *this; 462 struct nand_chip *this;
321 u16 boot_swapboot = 0; /* default value */ 463 u16 boot_swapboot = 0; /* default value */
322 int retval; 464 int retval;
323 u32 mem_staddr; 465 u32 mem_staddr;
324 u32 nand_phys; 466 u32 nand_phys;
325 467
326 /* Allocate memory for MTD device structure and private data */ 468 /* Allocate memory for MTD device structure and private data */
327 au1550_mtd = kmalloc (sizeof(struct mtd_info) + 469 au1550_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
328 sizeof (struct nand_chip), GFP_KERNEL);
329 if (!au1550_mtd) { 470 if (!au1550_mtd) {
330 printk ("Unable to allocate NAND MTD dev structure.\n"); 471 printk("Unable to allocate NAND MTD dev structure.\n");
331 return -ENOMEM; 472 return -ENOMEM;
332 } 473 }
333 474
334 /* Get pointer to private data */ 475 /* Get pointer to private data */
335 this = (struct nand_chip *) (&au1550_mtd[1]); 476 this = (struct nand_chip *)(&au1550_mtd[1]);
336 477
337 /* Initialize structures */ 478 /* Initialize structures */
338 memset((char *) au1550_mtd, 0, sizeof(struct mtd_info)); 479 memset(au1550_mtd, 0, sizeof(struct mtd_info));
339 memset((char *) this, 0, sizeof(struct nand_chip)); 480 memset(this, 0, sizeof(struct nand_chip));
340 481
341 /* Link the private data with the MTD structure */ 482 /* Link the private data with the MTD structure */
342 au1550_mtd->priv = this; 483 au1550_mtd->priv = this;
484 au1550_mtd->owner = THIS_MODULE;
343 485
344 486
345 /* disable interrupts */ 487 /* MEM_STNDCTL: disable ints, disable nand boot */
346 au_writel(au_readl(MEM_STNDCTL) & ~(1<<8), MEM_STNDCTL); 488 au_writel(0, MEM_STNDCTL);
347
348 /* disable NAND boot */
349 au_writel(au_readl(MEM_STNDCTL) & ~(1<<0), MEM_STNDCTL);
350 489
351#ifdef CONFIG_MIPS_PB1550 490#ifdef CONFIG_MIPS_PB1550
352 /* set gpio206 high */ 491 /* set gpio206 high */
353 au_writel(au_readl(GPIO2_DIR) & ~(1<<6), GPIO2_DIR); 492 au_writel(au_readl(GPIO2_DIR) & ~(1 << 6), GPIO2_DIR);
354 493
355 boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) | 494 boot_swapboot = (au_readl(MEM_STSTAT) & (0x7 << 1)) | ((bcsr->status >> 6) & 0x1);
356 ((bcsr->status >> 6) & 0x1);
357 switch (boot_swapboot) { 495 switch (boot_swapboot) {
358 case 0: 496 case 0:
359 case 2: 497 case 2:
360 case 8: 498 case 8:
361 case 0xC: 499 case 0xC:
362 case 0xD: 500 case 0xD:
363 /* x16 NAND Flash */ 501 /* x16 NAND Flash */
364 nand_width = 0; 502 nand_width = 0;
365 break; 503 break;
366 case 1: 504 case 1:
367 case 9: 505 case 9:
368 case 3: 506 case 3:
369 case 0xE: 507 case 0xE:
370 case 0xF: 508 case 0xF:
371 /* x8 NAND Flash */ 509 /* x8 NAND Flash */
372 nand_width = 1; 510 nand_width = 1;
373 break; 511 break;
374 default: 512 default:
375 printk("Pb1550 NAND: bad boot:swap\n"); 513 printk("Pb1550 NAND: bad boot:swap\n");
376 retval = -EINVAL; 514 retval = -EINVAL;
377 goto outmem; 515 goto outmem;
378 } 516 }
379#endif 517#endif
380 518
@@ -424,18 +562,20 @@ int __init au1xxx_nand_init (void)
424 562
425 /* make controller and MTD agree */ 563 /* make controller and MTD agree */
426 if (NAND_CS == 0) 564 if (NAND_CS == 0)
427 nand_width = au_readl(MEM_STCFG0) & (1<<22); 565 nand_width = au_readl(MEM_STCFG0) & (1 << 22);
428 if (NAND_CS == 1) 566 if (NAND_CS == 1)
429 nand_width = au_readl(MEM_STCFG1) & (1<<22); 567 nand_width = au_readl(MEM_STCFG1) & (1 << 22);
430 if (NAND_CS == 2) 568 if (NAND_CS == 2)
431 nand_width = au_readl(MEM_STCFG2) & (1<<22); 569 nand_width = au_readl(MEM_STCFG2) & (1 << 22);
432 if (NAND_CS == 3) 570 if (NAND_CS == 3)
433 nand_width = au_readl(MEM_STCFG3) & (1<<22); 571 nand_width = au_readl(MEM_STCFG3) & (1 << 22);
434
435 572
436 /* Set address of hardware control function */ 573 /* Set address of hardware control function */
437 this->hwcontrol = au1550_hwcontrol; 574 this->hwcontrol = au1550_hwcontrol;
438 this->dev_ready = au1550_device_ready; 575 this->dev_ready = au1550_device_ready;
576 this->select_chip = au1550_select_chip;
577 this->cmdfunc = au1550_command;
578
439 /* 30 us command delay time */ 579 /* 30 us command delay time */
440 this->chip_delay = 30; 580 this->chip_delay = 30;
441 this->eccmode = NAND_ECC_SOFT; 581 this->eccmode = NAND_ECC_SOFT;
@@ -454,7 +594,7 @@ int __init au1xxx_nand_init (void)
454 this->verify_buf = (!nand_width) ? au_verify_buf16 : au_verify_buf; 594 this->verify_buf = (!nand_width) ? au_verify_buf16 : au_verify_buf;
455 595
456 /* Scan to find existence of the device */ 596 /* Scan to find existence of the device */
457 if (nand_scan (au1550_mtd, 1)) { 597 if (nand_scan(au1550_mtd, 1)) {
458 retval = -ENXIO; 598 retval = -ENXIO;
459 goto outio; 599 goto outio;
460 } 600 }
@@ -465,10 +605,10 @@ int __init au1xxx_nand_init (void)
465 return 0; 605 return 0;
466 606
467 outio: 607 outio:
468 iounmap ((void *)p_nand); 608 iounmap((void *)p_nand);
469 609
470 outmem: 610 outmem:
471 kfree (au1550_mtd); 611 kfree(au1550_mtd);
472 return retval; 612 return retval;
473} 613}
474 614
@@ -477,22 +617,21 @@ module_init(au1xxx_nand_init);
477/* 617/*
478 * Clean up routine 618 * Clean up routine
479 */ 619 */
480#ifdef MODULE 620static void __exit au1550_cleanup(void)
481static void __exit au1550_cleanup (void)
482{ 621{
483 struct nand_chip *this = (struct nand_chip *) &au1550_mtd[1]; 622 struct nand_chip *this = (struct nand_chip *)&au1550_mtd[1];
484 623
485 /* Release resources, unregister device */ 624 /* Release resources, unregister device */
486 nand_release (au1550_mtd); 625 nand_release(au1550_mtd);
487 626
488 /* Free the MTD device structure */ 627 /* Free the MTD device structure */
489 kfree (au1550_mtd); 628 kfree(au1550_mtd);
490 629
491 /* Unmap */ 630 /* Unmap */
492 iounmap ((void *)p_nand); 631 iounmap((void *)p_nand);
493} 632}
633
494module_exit(au1550_cleanup); 634module_exit(au1550_cleanup);
495#endif
496 635
497MODULE_LICENSE("GPL"); 636MODULE_LICENSE("GPL");
498MODULE_AUTHOR("Embedded Edge, LLC"); 637MODULE_AUTHOR("Embedded Edge, LLC");