diff options
-rw-r--r-- | drivers/mtd/nand/Kconfig | 6 | ||||
-rw-r--r-- | drivers/mtd/nand/au1550nd.c | 115 |
2 files changed, 72 insertions, 49 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 36d34e5e5a5a..435739d4b297 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -1,5 +1,5 @@ | |||
1 | # drivers/mtd/nand/Kconfig | 1 | # drivers/mtd/nand/Kconfig |
2 | # $Id: Kconfig,v 1.31 2005/06/20 12:03:21 bjd Exp $ | 2 | # $Id: Kconfig,v 1.34 2005/09/23 01:44:55 ppopov Exp $ |
3 | 3 | ||
4 | menu "NAND Flash Device Drivers" | 4 | menu "NAND Flash Device Drivers" |
5 | depends on MTD!=n | 5 | depends on MTD!=n |
@@ -59,8 +59,8 @@ config MTD_NAND_IDS | |||
59 | tristate | 59 | tristate |
60 | 60 | ||
61 | config MTD_NAND_AU1550 | 61 | config MTD_NAND_AU1550 |
62 | tristate "Au1550 NAND support" | 62 | tristate "Au1550/1200 NAND support" |
63 | depends on SOC_AU1550 && MTD_NAND | 63 | depends on (SOC_AU1200 || SOC_AU1550) && MTD_NAND |
64 | help | 64 | help |
65 | This enables the driver for the NAND flash controller on the | 65 | This enables the driver for the NAND flash controller on the |
66 | AMD/Alchemy 1550 SOC. | 66 | AMD/Alchemy 1550 SOC. |
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 4c7719ce3f48..953daf379b9b 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2004 Embedded Edge, LLC | 4 | * Copyright (C) 2004 Embedded Edge, LLC |
5 | * | 5 | * |
6 | * $Id: au1550nd.c,v 1.11 2004/11/04 12:53:10 gleixner Exp $ | 6 | * $Id: au1550nd.c,v 1.12 2005/09/23 01:44:55 ppopov Exp $ |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -21,13 +21,7 @@ | |||
21 | 21 | ||
22 | /* fixme: this is ugly */ | 22 | /* fixme: this is ugly */ |
23 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 0) | 23 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 0) |
24 | #include <asm/mach-au1x00/au1000.h> | 24 | #include <asm/mach-au1x00/au1xxx.h> |
25 | #ifdef CONFIG_MIPS_PB1550 | ||
26 | #include <asm/mach-pb1x00/pb1550.h> | ||
27 | #endif | ||
28 | #ifdef CONFIG_MIPS_DB1550 | ||
29 | #include <asm/mach-db1x00/db1x00.h> | ||
30 | #endif | ||
31 | #else | 25 | #else |
32 | #include <asm/au1000.h> | 26 | #include <asm/au1000.h> |
33 | #ifdef CONFIG_MIPS_PB1550 | 27 | #ifdef CONFIG_MIPS_PB1550 |
@@ -45,39 +39,22 @@ static struct mtd_info *au1550_mtd = NULL; | |||
45 | static void __iomem *p_nand; | 39 | static void __iomem *p_nand; |
46 | static int nand_width = 1; /* default x8*/ | 40 | static int nand_width = 1; /* default x8*/ |
47 | 41 | ||
48 | #define NAND_CS 1 | ||
49 | |||
50 | /* | 42 | /* |
51 | * Define partitions for flash device | 43 | * Define partitions for flash device |
52 | */ | 44 | */ |
53 | const static struct mtd_partition partition_info[] = { | 45 | const static struct mtd_partition partition_info[] = { |
54 | #ifdef CONFIG_MIPS_PB1550 | ||
55 | #define NUM_PARTITIONS 2 | ||
56 | { | ||
57 | .name = "Pb1550 NAND FS 0", | ||
58 | .offset = 0, | ||
59 | .size = 8*1024*1024 | ||
60 | }, | ||
61 | { | ||
62 | .name = "Pb1550 NAND FS 1", | ||
63 | .offset = MTDPART_OFS_APPEND, | ||
64 | .size = MTDPART_SIZ_FULL | ||
65 | } | ||
66 | #endif | ||
67 | #ifdef CONFIG_MIPS_DB1550 | ||
68 | #define NUM_PARTITIONS 2 | ||
69 | { | 46 | { |
70 | .name = "Db1550 NAND FS 0", | 47 | .name = "NAND FS 0", |
71 | .offset = 0, | 48 | .offset = 0, |
72 | .size = 8*1024*1024 | 49 | .size = 8*1024*1024 |
73 | }, | 50 | }, |
74 | { | 51 | { |
75 | .name = "Db1550 NAND FS 1", | 52 | .name = "NAND FS 1", |
76 | .offset = MTDPART_OFS_APPEND, | 53 | .offset = MTDPART_OFS_APPEND, |
77 | .size = MTDPART_SIZ_FULL | 54 | .size = MTDPART_SIZ_FULL |
78 | } | 55 | } |
79 | #endif | ||
80 | }; | 56 | }; |
57 | #define NB_OF(x) (sizeof(x)/sizeof(x[0])) | ||
81 | 58 | ||
82 | 59 | ||
83 | /** | 60 | /** |
@@ -339,11 +316,13 @@ int au1550_device_ready(struct mtd_info *mtd) | |||
339 | /* | 316 | /* |
340 | * Main initialization routine | 317 | * Main initialization routine |
341 | */ | 318 | */ |
342 | int __init au1550_init (void) | 319 | int __init au1xxx_nand_init (void) |
343 | { | 320 | { |
344 | struct nand_chip *this; | 321 | struct nand_chip *this; |
345 | u16 boot_swapboot = 0; /* default value */ | 322 | u16 boot_swapboot = 0; /* default value */ |
346 | int retval; | 323 | int retval; |
324 | u32 mem_staddr; | ||
325 | u32 nand_phys; | ||
347 | 326 | ||
348 | /* Allocate memory for MTD device structure and private data */ | 327 | /* Allocate memory for MTD device structure and private data */ |
349 | au1550_mtd = kmalloc (sizeof(struct mtd_info) + | 328 | au1550_mtd = kmalloc (sizeof(struct mtd_info) + |
@@ -364,8 +343,11 @@ int __init au1550_init (void) | |||
364 | au1550_mtd->priv = this; | 343 | au1550_mtd->priv = this; |
365 | 344 | ||
366 | 345 | ||
367 | /* MEM_STNDCTL: disable ints, disable nand boot */ | 346 | /* disable interrupts */ |
368 | au_writel(0, MEM_STNDCTL); | 347 | au_writel(au_readl(MEM_STNDCTL) & ~(1<<8), MEM_STNDCTL); |
348 | |||
349 | /* disable NAND boot */ | ||
350 | au_writel(au_readl(MEM_STNDCTL) & ~(1<<0), MEM_STNDCTL); | ||
369 | 351 | ||
370 | #ifdef CONFIG_MIPS_PB1550 | 352 | #ifdef CONFIG_MIPS_PB1550 |
371 | /* set gpio206 high */ | 353 | /* set gpio206 high */ |
@@ -397,19 +379,60 @@ int __init au1550_init (void) | |||
397 | } | 379 | } |
398 | #endif | 380 | #endif |
399 | 381 | ||
400 | /* Configure RCE1 - should be done by YAMON */ | 382 | /* Configure chip-select; normally done by boot code, e.g. YAMON */ |
401 | au_writel(0x5 | (nand_width << 22), 0xB4001010); /* MEM_STCFG1 */ | 383 | #ifdef NAND_STCFG |
402 | au_writel(NAND_TIMING, 0xB4001014); /* MEM_STTIME1 */ | 384 | if (NAND_CS == 0) { |
403 | au_sync(); | 385 | au_writel(NAND_STCFG, MEM_STCFG0); |
386 | au_writel(NAND_STTIME, MEM_STTIME0); | ||
387 | au_writel(NAND_STADDR, MEM_STADDR0); | ||
388 | } | ||
389 | if (NAND_CS == 1) { | ||
390 | au_writel(NAND_STCFG, MEM_STCFG1); | ||
391 | au_writel(NAND_STTIME, MEM_STTIME1); | ||
392 | au_writel(NAND_STADDR, MEM_STADDR1); | ||
393 | } | ||
394 | if (NAND_CS == 2) { | ||
395 | au_writel(NAND_STCFG, MEM_STCFG2); | ||
396 | au_writel(NAND_STTIME, MEM_STTIME2); | ||
397 | au_writel(NAND_STADDR, MEM_STADDR2); | ||
398 | } | ||
399 | if (NAND_CS == 3) { | ||
400 | au_writel(NAND_STCFG, MEM_STCFG3); | ||
401 | au_writel(NAND_STTIME, MEM_STTIME3); | ||
402 | au_writel(NAND_STADDR, MEM_STADDR3); | ||
403 | } | ||
404 | #endif | ||
405 | |||
406 | /* Locate NAND chip-select in order to determine NAND phys address */ | ||
407 | mem_staddr = 0x00000000; | ||
408 | if (((au_readl(MEM_STCFG0) & 0x7) == 0x5) && (NAND_CS == 0)) | ||
409 | mem_staddr = au_readl(MEM_STADDR0); | ||
410 | else if (((au_readl(MEM_STCFG1) & 0x7) == 0x5) && (NAND_CS == 1)) | ||
411 | mem_staddr = au_readl(MEM_STADDR1); | ||
412 | else if (((au_readl(MEM_STCFG2) & 0x7) == 0x5) && (NAND_CS == 2)) | ||
413 | mem_staddr = au_readl(MEM_STADDR2); | ||
414 | else if (((au_readl(MEM_STCFG3) & 0x7) == 0x5) && (NAND_CS == 3)) | ||
415 | mem_staddr = au_readl(MEM_STADDR3); | ||
416 | |||
417 | if (mem_staddr == 0x00000000) { | ||
418 | printk("Au1xxx NAND: ERROR WITH NAND CHIP-SELECT\n"); | ||
419 | kfree(au1550_mtd); | ||
420 | return 1; | ||
421 | } | ||
422 | nand_phys = (mem_staddr << 4) & 0xFFFC0000; | ||
404 | 423 | ||
405 | /* setup and enable chip select, MEM_STADDR1 */ | 424 | p_nand = (void __iomem *)ioremap(nand_phys, 0x1000); |
406 | /* we really need to decode offsets only up till 0x20 */ | 425 | |
407 | au_writel((1<<28) | (NAND_PHYS_ADDR>>4) | | 426 | /* make controller and MTD agree */ |
408 | (((NAND_PHYS_ADDR + 0x1000)-1) & (0x3fff<<18)>>18), | 427 | if (NAND_CS == 0) |
409 | MEM_STADDR1); | 428 | nand_width = au_readl(MEM_STCFG0) & (1<<22); |
410 | au_sync(); | 429 | if (NAND_CS == 1) |
430 | nand_width = au_readl(MEM_STCFG1) & (1<<22); | ||
431 | if (NAND_CS == 2) | ||
432 | nand_width = au_readl(MEM_STCFG2) & (1<<22); | ||
433 | if (NAND_CS == 3) | ||
434 | nand_width = au_readl(MEM_STCFG3) & (1<<22); | ||
411 | 435 | ||
412 | p_nand = ioremap(NAND_PHYS_ADDR, 0x1000); | ||
413 | 436 | ||
414 | /* Set address of hardware control function */ | 437 | /* Set address of hardware control function */ |
415 | this->hwcontrol = au1550_hwcontrol; | 438 | this->hwcontrol = au1550_hwcontrol; |
@@ -438,7 +461,7 @@ int __init au1550_init (void) | |||
438 | } | 461 | } |
439 | 462 | ||
440 | /* Register the partitions */ | 463 | /* Register the partitions */ |
441 | add_mtd_partitions(au1550_mtd, partition_info, NUM_PARTITIONS); | 464 | add_mtd_partitions(au1550_mtd, partition_info, NB_OF(partition_info)); |
442 | 465 | ||
443 | return 0; | 466 | return 0; |
444 | 467 | ||
@@ -450,7 +473,7 @@ int __init au1550_init (void) | |||
450 | return retval; | 473 | return retval; |
451 | } | 474 | } |
452 | 475 | ||
453 | module_init(au1550_init); | 476 | module_init(au1xxx_nand_init); |
454 | 477 | ||
455 | /* | 478 | /* |
456 | * Clean up routine | 479 | * Clean up routine |