aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/au1550nd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/au1550nd.c')
-rw-r--r--drivers/mtd/nand/au1550nd.c165
1 files changed, 94 insertions, 71 deletions
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index 4c7719ce3f48..3cafcdf28aed 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.13 2005/11/07 11:14:30 gleixner 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,20 +21,14 @@
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
34#include <asm/pb1550.h> 28#include <asm/pb1550.h>
35#endif 29#endif
36#ifdef CONFIG_MIPS_DB1550 30#ifdef CONFIG_MIPS_DB1550
37#include <asm/db1x00.h> 31#include <asm/db1x00.h>
38#endif 32#endif
39#endif 33#endif
40 34
@@ -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 46 {
55#define NUM_PARTITIONS 2 47 .name = "NAND FS 0",
56 {
57 .name = "Pb1550 NAND FS 0",
58 .offset = 0, 48 .offset = 0,
59 .size = 8*1024*1024 49 .size = 8*1024*1024
60 }, 50 },
61 { 51 {
62 .name = "Pb1550 NAND FS 1", 52 .name = "NAND FS 1",
63 .offset = MTDPART_OFS_APPEND, 53 .offset = MTDPART_OFS_APPEND,
64 .size = MTDPART_SIZ_FULL 54 .size = MTDPART_SIZ_FULL
65 } 55 }
66#endif
67#ifdef CONFIG_MIPS_DB1550
68#define NUM_PARTITIONS 2
69 {
70 .name = "Db1550 NAND FS 0",
71 .offset = 0,
72 .size = 8*1024*1024
73 },
74 {
75 .name = "Db1550 NAND FS 1",
76 .offset = MTDPART_OFS_APPEND,
77 .size = MTDPART_SIZ_FULL
78 }
79#endif
80}; 56};
57#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
81 58
82 59
83/** 60/**
@@ -112,7 +89,7 @@ static void au_write_byte(struct mtd_info *mtd, u_char byte)
112 * au_read_byte16 - read one byte endianess aware from the chip 89 * au_read_byte16 - read one byte endianess aware from the chip
113 * @mtd: MTD device structure 90 * @mtd: MTD device structure
114 * 91 *
115 * read function for 16bit buswith with 92 * read function for 16bit buswith with
116 * endianess conversion 93 * endianess conversion
117 */ 94 */
118static u_char au_read_byte16(struct mtd_info *mtd) 95static u_char au_read_byte16(struct mtd_info *mtd)
@@ -142,7 +119,7 @@ static void au_write_byte16(struct mtd_info *mtd, u_char byte)
142 * au_read_word - read one word from the chip 119 * au_read_word - read one word from the chip
143 * @mtd: MTD device structure 120 * @mtd: MTD device structure
144 * 121 *
145 * read function for 16bit buswith without 122 * read function for 16bit buswith without
146 * endianess conversion 123 * endianess conversion
147 */ 124 */
148static u16 au_read_word(struct mtd_info *mtd) 125static u16 au_read_word(struct mtd_info *mtd)
@@ -158,7 +135,7 @@ static u16 au_read_word(struct mtd_info *mtd)
158 * @mtd: MTD device structure 135 * @mtd: MTD device structure
159 * @word: data word to write 136 * @word: data word to write
160 * 137 *
161 * write function for 16bit buswith without 138 * write function for 16bit buswith without
162 * endianess conversion 139 * endianess conversion
163 */ 140 */
164static void au_write_word(struct mtd_info *mtd, u16 word) 141static void au_write_word(struct mtd_info *mtd, u16 word)
@@ -188,7 +165,7 @@ static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
188} 165}
189 166
190/** 167/**
191 * au_read_buf - read chip data into buffer 168 * au_read_buf - read chip data into buffer
192 * @mtd: MTD device structure 169 * @mtd: MTD device structure
193 * @buf: buffer to store date 170 * @buf: buffer to store date
194 * @len: number of bytes to read 171 * @len: number of bytes to read
@@ -202,12 +179,12 @@ static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
202 179
203 for (i=0; i<len; i++) { 180 for (i=0; i<len; i++) {
204 buf[i] = readb(this->IO_ADDR_R); 181 buf[i] = readb(this->IO_ADDR_R);
205 au_sync(); 182 au_sync();
206 } 183 }
207} 184}
208 185
209/** 186/**
210 * au_verify_buf - Verify chip data against buffer 187 * au_verify_buf - Verify chip data against buffer
211 * @mtd: MTD device structure 188 * @mtd: MTD device structure
212 * @buf: buffer containing the data to compare 189 * @buf: buffer containing the data to compare
213 * @len: number of bytes to compare 190 * @len: number of bytes to compare
@@ -242,16 +219,16 @@ static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
242 struct nand_chip *this = mtd->priv; 219 struct nand_chip *this = mtd->priv;
243 u16 *p = (u16 *) buf; 220 u16 *p = (u16 *) buf;
244 len >>= 1; 221 len >>= 1;
245 222
246 for (i=0; i<len; i++) { 223 for (i=0; i<len; i++) {
247 writew(p[i], this->IO_ADDR_W); 224 writew(p[i], this->IO_ADDR_W);
248 au_sync(); 225 au_sync();
249 } 226 }
250 227
251} 228}
252 229
253/** 230/**
254 * au_read_buf16 - read chip data into buffer 231 * au_read_buf16 - read chip data into buffer
255 * @mtd: MTD device structure 232 * @mtd: MTD device structure
256 * @buf: buffer to store date 233 * @buf: buffer to store date
257 * @len: number of bytes to read 234 * @len: number of bytes to read
@@ -272,7 +249,7 @@ static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
272} 249}
273 250
274/** 251/**
275 * au_verify_buf16 - Verify chip data against buffer 252 * au_verify_buf16 - Verify chip data against buffer
276 * @mtd: MTD device structure 253 * @mtd: MTD device structure
277 * @buf: buffer containing the data to compare 254 * @buf: buffer containing the data to compare
278 * @len: number of bytes to compare 255 * @len: number of bytes to compare
@@ -305,26 +282,26 @@ static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
305 case NAND_CTL_CLRCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; break; 282 case NAND_CTL_CLRCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; break;
306 283
307 case NAND_CTL_SETALE: this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR; break; 284 case NAND_CTL_SETALE: this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR; break;
308 case NAND_CTL_CLRALE: 285 case NAND_CTL_CLRALE:
309 this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; 286 this->IO_ADDR_W = p_nand + MEM_STNAND_DATA;
310 /* FIXME: Nobody knows why this is neccecary, 287 /* FIXME: Nobody knows why this is neccecary,
311 * but it works only that way */ 288 * but it works only that way */
312 udelay(1); 289 udelay(1);
313 break; 290 break;
314 291
315 case NAND_CTL_SETNCE: 292 case NAND_CTL_SETNCE:
316 /* assert (force assert) chip enable */ 293 /* assert (force assert) chip enable */
317 au_writel((1<<(4+NAND_CS)) , MEM_STNDCTL); break; 294 au_writel((1<<(4+NAND_CS)) , MEM_STNDCTL); break;
318 break; 295 break;
319 296
320 case NAND_CTL_CLRNCE: 297 case NAND_CTL_CLRNCE:
321 /* deassert chip enable */ 298 /* deassert chip enable */
322 au_writel(0, MEM_STNDCTL); break; 299 au_writel(0, MEM_STNDCTL); break;
323 break; 300 break;
324 } 301 }
325 302
326 this->IO_ADDR_R = this->IO_ADDR_W; 303 this->IO_ADDR_R = this->IO_ADDR_W;
327 304
328 /* Drain the writebuffer */ 305 /* Drain the writebuffer */
329 au_sync(); 306 au_sync();
330} 307}
@@ -339,14 +316,16 @@ 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) +
350 sizeof (struct nand_chip), GFP_KERNEL); 329 sizeof (struct nand_chip), GFP_KERNEL);
351 if (!au1550_mtd) { 330 if (!au1550_mtd) {
352 printk ("Unable to allocate NAND MTD dev structure.\n"); 331 printk ("Unable to allocate NAND MTD dev structure.\n");
@@ -364,14 +343,17 @@ 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 */
372 au_writel(au_readl(GPIO2_DIR) & ~(1<<6), GPIO2_DIR); 354 au_writel(au_readl(GPIO2_DIR) & ~(1<<6), GPIO2_DIR);
373 355
374 boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) | 356 boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) |
375 ((bcsr->status >> 6) & 0x1); 357 ((bcsr->status >> 6) & 0x1);
376 switch (boot_swapboot) { 358 switch (boot_swapboot) {
377 case 0: 359 case 0:
@@ -397,25 +379,66 @@ 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
404 405
405 /* setup and enable chip select, MEM_STADDR1 */ 406 /* Locate NAND chip-select in order to determine NAND phys address */
406 /* we really need to decode offsets only up till 0x20 */ 407 mem_staddr = 0x00000000;
407 au_writel((1<<28) | (NAND_PHYS_ADDR>>4) | 408 if (((au_readl(MEM_STCFG0) & 0x7) == 0x5) && (NAND_CS == 0))
408 (((NAND_PHYS_ADDR + 0x1000)-1) & (0x3fff<<18)>>18), 409 mem_staddr = au_readl(MEM_STADDR0);
409 MEM_STADDR1); 410 else if (((au_readl(MEM_STCFG1) & 0x7) == 0x5) && (NAND_CS == 1))
410 au_sync(); 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;
423
424 p_nand = (void __iomem *)ioremap(nand_phys, 0x1000);
425
426 /* make controller and MTD agree */
427 if (NAND_CS == 0)
428 nand_width = au_readl(MEM_STCFG0) & (1<<22);
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;
416 this->dev_ready = au1550_device_ready; 439 this->dev_ready = au1550_device_ready;
417 /* 30 us command delay time */ 440 /* 30 us command delay time */
418 this->chip_delay = 30; 441 this->chip_delay = 30;
419 this->eccmode = NAND_ECC_SOFT; 442 this->eccmode = NAND_ECC_SOFT;
420 443
421 this->options = NAND_NO_AUTOINCR; 444 this->options = NAND_NO_AUTOINCR;
@@ -438,19 +461,19 @@ 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
445 outio: 468 outio:
446 iounmap ((void *)p_nand); 469 iounmap ((void *)p_nand);
447 470
448 outmem: 471 outmem:
449 kfree (au1550_mtd); 472 kfree (au1550_mtd);
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