diff options
Diffstat (limited to 'drivers/mtd/nand/au1550nd.c')
-rw-r--r-- | drivers/mtd/nand/au1550nd.c | 165 |
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; | |||
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 | 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 | */ |
118 | static u_char au_read_byte16(struct mtd_info *mtd) | 95 | static 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 | */ |
148 | static u16 au_read_word(struct mtd_info *mtd) | 125 | static 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 | */ |
164 | static void au_write_word(struct mtd_info *mtd, u16 word) | 141 | static 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 | */ |
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) + |
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 | ||
453 | module_init(au1550_init); | 476 | module_init(au1xxx_nand_init); |
454 | 477 | ||
455 | /* | 478 | /* |
456 | * Clean up routine | 479 | * Clean up routine |