aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/nand/Kconfig6
-rw-r--r--drivers/mtd/nand/au1550nd.c115
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
4menu "NAND Flash Device Drivers" 4menu "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
61config MTD_NAND_AU1550 61config 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;
45static void __iomem *p_nand; 39static void __iomem *p_nand;
46static int nand_width = 1; /* default x8*/ 40static 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 */
53const static struct mtd_partition partition_info[] = { 45const 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 */
342int __init au1550_init (void) 319int __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
453module_init(au1550_init); 476module_init(au1xxx_nand_init);
454 477
455/* 478/*
456 * Clean up routine 479 * Clean up routine