diff options
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r-- | drivers/mtd/nand/Kconfig | 26 | ||||
-rw-r--r-- | drivers/mtd/nand/au1550nd.c | 165 | ||||
-rw-r--r-- | drivers/mtd/nand/autcpu12.c | 22 | ||||
-rw-r--r-- | drivers/mtd/nand/diskonchip.c | 100 | ||||
-rw-r--r-- | drivers/mtd/nand/edb7312.c | 48 | ||||
-rw-r--r-- | drivers/mtd/nand/h1910.c | 48 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 529 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_bbt.c | 248 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_ecc.c | 44 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_ids.c | 30 | ||||
-rw-r--r-- | drivers/mtd/nand/nandsim.c | 162 | ||||
-rw-r--r-- | drivers/mtd/nand/ppchameleonevb.c | 6 | ||||
-rw-r--r-- | drivers/mtd/nand/rtc_from4.c | 58 | ||||
-rw-r--r-- | drivers/mtd/nand/s3c2410.c | 61 | ||||
-rw-r--r-- | drivers/mtd/nand/sharpsl.c | 41 | ||||
-rw-r--r-- | drivers/mtd/nand/spia.c | 6 | ||||
-rw-r--r-- | drivers/mtd/nand/toto.c | 20 |
17 files changed, 849 insertions, 765 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 36d34e5e5a5a..1fc4c134d939 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.35 2005/11/07 11:14:30 gleixner 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 |
@@ -25,33 +25,33 @@ config MTD_NAND_VERIFY_WRITE | |||
25 | 25 | ||
26 | config MTD_NAND_AUTCPU12 | 26 | config MTD_NAND_AUTCPU12 |
27 | tristate "SmartMediaCard on autronix autcpu12 board" | 27 | tristate "SmartMediaCard on autronix autcpu12 board" |
28 | depends on ARM && MTD_NAND && ARCH_AUTCPU12 | 28 | depends on MTD_NAND && ARCH_AUTCPU12 |
29 | help | 29 | help |
30 | This enables the driver for the autronix autcpu12 board to | 30 | This enables the driver for the autronix autcpu12 board to |
31 | access the SmartMediaCard. | 31 | access the SmartMediaCard. |
32 | 32 | ||
33 | config MTD_NAND_EDB7312 | 33 | config MTD_NAND_EDB7312 |
34 | tristate "Support for Cirrus Logic EBD7312 evaluation board" | 34 | tristate "Support for Cirrus Logic EBD7312 evaluation board" |
35 | depends on ARM && MTD_NAND && ARCH_EDB7312 | 35 | depends on MTD_NAND && ARCH_EDB7312 |
36 | help | 36 | help |
37 | This enables the driver for the Cirrus Logic EBD7312 evaluation | 37 | This enables the driver for the Cirrus Logic EBD7312 evaluation |
38 | board to access the onboard NAND Flash. | 38 | board to access the onboard NAND Flash. |
39 | 39 | ||
40 | config MTD_NAND_H1900 | 40 | config MTD_NAND_H1900 |
41 | tristate "iPAQ H1900 flash" | 41 | tristate "iPAQ H1900 flash" |
42 | depends on ARM && MTD_NAND && ARCH_PXA && MTD_PARTITIONS | 42 | depends on MTD_NAND && ARCH_PXA && MTD_PARTITIONS |
43 | help | 43 | help |
44 | This enables the driver for the iPAQ h1900 flash. | 44 | This enables the driver for the iPAQ h1900 flash. |
45 | 45 | ||
46 | config MTD_NAND_SPIA | 46 | config MTD_NAND_SPIA |
47 | tristate "NAND Flash device on SPIA board" | 47 | tristate "NAND Flash device on SPIA board" |
48 | depends on ARM && ARCH_P720T && MTD_NAND | 48 | depends on ARCH_P720T && MTD_NAND |
49 | help | 49 | help |
50 | If you had to ask, you don't have one. Say 'N'. | 50 | If you had to ask, you don't have one. Say 'N'. |
51 | 51 | ||
52 | config MTD_NAND_TOTO | 52 | config MTD_NAND_TOTO |
53 | tristate "NAND Flash device on TOTO board" | 53 | tristate "NAND Flash device on TOTO board" |
54 | depends on ARM && ARCH_OMAP && MTD_NAND | 54 | depends on ARCH_OMAP && MTD_NAND |
55 | help | 55 | help |
56 | Support for NAND flash on Texas Instruments Toto platform. | 56 | Support for NAND flash on Texas Instruments Toto platform. |
57 | 57 | ||
@@ -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. |
@@ -71,7 +71,7 @@ config MTD_NAND_RTC_FROM4 | |||
71 | select REED_SOLOMON | 71 | select REED_SOLOMON |
72 | select REED_SOLOMON_DEC8 | 72 | select REED_SOLOMON_DEC8 |
73 | help | 73 | help |
74 | This enables the driver for the Renesas Technology AG-AND | 74 | This enables the driver for the Renesas Technology AG-AND |
75 | flash interface board (FROM_BOARD4) | 75 | flash interface board (FROM_BOARD4) |
76 | 76 | ||
77 | config MTD_NAND_PPCHAMELEONEVB | 77 | config MTD_NAND_PPCHAMELEONEVB |
@@ -88,7 +88,7 @@ config MTD_NAND_S3C2410 | |||
88 | SoCs | 88 | SoCs |
89 | 89 | ||
90 | No board specfic support is done by this driver, each board | 90 | No board specfic support is done by this driver, each board |
91 | must advertise a platform_device for the driver to attach. | 91 | must advertise a platform_device for the driver to attach. |
92 | 92 | ||
93 | config MTD_NAND_S3C2410_DEBUG | 93 | config MTD_NAND_S3C2410_DEBUG |
94 | bool "S3C2410 NAND driver debug" | 94 | bool "S3C2410 NAND driver debug" |
@@ -181,7 +181,7 @@ config MTD_NAND_DISKONCHIP_BBTWRITE | |||
181 | 181 | ||
182 | config MTD_NAND_SHARPSL | 182 | config MTD_NAND_SHARPSL |
183 | bool "Support for NAND Flash on Sharp SL Series (C7xx + others)" | 183 | bool "Support for NAND Flash on Sharp SL Series (C7xx + others)" |
184 | depends on MTD_NAND && ARCH_PXA | 184 | depends on MTD_NAND && ARCH_PXA |
185 | 185 | ||
186 | config MTD_NAND_NANDSIM | 186 | config MTD_NAND_NANDSIM |
187 | bool "Support for NAND Flash Simulator" | 187 | bool "Support for NAND Flash Simulator" |
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 |
diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c index 4afa8ced05ad..056dfc17a075 100644 --- a/drivers/mtd/nand/autcpu12.c +++ b/drivers/mtd/nand/autcpu12.c | |||
@@ -5,8 +5,8 @@ | |||
5 | * | 5 | * |
6 | * Derived from drivers/mtd/spia.c | 6 | * Derived from drivers/mtd/spia.c |
7 | * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) | 7 | * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) |
8 | * | 8 | * |
9 | * $Id: autcpu12.c,v 1.22 2004/11/04 12:53:10 gleixner Exp $ | 9 | * $Id: autcpu12.c,v 1.23 2005/11/07 11:14:30 gleixner Exp $ |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2 as | 12 | * it under the terms of the GNU General Public License version 2 as |
@@ -14,7 +14,7 @@ | |||
14 | * | 14 | * |
15 | * Overview: | 15 | * Overview: |
16 | * This is a device driver for the NAND flash device found on the | 16 | * This is a device driver for the NAND flash device found on the |
17 | * autronix autcpu12 board, which is a SmartMediaCard. It supports | 17 | * autronix autcpu12 board, which is a SmartMediaCard. It supports |
18 | * 16MiB, 32MiB and 64MiB cards. | 18 | * 16MiB, 32MiB and 64MiB cards. |
19 | * | 19 | * |
20 | * | 20 | * |
@@ -93,7 +93,7 @@ static struct mtd_partition partition_info128k[] = { | |||
93 | #define NUM_PARTITIONS32K 2 | 93 | #define NUM_PARTITIONS32K 2 |
94 | #define NUM_PARTITIONS64K 2 | 94 | #define NUM_PARTITIONS64K 2 |
95 | #define NUM_PARTITIONS128K 2 | 95 | #define NUM_PARTITIONS128K 2 |
96 | /* | 96 | /* |
97 | * hardware specific access to control-lines | 97 | * hardware specific access to control-lines |
98 | */ | 98 | */ |
99 | static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd) | 99 | static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd) |
@@ -163,7 +163,7 @@ int __init autcpu12_init (void) | |||
163 | this->hwcontrol = autcpu12_hwcontrol; | 163 | this->hwcontrol = autcpu12_hwcontrol; |
164 | this->dev_ready = autcpu12_device_ready; | 164 | this->dev_ready = autcpu12_device_ready; |
165 | /* 20 us command delay time */ | 165 | /* 20 us command delay time */ |
166 | this->chip_delay = 20; | 166 | this->chip_delay = 20; |
167 | this->eccmode = NAND_ECC_SOFT; | 167 | this->eccmode = NAND_ECC_SOFT; |
168 | 168 | ||
169 | /* Enable the following for a flash based bad block table */ | 169 | /* Enable the following for a flash based bad block table */ |
@@ -171,21 +171,21 @@ int __init autcpu12_init (void) | |||
171 | this->options = NAND_USE_FLASH_BBT; | 171 | this->options = NAND_USE_FLASH_BBT; |
172 | */ | 172 | */ |
173 | this->options = NAND_USE_FLASH_BBT; | 173 | this->options = NAND_USE_FLASH_BBT; |
174 | 174 | ||
175 | /* Scan to find existance of the device */ | 175 | /* Scan to find existance of the device */ |
176 | if (nand_scan (autcpu12_mtd, 1)) { | 176 | if (nand_scan (autcpu12_mtd, 1)) { |
177 | err = -ENXIO; | 177 | err = -ENXIO; |
178 | goto out_ior; | 178 | goto out_ior; |
179 | } | 179 | } |
180 | 180 | ||
181 | /* Register the partitions */ | 181 | /* Register the partitions */ |
182 | switch(autcpu12_mtd->size){ | 182 | switch(autcpu12_mtd->size){ |
183 | case SZ_16M: add_mtd_partitions(autcpu12_mtd, partition_info16k, NUM_PARTITIONS16K); break; | 183 | case SZ_16M: add_mtd_partitions(autcpu12_mtd, partition_info16k, NUM_PARTITIONS16K); break; |
184 | case SZ_32M: add_mtd_partitions(autcpu12_mtd, partition_info32k, NUM_PARTITIONS32K); break; | 184 | case SZ_32M: add_mtd_partitions(autcpu12_mtd, partition_info32k, NUM_PARTITIONS32K); break; |
185 | case SZ_64M: add_mtd_partitions(autcpu12_mtd, partition_info64k, NUM_PARTITIONS64K); break; | 185 | case SZ_64M: add_mtd_partitions(autcpu12_mtd, partition_info64k, NUM_PARTITIONS64K); break; |
186 | case SZ_128M: add_mtd_partitions(autcpu12_mtd, partition_info128k, NUM_PARTITIONS128K); break; | 186 | case SZ_128M: add_mtd_partitions(autcpu12_mtd, partition_info128k, NUM_PARTITIONS128K); break; |
187 | default: { | 187 | default: { |
188 | printk ("Unsupported SmartMedia device\n"); | 188 | printk ("Unsupported SmartMedia device\n"); |
189 | err = -ENXIO; | 189 | err = -ENXIO; |
190 | goto out_ior; | 190 | goto out_ior; |
191 | } | 191 | } |
@@ -213,7 +213,7 @@ static void __exit autcpu12_cleanup (void) | |||
213 | 213 | ||
214 | /* unmap physical adress */ | 214 | /* unmap physical adress */ |
215 | iounmap((void *)autcpu12_fio_base); | 215 | iounmap((void *)autcpu12_fio_base); |
216 | 216 | ||
217 | /* Free the MTD device structure */ | 217 | /* Free the MTD device structure */ |
218 | kfree (autcpu12_mtd); | 218 | kfree (autcpu12_mtd); |
219 | } | 219 | } |
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index fdb5d4ad3d52..21d4e8f4b7af 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/mtd/nand/diskonchip.c | 2 | * drivers/mtd/nand/diskonchip.c |
3 | * | 3 | * |
4 | * (C) 2003 Red Hat, Inc. | 4 | * (C) 2003 Red Hat, Inc. |
@@ -8,15 +8,15 @@ | |||
8 | * Author: David Woodhouse <dwmw2@infradead.org> | 8 | * Author: David Woodhouse <dwmw2@infradead.org> |
9 | * Additional Diskonchip 2000 and Millennium support by Dan Brown <dan_brown@ieee.org> | 9 | * Additional Diskonchip 2000 and Millennium support by Dan Brown <dan_brown@ieee.org> |
10 | * Diskonchip Millennium Plus support by Kalev Lember <kalev@smartlink.ee> | 10 | * Diskonchip Millennium Plus support by Kalev Lember <kalev@smartlink.ee> |
11 | * | 11 | * |
12 | * Error correction code lifted from the old docecc code | 12 | * Error correction code lifted from the old docecc code |
13 | * Author: Fabrice Bellard (fabrice.bellard@netgem.com) | 13 | * Author: Fabrice Bellard (fabrice.bellard@netgem.com) |
14 | * Copyright (C) 2000 Netgem S.A. | 14 | * Copyright (C) 2000 Netgem S.A. |
15 | * converted to the generic Reed-Solomon library by Thomas Gleixner <tglx@linutronix.de> | 15 | * converted to the generic Reed-Solomon library by Thomas Gleixner <tglx@linutronix.de> |
16 | * | 16 | * |
17 | * Interface to generic NAND code for M-Systems DiskOnChip devices | 17 | * Interface to generic NAND code for M-Systems DiskOnChip devices |
18 | * | 18 | * |
19 | * $Id: diskonchip.c,v 1.54 2005/04/07 14:22:55 dbrown Exp $ | 19 | * $Id: diskonchip.c,v 1.55 2005/11/07 11:14:30 gleixner Exp $ |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
@@ -42,16 +42,16 @@ | |||
42 | static unsigned long __initdata doc_locations[] = { | 42 | static unsigned long __initdata doc_locations[] = { |
43 | #if defined (__alpha__) || defined(__i386__) || defined(__x86_64__) | 43 | #if defined (__alpha__) || defined(__i386__) || defined(__x86_64__) |
44 | #ifdef CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH | 44 | #ifdef CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH |
45 | 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, | 45 | 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, |
46 | 0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000, | 46 | 0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000, |
47 | 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, | 47 | 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, |
48 | 0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000, | 48 | 0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000, |
49 | 0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000, | 49 | 0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000, |
50 | #else /* CONFIG_MTD_DOCPROBE_HIGH */ | 50 | #else /* CONFIG_MTD_DOCPROBE_HIGH */ |
51 | 0xc8000, 0xca000, 0xcc000, 0xce000, | 51 | 0xc8000, 0xca000, 0xcc000, 0xce000, |
52 | 0xd0000, 0xd2000, 0xd4000, 0xd6000, | 52 | 0xd0000, 0xd2000, 0xd4000, 0xd6000, |
53 | 0xd8000, 0xda000, 0xdc000, 0xde000, | 53 | 0xd8000, 0xda000, 0xdc000, 0xde000, |
54 | 0xe0000, 0xe2000, 0xe4000, 0xe6000, | 54 | 0xe0000, 0xe2000, 0xe4000, 0xe6000, |
55 | 0xe8000, 0xea000, 0xec000, 0xee000, | 55 | 0xe8000, 0xea000, 0xec000, 0xee000, |
56 | #endif /* CONFIG_MTD_DOCPROBE_HIGH */ | 56 | #endif /* CONFIG_MTD_DOCPROBE_HIGH */ |
57 | #elif defined(__PPC__) | 57 | #elif defined(__PPC__) |
@@ -138,7 +138,7 @@ MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe | |||
138 | /* the Reed Solomon control structure */ | 138 | /* the Reed Solomon control structure */ |
139 | static struct rs_control *rs_decoder; | 139 | static struct rs_control *rs_decoder; |
140 | 140 | ||
141 | /* | 141 | /* |
142 | * The HW decoder in the DoC ASIC's provides us a error syndrome, | 142 | * The HW decoder in the DoC ASIC's provides us a error syndrome, |
143 | * which we must convert to a standard syndrom usable by the generic | 143 | * which we must convert to a standard syndrom usable by the generic |
144 | * Reed-Solomon library code. | 144 | * Reed-Solomon library code. |
@@ -163,8 +163,8 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) | |||
163 | /* Initialize the syndrom buffer */ | 163 | /* Initialize the syndrom buffer */ |
164 | for (i = 0; i < NROOTS; i++) | 164 | for (i = 0; i < NROOTS; i++) |
165 | s[i] = ds[0]; | 165 | s[i] = ds[0]; |
166 | /* | 166 | /* |
167 | * Evaluate | 167 | * Evaluate |
168 | * s[i] = ds[3]x^3 + ds[2]x^2 + ds[1]x^1 + ds[0] | 168 | * s[i] = ds[3]x^3 + ds[2]x^2 + ds[1]x^1 + ds[0] |
169 | * where x = alpha^(FCR + i) | 169 | * where x = alpha^(FCR + i) |
170 | */ | 170 | */ |
@@ -188,7 +188,7 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) | |||
188 | if (nerr < 0) | 188 | if (nerr < 0) |
189 | return nerr; | 189 | return nerr; |
190 | 190 | ||
191 | /* | 191 | /* |
192 | * Correct the errors. The bitpositions are a bit of magic, | 192 | * Correct the errors. The bitpositions are a bit of magic, |
193 | * but they are given by the design of the de/encoder circuit | 193 | * but they are given by the design of the de/encoder circuit |
194 | * in the DoC ASIC's. | 194 | * in the DoC ASIC's. |
@@ -205,7 +205,7 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) | |||
205 | can be modified since pos is even */ | 205 | can be modified since pos is even */ |
206 | index = (pos >> 3) ^ 1; | 206 | index = (pos >> 3) ^ 1; |
207 | bitpos = pos & 7; | 207 | bitpos = pos & 7; |
208 | if ((index >= 0 && index < SECTOR_SIZE) || | 208 | if ((index >= 0 && index < SECTOR_SIZE) || |
209 | index == (SECTOR_SIZE + 1)) { | 209 | index == (SECTOR_SIZE + 1)) { |
210 | val = (uint8_t) (errval[i] >> (2 + bitpos)); | 210 | val = (uint8_t) (errval[i] >> (2 + bitpos)); |
211 | parity ^= val; | 211 | parity ^= val; |
@@ -216,7 +216,7 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) | |||
216 | bitpos = (bitpos + 10) & 7; | 216 | bitpos = (bitpos + 10) & 7; |
217 | if (bitpos == 0) | 217 | if (bitpos == 0) |
218 | bitpos = 8; | 218 | bitpos = 8; |
219 | if ((index >= 0 && index < SECTOR_SIZE) || | 219 | if ((index >= 0 && index < SECTOR_SIZE) || |
220 | index == (SECTOR_SIZE + 1)) { | 220 | index == (SECTOR_SIZE + 1)) { |
221 | val = (uint8_t)(errval[i] << (8 - bitpos)); | 221 | val = (uint8_t)(errval[i] << (8 - bitpos)); |
222 | parity ^= val; | 222 | parity ^= val; |
@@ -233,7 +233,7 @@ static void DoC_Delay(struct doc_priv *doc, unsigned short cycles) | |||
233 | { | 233 | { |
234 | volatile char dummy; | 234 | volatile char dummy; |
235 | int i; | 235 | int i; |
236 | 236 | ||
237 | for (i = 0; i < cycles; i++) { | 237 | for (i = 0; i < cycles; i++) { |
238 | if (DoC_is_Millennium(doc)) | 238 | if (DoC_is_Millennium(doc)) |
239 | dummy = ReadDOC(doc->virtadr, NOP); | 239 | dummy = ReadDOC(doc->virtadr, NOP); |
@@ -242,7 +242,7 @@ static void DoC_Delay(struct doc_priv *doc, unsigned short cycles) | |||
242 | else | 242 | else |
243 | dummy = ReadDOC(doc->virtadr, DOCStatus); | 243 | dummy = ReadDOC(doc->virtadr, DOCStatus); |
244 | } | 244 | } |
245 | 245 | ||
246 | } | 246 | } |
247 | 247 | ||
248 | #define CDSN_CTRL_FR_B_MASK (CDSN_CTRL_FR_B0 | CDSN_CTRL_FR_B1) | 248 | #define CDSN_CTRL_FR_B_MASK (CDSN_CTRL_FR_B0 | CDSN_CTRL_FR_B1) |
@@ -327,7 +327,7 @@ static u_char doc2000_read_byte(struct mtd_info *mtd) | |||
327 | return ret; | 327 | return ret; |
328 | } | 328 | } |
329 | 329 | ||
330 | static void doc2000_writebuf(struct mtd_info *mtd, | 330 | static void doc2000_writebuf(struct mtd_info *mtd, |
331 | const u_char *buf, int len) | 331 | const u_char *buf, int len) |
332 | { | 332 | { |
333 | struct nand_chip *this = mtd->priv; | 333 | struct nand_chip *this = mtd->priv; |
@@ -343,7 +343,7 @@ static void doc2000_writebuf(struct mtd_info *mtd, | |||
343 | if (debug) printk("\n"); | 343 | if (debug) printk("\n"); |
344 | } | 344 | } |
345 | 345 | ||
346 | static void doc2000_readbuf(struct mtd_info *mtd, | 346 | static void doc2000_readbuf(struct mtd_info *mtd, |
347 | u_char *buf, int len) | 347 | u_char *buf, int len) |
348 | { | 348 | { |
349 | struct nand_chip *this = mtd->priv; | 349 | struct nand_chip *this = mtd->priv; |
@@ -358,7 +358,7 @@ static void doc2000_readbuf(struct mtd_info *mtd, | |||
358 | } | 358 | } |
359 | } | 359 | } |
360 | 360 | ||
361 | static void doc2000_readbuf_dword(struct mtd_info *mtd, | 361 | static void doc2000_readbuf_dword(struct mtd_info *mtd, |
362 | u_char *buf, int len) | 362 | u_char *buf, int len) |
363 | { | 363 | { |
364 | struct nand_chip *this = mtd->priv; | 364 | struct nand_chip *this = mtd->priv; |
@@ -379,7 +379,7 @@ static void doc2000_readbuf_dword(struct mtd_info *mtd, | |||
379 | } | 379 | } |
380 | } | 380 | } |
381 | 381 | ||
382 | static int doc2000_verifybuf(struct mtd_info *mtd, | 382 | static int doc2000_verifybuf(struct mtd_info *mtd, |
383 | const u_char *buf, int len) | 383 | const u_char *buf, int len) |
384 | { | 384 | { |
385 | struct nand_chip *this = mtd->priv; | 385 | struct nand_chip *this = mtd->priv; |
@@ -406,12 +406,12 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) | |||
406 | doc200x_hwcontrol(mtd, NAND_CTL_SETALE); | 406 | doc200x_hwcontrol(mtd, NAND_CTL_SETALE); |
407 | this->write_byte(mtd, 0); | 407 | this->write_byte(mtd, 0); |
408 | doc200x_hwcontrol(mtd, NAND_CTL_CLRALE); | 408 | doc200x_hwcontrol(mtd, NAND_CTL_CLRALE); |
409 | 409 | ||
410 | /* We cant' use dev_ready here, but at least we wait for the | 410 | /* We cant' use dev_ready here, but at least we wait for the |
411 | * command to complete | 411 | * command to complete |
412 | */ | 412 | */ |
413 | udelay(50); | 413 | udelay(50); |
414 | 414 | ||
415 | ret = this->read_byte(mtd) << 8; | 415 | ret = this->read_byte(mtd) << 8; |
416 | ret |= this->read_byte(mtd); | 416 | ret |= this->read_byte(mtd); |
417 | 417 | ||
@@ -438,7 +438,7 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) | |||
438 | this->read_buf = &doc2000_readbuf_dword; | 438 | this->read_buf = &doc2000_readbuf_dword; |
439 | } | 439 | } |
440 | } | 440 | } |
441 | 441 | ||
442 | return ret; | 442 | return ret; |
443 | } | 443 | } |
444 | 444 | ||
@@ -469,7 +469,7 @@ static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this, int state) | |||
469 | struct doc_priv *doc = this->priv; | 469 | struct doc_priv *doc = this->priv; |
470 | 470 | ||
471 | int status; | 471 | int status; |
472 | 472 | ||
473 | DoC_WaitReady(doc); | 473 | DoC_WaitReady(doc); |
474 | this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); | 474 | this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); |
475 | DoC_WaitReady(doc); | 475 | DoC_WaitReady(doc); |
@@ -503,7 +503,7 @@ static u_char doc2001_read_byte(struct mtd_info *mtd) | |||
503 | return ReadDOC(docptr, LastDataRead); | 503 | return ReadDOC(docptr, LastDataRead); |
504 | } | 504 | } |
505 | 505 | ||
506 | static void doc2001_writebuf(struct mtd_info *mtd, | 506 | static void doc2001_writebuf(struct mtd_info *mtd, |
507 | const u_char *buf, int len) | 507 | const u_char *buf, int len) |
508 | { | 508 | { |
509 | struct nand_chip *this = mtd->priv; | 509 | struct nand_chip *this = mtd->priv; |
@@ -517,7 +517,7 @@ static void doc2001_writebuf(struct mtd_info *mtd, | |||
517 | WriteDOC(0x00, docptr, WritePipeTerm); | 517 | WriteDOC(0x00, docptr, WritePipeTerm); |
518 | } | 518 | } |
519 | 519 | ||
520 | static void doc2001_readbuf(struct mtd_info *mtd, | 520 | static void doc2001_readbuf(struct mtd_info *mtd, |
521 | u_char *buf, int len) | 521 | u_char *buf, int len) |
522 | { | 522 | { |
523 | struct nand_chip *this = mtd->priv; | 523 | struct nand_chip *this = mtd->priv; |
@@ -535,7 +535,7 @@ static void doc2001_readbuf(struct mtd_info *mtd, | |||
535 | buf[i] = ReadDOC(docptr, LastDataRead); | 535 | buf[i] = ReadDOC(docptr, LastDataRead); |
536 | } | 536 | } |
537 | 537 | ||
538 | static int doc2001_verifybuf(struct mtd_info *mtd, | 538 | static int doc2001_verifybuf(struct mtd_info *mtd, |
539 | const u_char *buf, int len) | 539 | const u_char *buf, int len) |
540 | { | 540 | { |
541 | struct nand_chip *this = mtd->priv; | 541 | struct nand_chip *this = mtd->priv; |
@@ -570,7 +570,7 @@ static u_char doc2001plus_read_byte(struct mtd_info *mtd) | |||
570 | return ret; | 570 | return ret; |
571 | } | 571 | } |
572 | 572 | ||
573 | static void doc2001plus_writebuf(struct mtd_info *mtd, | 573 | static void doc2001plus_writebuf(struct mtd_info *mtd, |
574 | const u_char *buf, int len) | 574 | const u_char *buf, int len) |
575 | { | 575 | { |
576 | struct nand_chip *this = mtd->priv; | 576 | struct nand_chip *this = mtd->priv; |
@@ -587,7 +587,7 @@ static void doc2001plus_writebuf(struct mtd_info *mtd, | |||
587 | if (debug) printk("\n"); | 587 | if (debug) printk("\n"); |
588 | } | 588 | } |
589 | 589 | ||
590 | static void doc2001plus_readbuf(struct mtd_info *mtd, | 590 | static void doc2001plus_readbuf(struct mtd_info *mtd, |
591 | u_char *buf, int len) | 591 | u_char *buf, int len) |
592 | { | 592 | { |
593 | struct nand_chip *this = mtd->priv; | 593 | struct nand_chip *this = mtd->priv; |
@@ -617,7 +617,7 @@ static void doc2001plus_readbuf(struct mtd_info *mtd, | |||
617 | if (debug) printk("\n"); | 617 | if (debug) printk("\n"); |
618 | } | 618 | } |
619 | 619 | ||
620 | static int doc2001plus_verifybuf(struct mtd_info *mtd, | 620 | static int doc2001plus_verifybuf(struct mtd_info *mtd, |
621 | const u_char *buf, int len) | 621 | const u_char *buf, int len) |
622 | { | 622 | { |
623 | struct nand_chip *this = mtd->priv; | 623 | struct nand_chip *this = mtd->priv; |
@@ -797,7 +797,7 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col | |||
797 | WriteDOC(0, docptr, Mplus_FlashControl); | 797 | WriteDOC(0, docptr, Mplus_FlashControl); |
798 | } | 798 | } |
799 | 799 | ||
800 | /* | 800 | /* |
801 | * program and erase have their own busy handlers | 801 | * program and erase have their own busy handlers |
802 | * status and sequential in needs no delay | 802 | * status and sequential in needs no delay |
803 | */ | 803 | */ |
@@ -822,7 +822,7 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col | |||
822 | 822 | ||
823 | /* This applies to read commands */ | 823 | /* This applies to read commands */ |
824 | default: | 824 | default: |
825 | /* | 825 | /* |
826 | * If we don't have access to the busy pin, we apply the given | 826 | * If we don't have access to the busy pin, we apply the given |
827 | * command delay | 827 | * command delay |
828 | */ | 828 | */ |
@@ -945,7 +945,7 @@ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, | |||
945 | for (i = 0; i < 6; i++) { | 945 | for (i = 0; i < 6; i++) { |
946 | if (DoC_is_MillenniumPlus(doc)) | 946 | if (DoC_is_MillenniumPlus(doc)) |
947 | ecc_code[i] = ReadDOC_(docptr, DoC_Mplus_ECCSyndrome0 + i); | 947 | ecc_code[i] = ReadDOC_(docptr, DoC_Mplus_ECCSyndrome0 + i); |
948 | else | 948 | else |
949 | ecc_code[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i); | 949 | ecc_code[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i); |
950 | if (ecc_code[i] != empty_write_ecc[i]) | 950 | if (ecc_code[i] != empty_write_ecc[i]) |
951 | emptymatch = 0; | 951 | emptymatch = 0; |
@@ -982,7 +982,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ | |||
982 | void __iomem *docptr = doc->virtadr; | 982 | void __iomem *docptr = doc->virtadr; |
983 | volatile u_char dummy; | 983 | volatile u_char dummy; |
984 | int emptymatch = 1; | 984 | int emptymatch = 1; |
985 | 985 | ||
986 | /* flush the pipeline */ | 986 | /* flush the pipeline */ |
987 | if (DoC_is_2000(doc)) { | 987 | if (DoC_is_2000(doc)) { |
988 | dummy = ReadDOC(docptr, 2k_ECCStatus); | 988 | dummy = ReadDOC(docptr, 2k_ECCStatus); |
@@ -997,7 +997,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ | |||
997 | dummy = ReadDOC(docptr, ECCConf); | 997 | dummy = ReadDOC(docptr, ECCConf); |
998 | dummy = ReadDOC(docptr, ECCConf); | 998 | dummy = ReadDOC(docptr, ECCConf); |
999 | } | 999 | } |
1000 | 1000 | ||
1001 | /* Error occured ? */ | 1001 | /* Error occured ? */ |
1002 | if (dummy & 0x80) { | 1002 | if (dummy & 0x80) { |
1003 | for (i = 0; i < 6; i++) { | 1003 | for (i = 0; i < 6; i++) { |
@@ -1035,7 +1035,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ | |||
1035 | if (!emptymatch) ret = doc_ecc_decode (rs_decoder, dat, calc_ecc); | 1035 | if (!emptymatch) ret = doc_ecc_decode (rs_decoder, dat, calc_ecc); |
1036 | if (ret > 0) | 1036 | if (ret > 0) |
1037 | printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret); | 1037 | printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret); |
1038 | } | 1038 | } |
1039 | if (DoC_is_MillenniumPlus(doc)) | 1039 | if (DoC_is_MillenniumPlus(doc)) |
1040 | WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf); | 1040 | WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf); |
1041 | else | 1041 | else |
@@ -1046,7 +1046,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ | |||
1046 | } | 1046 | } |
1047 | return ret; | 1047 | return ret; |
1048 | } | 1048 | } |
1049 | 1049 | ||
1050 | //u_char mydatabuf[528]; | 1050 | //u_char mydatabuf[528]; |
1051 | 1051 | ||
1052 | /* The strange out-of-order .oobfree list below is a (possibly unneeded) | 1052 | /* The strange out-of-order .oobfree list below is a (possibly unneeded) |
@@ -1065,7 +1065,7 @@ static struct nand_oobinfo doc200x_oobinfo = { | |||
1065 | .eccpos = {0, 1, 2, 3, 4, 5}, | 1065 | .eccpos = {0, 1, 2, 3, 4, 5}, |
1066 | .oobfree = { {8, 8}, {6, 2} } | 1066 | .oobfree = { {8, 8}, {6, 2} } |
1067 | }; | 1067 | }; |
1068 | 1068 | ||
1069 | /* Find the (I)NFTL Media Header, and optionally also the mirror media header. | 1069 | /* Find the (I)NFTL Media Header, and optionally also the mirror media header. |
1070 | On sucessful return, buf will contain a copy of the media header for | 1070 | On sucessful return, buf will contain a copy of the media header for |
1071 | further processing. id is the string to scan for, and will presumably be | 1071 | further processing. id is the string to scan for, and will presumably be |
@@ -1251,7 +1251,7 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, | |||
1251 | mh->BlockMultiplierBits = le32_to_cpu(mh->BlockMultiplierBits); | 1251 | mh->BlockMultiplierBits = le32_to_cpu(mh->BlockMultiplierBits); |
1252 | mh->FormatFlags = le32_to_cpu(mh->FormatFlags); | 1252 | mh->FormatFlags = le32_to_cpu(mh->FormatFlags); |
1253 | mh->PercentUsed = le32_to_cpu(mh->PercentUsed); | 1253 | mh->PercentUsed = le32_to_cpu(mh->PercentUsed); |
1254 | 1254 | ||
1255 | printk(KERN_INFO " bootRecordID = %s\n" | 1255 | printk(KERN_INFO " bootRecordID = %s\n" |
1256 | " NoOfBootImageBlocks = %d\n" | 1256 | " NoOfBootImageBlocks = %d\n" |
1257 | " NoOfBinaryPartitions = %d\n" | 1257 | " NoOfBinaryPartitions = %d\n" |
@@ -1468,7 +1468,7 @@ static inline int __init doc2001_init(struct mtd_info *mtd) | |||
1468 | ReadDOC(doc->virtadr, ChipID); | 1468 | ReadDOC(doc->virtadr, ChipID); |
1469 | if (ReadDOC(doc->virtadr, ChipID) != DOC_ChipID_DocMil) { | 1469 | if (ReadDOC(doc->virtadr, ChipID) != DOC_ChipID_DocMil) { |
1470 | /* It's not a Millennium; it's one of the newer | 1470 | /* It's not a Millennium; it's one of the newer |
1471 | DiskOnChip 2000 units with a similar ASIC. | 1471 | DiskOnChip 2000 units with a similar ASIC. |
1472 | Treat it like a Millennium, except that it | 1472 | Treat it like a Millennium, except that it |
1473 | can have multiple chips. */ | 1473 | can have multiple chips. */ |
1474 | doc2000_count_chips(mtd); | 1474 | doc2000_count_chips(mtd); |
@@ -1530,20 +1530,20 @@ static inline int __init doc_probe(unsigned long physadr) | |||
1530 | * to the DOCControl register. So we store the current contents | 1530 | * to the DOCControl register. So we store the current contents |
1531 | * of the DOCControl register's location, in case we later decide | 1531 | * of the DOCControl register's location, in case we later decide |
1532 | * that it's not a DiskOnChip, and want to put it back how we | 1532 | * that it's not a DiskOnChip, and want to put it back how we |
1533 | * found it. | 1533 | * found it. |
1534 | */ | 1534 | */ |
1535 | save_control = ReadDOC(virtadr, DOCControl); | 1535 | save_control = ReadDOC(virtadr, DOCControl); |
1536 | 1536 | ||
1537 | /* Reset the DiskOnChip ASIC */ | 1537 | /* Reset the DiskOnChip ASIC */ |
1538 | WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, | 1538 | WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, |
1539 | virtadr, DOCControl); | 1539 | virtadr, DOCControl); |
1540 | WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, | 1540 | WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, |
1541 | virtadr, DOCControl); | 1541 | virtadr, DOCControl); |
1542 | 1542 | ||
1543 | /* Enable the DiskOnChip ASIC */ | 1543 | /* Enable the DiskOnChip ASIC */ |
1544 | WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, | 1544 | WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, |
1545 | virtadr, DOCControl); | 1545 | virtadr, DOCControl); |
1546 | WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, | 1546 | WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, |
1547 | virtadr, DOCControl); | 1547 | virtadr, DOCControl); |
1548 | 1548 | ||
1549 | ChipID = ReadDOC(virtadr, ChipID); | 1549 | ChipID = ReadDOC(virtadr, ChipID); |
@@ -1738,7 +1738,7 @@ static int __init init_nanddoc(void) | |||
1738 | int i, ret = 0; | 1738 | int i, ret = 0; |
1739 | 1739 | ||
1740 | /* We could create the decoder on demand, if memory is a concern. | 1740 | /* We could create the decoder on demand, if memory is a concern. |
1741 | * This way we have it handy, if an error happens | 1741 | * This way we have it handy, if an error happens |
1742 | * | 1742 | * |
1743 | * Symbolsize is 10 (bits) | 1743 | * Symbolsize is 10 (bits) |
1744 | * Primitve polynomial is x^10+x^3+1 | 1744 | * Primitve polynomial is x^10+x^3+1 |
diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c index 5549681ccdce..9b1fd2f387fa 100644 --- a/drivers/mtd/nand/edb7312.c +++ b/drivers/mtd/nand/edb7312.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Derived from drivers/mtd/nand/autcpu12.c | 6 | * Derived from drivers/mtd/nand/autcpu12.c |
7 | * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) | 7 | * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) |
8 | * | 8 | * |
9 | * $Id: edb7312.c,v 1.11 2004/11/04 12:53:10 gleixner Exp $ | 9 | * $Id: edb7312.c,v 1.12 2005/11/07 11:14:30 gleixner Exp $ |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2 as | 12 | * it under the terms of the GNU General Public License version 2 as |
@@ -71,27 +71,27 @@ static struct mtd_partition partition_info[] = { | |||
71 | #endif | 71 | #endif |
72 | 72 | ||
73 | 73 | ||
74 | /* | 74 | /* |
75 | * hardware specific access to control-lines | 75 | * hardware specific access to control-lines |
76 | */ | 76 | */ |
77 | static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd) | 77 | static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd) |
78 | { | 78 | { |
79 | switch(cmd) { | 79 | switch(cmd) { |
80 | 80 | ||
81 | case NAND_CTL_SETCLE: | 81 | case NAND_CTL_SETCLE: |
82 | clps_writeb(clps_readb(ep7312_pxdr) | 0x10, ep7312_pxdr); | 82 | clps_writeb(clps_readb(ep7312_pxdr) | 0x10, ep7312_pxdr); |
83 | break; | 83 | break; |
84 | case NAND_CTL_CLRCLE: | 84 | case NAND_CTL_CLRCLE: |
85 | clps_writeb(clps_readb(ep7312_pxdr) & ~0x10, ep7312_pxdr); | 85 | clps_writeb(clps_readb(ep7312_pxdr) & ~0x10, ep7312_pxdr); |
86 | break; | 86 | break; |
87 | 87 | ||
88 | case NAND_CTL_SETALE: | 88 | case NAND_CTL_SETALE: |
89 | clps_writeb(clps_readb(ep7312_pxdr) | 0x20, ep7312_pxdr); | 89 | clps_writeb(clps_readb(ep7312_pxdr) | 0x20, ep7312_pxdr); |
90 | break; | 90 | break; |
91 | case NAND_CTL_CLRALE: | 91 | case NAND_CTL_CLRALE: |
92 | clps_writeb(clps_readb(ep7312_pxdr) & ~0x20, ep7312_pxdr); | 92 | clps_writeb(clps_readb(ep7312_pxdr) & ~0x20, ep7312_pxdr); |
93 | break; | 93 | break; |
94 | 94 | ||
95 | case NAND_CTL_SETNCE: | 95 | case NAND_CTL_SETNCE: |
96 | clps_writeb((clps_readb(ep7312_pxdr) | 0x80) & ~0x40, ep7312_pxdr); | 96 | clps_writeb((clps_readb(ep7312_pxdr) | 0x80) & ~0x40, ep7312_pxdr); |
97 | break; | 97 | break; |
@@ -122,16 +122,16 @@ static int __init ep7312_init (void) | |||
122 | int mtd_parts_nb = 0; | 122 | int mtd_parts_nb = 0; |
123 | struct mtd_partition *mtd_parts = 0; | 123 | struct mtd_partition *mtd_parts = 0; |
124 | void __iomem * ep7312_fio_base; | 124 | void __iomem * ep7312_fio_base; |
125 | 125 | ||
126 | /* Allocate memory for MTD device structure and private data */ | 126 | /* Allocate memory for MTD device structure and private data */ |
127 | ep7312_mtd = kmalloc(sizeof(struct mtd_info) + | 127 | ep7312_mtd = kmalloc(sizeof(struct mtd_info) + |
128 | sizeof(struct nand_chip), | 128 | sizeof(struct nand_chip), |
129 | GFP_KERNEL); | 129 | GFP_KERNEL); |
130 | if (!ep7312_mtd) { | 130 | if (!ep7312_mtd) { |
131 | printk("Unable to allocate EDB7312 NAND MTD device structure.\n"); | 131 | printk("Unable to allocate EDB7312 NAND MTD device structure.\n"); |
132 | return -ENOMEM; | 132 | return -ENOMEM; |
133 | } | 133 | } |
134 | 134 | ||
135 | /* map physical adress */ | 135 | /* map physical adress */ |
136 | ep7312_fio_base = ioremap(ep7312_fio_pbase, SZ_1K); | 136 | ep7312_fio_base = ioremap(ep7312_fio_pbase, SZ_1K); |
137 | if(!ep7312_fio_base) { | 137 | if(!ep7312_fio_base) { |
@@ -139,23 +139,23 @@ static int __init ep7312_init (void) | |||
139 | kfree(ep7312_mtd); | 139 | kfree(ep7312_mtd); |
140 | return -EIO; | 140 | return -EIO; |
141 | } | 141 | } |
142 | 142 | ||
143 | /* Get pointer to private data */ | 143 | /* Get pointer to private data */ |
144 | this = (struct nand_chip *) (&ep7312_mtd[1]); | 144 | this = (struct nand_chip *) (&ep7312_mtd[1]); |
145 | 145 | ||
146 | /* Initialize structures */ | 146 | /* Initialize structures */ |
147 | memset((char *) ep7312_mtd, 0, sizeof(struct mtd_info)); | 147 | memset((char *) ep7312_mtd, 0, sizeof(struct mtd_info)); |
148 | memset((char *) this, 0, sizeof(struct nand_chip)); | 148 | memset((char *) this, 0, sizeof(struct nand_chip)); |
149 | 149 | ||
150 | /* Link the private data with the MTD structure */ | 150 | /* Link the private data with the MTD structure */ |
151 | ep7312_mtd->priv = this; | 151 | ep7312_mtd->priv = this; |
152 | 152 | ||
153 | /* | 153 | /* |
154 | * Set GPIO Port B control register so that the pins are configured | 154 | * Set GPIO Port B control register so that the pins are configured |
155 | * to be outputs for controlling the NAND flash. | 155 | * to be outputs for controlling the NAND flash. |
156 | */ | 156 | */ |
157 | clps_writeb(0xf0, ep7312_pxddr); | 157 | clps_writeb(0xf0, ep7312_pxddr); |
158 | 158 | ||
159 | /* insert callbacks */ | 159 | /* insert callbacks */ |
160 | this->IO_ADDR_R = ep7312_fio_base; | 160 | this->IO_ADDR_R = ep7312_fio_base; |
161 | this->IO_ADDR_W = ep7312_fio_base; | 161 | this->IO_ADDR_W = ep7312_fio_base; |
@@ -163,14 +163,14 @@ static int __init ep7312_init (void) | |||
163 | this->dev_ready = ep7312_device_ready; | 163 | this->dev_ready = ep7312_device_ready; |
164 | /* 15 us command delay time */ | 164 | /* 15 us command delay time */ |
165 | this->chip_delay = 15; | 165 | this->chip_delay = 15; |
166 | 166 | ||
167 | /* Scan to find existence of the device */ | 167 | /* Scan to find existence of the device */ |
168 | if (nand_scan (ep7312_mtd, 1)) { | 168 | if (nand_scan (ep7312_mtd, 1)) { |
169 | iounmap((void *)ep7312_fio_base); | 169 | iounmap((void *)ep7312_fio_base); |
170 | kfree (ep7312_mtd); | 170 | kfree (ep7312_mtd); |
171 | return -ENXIO; | 171 | return -ENXIO; |
172 | } | 172 | } |
173 | 173 | ||
174 | #ifdef CONFIG_MTD_PARTITIONS | 174 | #ifdef CONFIG_MTD_PARTITIONS |
175 | ep7312_mtd->name = "edb7312-nand"; | 175 | ep7312_mtd->name = "edb7312-nand"; |
176 | mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, | 176 | mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, |
@@ -185,11 +185,11 @@ static int __init ep7312_init (void) | |||
185 | mtd_parts_nb = NUM_PARTITIONS; | 185 | mtd_parts_nb = NUM_PARTITIONS; |
186 | part_type = "static"; | 186 | part_type = "static"; |
187 | } | 187 | } |
188 | 188 | ||
189 | /* Register the partitions */ | 189 | /* Register the partitions */ |
190 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); | 190 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); |
191 | add_mtd_partitions(ep7312_mtd, mtd_parts, mtd_parts_nb); | 191 | add_mtd_partitions(ep7312_mtd, mtd_parts, mtd_parts_nb); |
192 | 192 | ||
193 | /* Return happy */ | 193 | /* Return happy */ |
194 | return 0; | 194 | return 0; |
195 | } | 195 | } |
@@ -201,13 +201,13 @@ module_init(ep7312_init); | |||
201 | static void __exit ep7312_cleanup (void) | 201 | static void __exit ep7312_cleanup (void) |
202 | { | 202 | { |
203 | struct nand_chip *this = (struct nand_chip *) &ep7312_mtd[1]; | 203 | struct nand_chip *this = (struct nand_chip *) &ep7312_mtd[1]; |
204 | 204 | ||
205 | /* Release resources, unregister device */ | 205 | /* Release resources, unregister device */ |
206 | nand_release (ap7312_mtd); | 206 | nand_release (ap7312_mtd); |
207 | 207 | ||
208 | /* Free internal data buffer */ | 208 | /* Free internal data buffer */ |
209 | kfree (this->data_buf); | 209 | kfree (this->data_buf); |
210 | 210 | ||
211 | /* Free the MTD device structure */ | 211 | /* Free the MTD device structure */ |
212 | kfree (ep7312_mtd); | 212 | kfree (ep7312_mtd); |
213 | } | 213 | } |
diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c index 3825a7a0900c..041e4b3358fb 100644 --- a/drivers/mtd/nand/h1910.c +++ b/drivers/mtd/nand/h1910.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * Copyright (C) 2002 Marius Gröger (mag@sysgo.de) | 7 | * Copyright (C) 2002 Marius Gröger (mag@sysgo.de) |
8 | * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) | 8 | * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) |
9 | * | 9 | * |
10 | * $Id: h1910.c,v 1.5 2004/11/04 12:53:10 gleixner Exp $ | 10 | * $Id: h1910.c,v 1.6 2005/11/07 11:14:30 gleixner Exp $ |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
13 | * it under the terms of the GNU General Public License version 2 as | 13 | * it under the terms of the GNU General Public License version 2 as |
@@ -54,24 +54,24 @@ static struct mtd_partition partition_info[] = { | |||
54 | #endif | 54 | #endif |
55 | 55 | ||
56 | 56 | ||
57 | /* | 57 | /* |
58 | * hardware specific access to control-lines | 58 | * hardware specific access to control-lines |
59 | */ | 59 | */ |
60 | static void h1910_hwcontrol(struct mtd_info *mtd, int cmd) | 60 | static void h1910_hwcontrol(struct mtd_info *mtd, int cmd) |
61 | { | 61 | { |
62 | struct nand_chip* this = (struct nand_chip *) (mtd->priv); | 62 | struct nand_chip* this = (struct nand_chip *) (mtd->priv); |
63 | 63 | ||
64 | switch(cmd) { | 64 | switch(cmd) { |
65 | 65 | ||
66 | case NAND_CTL_SETCLE: | 66 | case NAND_CTL_SETCLE: |
67 | this->IO_ADDR_R |= (1 << 2); | 67 | this->IO_ADDR_R |= (1 << 2); |
68 | this->IO_ADDR_W |= (1 << 2); | 68 | this->IO_ADDR_W |= (1 << 2); |
69 | break; | 69 | break; |
70 | case NAND_CTL_CLRCLE: | 70 | case NAND_CTL_CLRCLE: |
71 | this->IO_ADDR_R &= ~(1 << 2); | 71 | this->IO_ADDR_R &= ~(1 << 2); |
72 | this->IO_ADDR_W &= ~(1 << 2); | 72 | this->IO_ADDR_W &= ~(1 << 2); |
73 | break; | 73 | break; |
74 | 74 | ||
75 | case NAND_CTL_SETALE: | 75 | case NAND_CTL_SETALE: |
76 | this->IO_ADDR_R |= (1 << 3); | 76 | this->IO_ADDR_R |= (1 << 3); |
77 | this->IO_ADDR_W |= (1 << 3); | 77 | this->IO_ADDR_W |= (1 << 3); |
@@ -80,7 +80,7 @@ static void h1910_hwcontrol(struct mtd_info *mtd, int cmd) | |||
80 | this->IO_ADDR_R &= ~(1 << 3); | 80 | this->IO_ADDR_R &= ~(1 << 3); |
81 | this->IO_ADDR_W &= ~(1 << 3); | 81 | this->IO_ADDR_W &= ~(1 << 3); |
82 | break; | 82 | break; |
83 | 83 | ||
84 | case NAND_CTL_SETNCE: | 84 | case NAND_CTL_SETNCE: |
85 | break; | 85 | break; |
86 | case NAND_CTL_CLRNCE: | 86 | case NAND_CTL_CLRNCE: |
@@ -108,18 +108,18 @@ static int __init h1910_init (void) | |||
108 | int mtd_parts_nb = 0; | 108 | int mtd_parts_nb = 0; |
109 | struct mtd_partition *mtd_parts = 0; | 109 | struct mtd_partition *mtd_parts = 0; |
110 | void __iomem *nandaddr; | 110 | void __iomem *nandaddr; |
111 | 111 | ||
112 | if (!machine_is_h1900()) | 112 | if (!machine_is_h1900()) |
113 | return -ENODEV; | 113 | return -ENODEV; |
114 | 114 | ||
115 | nandaddr = __ioremap(0x08000000, 0x1000, 0, 1); | 115 | nandaddr = __ioremap(0x08000000, 0x1000, 0, 1); |
116 | if (!nandaddr) { | 116 | if (!nandaddr) { |
117 | printk("Failed to ioremap nand flash.\n"); | 117 | printk("Failed to ioremap nand flash.\n"); |
118 | return -ENOMEM; | 118 | return -ENOMEM; |
119 | } | 119 | } |
120 | 120 | ||
121 | /* Allocate memory for MTD device structure and private data */ | 121 | /* Allocate memory for MTD device structure and private data */ |
122 | h1910_nand_mtd = kmalloc(sizeof(struct mtd_info) + | 122 | h1910_nand_mtd = kmalloc(sizeof(struct mtd_info) + |
123 | sizeof(struct nand_chip), | 123 | sizeof(struct nand_chip), |
124 | GFP_KERNEL); | 124 | GFP_KERNEL); |
125 | if (!h1910_nand_mtd) { | 125 | if (!h1910_nand_mtd) { |
@@ -127,22 +127,22 @@ static int __init h1910_init (void) | |||
127 | iounmap ((void *) nandaddr); | 127 | iounmap ((void *) nandaddr); |
128 | return -ENOMEM; | 128 | return -ENOMEM; |
129 | } | 129 | } |
130 | 130 | ||
131 | /* Get pointer to private data */ | 131 | /* Get pointer to private data */ |
132 | this = (struct nand_chip *) (&h1910_nand_mtd[1]); | 132 | this = (struct nand_chip *) (&h1910_nand_mtd[1]); |
133 | 133 | ||
134 | /* Initialize structures */ | 134 | /* Initialize structures */ |
135 | memset((char *) h1910_nand_mtd, 0, sizeof(struct mtd_info)); | 135 | memset((char *) h1910_nand_mtd, 0, sizeof(struct mtd_info)); |
136 | memset((char *) this, 0, sizeof(struct nand_chip)); | 136 | memset((char *) this, 0, sizeof(struct nand_chip)); |
137 | 137 | ||
138 | /* Link the private data with the MTD structure */ | 138 | /* Link the private data with the MTD structure */ |
139 | h1910_nand_mtd->priv = this; | 139 | h1910_nand_mtd->priv = this; |
140 | 140 | ||
141 | /* | 141 | /* |
142 | * Enable VPEN | 142 | * Enable VPEN |
143 | */ | 143 | */ |
144 | GPSR(37) = GPIO_bit(37); | 144 | GPSR(37) = GPIO_bit(37); |
145 | 145 | ||
146 | /* insert callbacks */ | 146 | /* insert callbacks */ |
147 | this->IO_ADDR_R = nandaddr; | 147 | this->IO_ADDR_R = nandaddr; |
148 | this->IO_ADDR_W = nandaddr; | 148 | this->IO_ADDR_W = nandaddr; |
@@ -152,7 +152,7 @@ static int __init h1910_init (void) | |||
152 | this->chip_delay = 50; | 152 | this->chip_delay = 50; |
153 | this->eccmode = NAND_ECC_SOFT; | 153 | this->eccmode = NAND_ECC_SOFT; |
154 | this->options = NAND_NO_AUTOINCR; | 154 | this->options = NAND_NO_AUTOINCR; |
155 | 155 | ||
156 | /* Scan to find existence of the device */ | 156 | /* Scan to find existence of the device */ |
157 | if (nand_scan (h1910_nand_mtd, 1)) { | 157 | if (nand_scan (h1910_nand_mtd, 1)) { |
158 | printk(KERN_NOTICE "No NAND device - returning -ENXIO\n"); | 158 | printk(KERN_NOTICE "No NAND device - returning -ENXIO\n"); |
@@ -160,9 +160,9 @@ static int __init h1910_init (void) | |||
160 | iounmap ((void *) nandaddr); | 160 | iounmap ((void *) nandaddr); |
161 | return -ENXIO; | 161 | return -ENXIO; |
162 | } | 162 | } |
163 | 163 | ||
164 | #ifdef CONFIG_MTD_CMDLINE_PARTS | 164 | #ifdef CONFIG_MTD_CMDLINE_PARTS |
165 | mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts, | 165 | mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts, |
166 | "h1910-nand"); | 166 | "h1910-nand"); |
167 | if (mtd_parts_nb > 0) | 167 | if (mtd_parts_nb > 0) |
168 | part_type = "command line"; | 168 | part_type = "command line"; |
@@ -175,11 +175,11 @@ static int __init h1910_init (void) | |||
175 | mtd_parts_nb = NUM_PARTITIONS; | 175 | mtd_parts_nb = NUM_PARTITIONS; |
176 | part_type = "static"; | 176 | part_type = "static"; |
177 | } | 177 | } |
178 | 178 | ||
179 | /* Register the partitions */ | 179 | /* Register the partitions */ |
180 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); | 180 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); |
181 | add_mtd_partitions(h1910_nand_mtd, mtd_parts, mtd_parts_nb); | 181 | add_mtd_partitions(h1910_nand_mtd, mtd_parts, mtd_parts_nb); |
182 | 182 | ||
183 | /* Return happy */ | 183 | /* Return happy */ |
184 | return 0; | 184 | return 0; |
185 | } | 185 | } |
@@ -191,7 +191,7 @@ module_init(h1910_init); | |||
191 | static void __exit h1910_cleanup (void) | 191 | static void __exit h1910_cleanup (void) |
192 | { | 192 | { |
193 | struct nand_chip *this = (struct nand_chip *) &h1910_nand_mtd[1]; | 193 | struct nand_chip *this = (struct nand_chip *) &h1910_nand_mtd[1]; |
194 | 194 | ||
195 | /* Release resources, unregister device */ | 195 | /* Release resources, unregister device */ |
196 | nand_release (h1910_nand_mtd); | 196 | nand_release (h1910_nand_mtd); |
197 | 197 | ||
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 8e78d7b96a56..5d222460b42a 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -5,14 +5,14 @@ | |||
5 | * This is the generic MTD driver for NAND flash devices. It should be | 5 | * This is the generic MTD driver for NAND flash devices. It should be |
6 | * capable of working with almost all NAND chips currently available. | 6 | * capable of working with almost all NAND chips currently available. |
7 | * Basic support for AG-AND chips is provided. | 7 | * Basic support for AG-AND chips is provided. |
8 | * | 8 | * |
9 | * Additional technical information is available on | 9 | * Additional technical information is available on |
10 | * http://www.linux-mtd.infradead.org/tech/nand.html | 10 | * http://www.linux-mtd.infradead.org/tech/nand.html |
11 | * | 11 | * |
12 | * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) | 12 | * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) |
13 | * 2002 Thomas Gleixner (tglx@linutronix.de) | 13 | * 2002 Thomas Gleixner (tglx@linutronix.de) |
14 | * | 14 | * |
15 | * 02-08-2004 tglx: support for strange chips, which cannot auto increment | 15 | * 02-08-2004 tglx: support for strange chips, which cannot auto increment |
16 | * pages on read / read_oob | 16 | * pages on read / read_oob |
17 | * | 17 | * |
18 | * 03-17-2004 tglx: Check ready before auto increment check. Simon Bayes | 18 | * 03-17-2004 tglx: Check ready before auto increment check. Simon Bayes |
@@ -21,7 +21,7 @@ | |||
21 | * Make reads over block boundaries work too | 21 | * Make reads over block boundaries work too |
22 | * | 22 | * |
23 | * 04-14-2004 tglx: first working version for 2k page size chips | 23 | * 04-14-2004 tglx: first working version for 2k page size chips |
24 | * | 24 | * |
25 | * 05-19-2004 tglx: Basic support for Renesas AG-AND chips | 25 | * 05-19-2004 tglx: Basic support for Renesas AG-AND chips |
26 | * | 26 | * |
27 | * 09-24-2004 tglx: add support for hardware controllers (e.g. ECC) shared | 27 | * 09-24-2004 tglx: add support for hardware controllers (e.g. ECC) shared |
@@ -30,25 +30,27 @@ | |||
30 | * | 30 | * |
31 | * 12-05-2004 dmarlin: add workaround for Renesas AG-AND chips "disturb" issue. | 31 | * 12-05-2004 dmarlin: add workaround for Renesas AG-AND chips "disturb" issue. |
32 | * Basically, any block not rewritten may lose data when surrounding blocks | 32 | * Basically, any block not rewritten may lose data when surrounding blocks |
33 | * are rewritten many times. JFFS2 ensures this doesn't happen for blocks | 33 | * are rewritten many times. JFFS2 ensures this doesn't happen for blocks |
34 | * it uses, but the Bad Block Table(s) may not be rewritten. To ensure they | 34 | * it uses, but the Bad Block Table(s) may not be rewritten. To ensure they |
35 | * do not lose data, force them to be rewritten when some of the surrounding | 35 | * do not lose data, force them to be rewritten when some of the surrounding |
36 | * blocks are erased. Rather than tracking a specific nearby block (which | 36 | * blocks are erased. Rather than tracking a specific nearby block (which |
37 | * could itself go bad), use a page address 'mask' to select several blocks | 37 | * could itself go bad), use a page address 'mask' to select several blocks |
38 | * in the same area, and rewrite the BBT when any of them are erased. | 38 | * in the same area, and rewrite the BBT when any of them are erased. |
39 | * | 39 | * |
40 | * 01-03-2005 dmarlin: added support for the device recovery command sequence for Renesas | 40 | * 01-03-2005 dmarlin: added support for the device recovery command sequence for Renesas |
41 | * AG-AND chips. If there was a sudden loss of power during an erase operation, | 41 | * AG-AND chips. If there was a sudden loss of power during an erase operation, |
42 | * a "device recovery" operation must be performed when power is restored | 42 | * a "device recovery" operation must be performed when power is restored |
43 | * to ensure correct operation. | 43 | * to ensure correct operation. |
44 | * | 44 | * |
45 | * 01-20-2005 dmarlin: added support for optional hardware specific callback routine to | 45 | * 01-20-2005 dmarlin: added support for optional hardware specific callback routine to |
46 | * perform extra error status checks on erase and write failures. This required | 46 | * perform extra error status checks on erase and write failures. This required |
47 | * adding a wrapper function for nand_read_ecc. | 47 | * adding a wrapper function for nand_read_ecc. |
48 | * | 48 | * |
49 | * 08-20-2005 vwool: suspend/resume added | ||
50 | * | ||
49 | * Credits: | 51 | * Credits: |
50 | * David Woodhouse for adding multichip support | 52 | * David Woodhouse for adding multichip support |
51 | * | 53 | * |
52 | * Aleph One Ltd. and Toby Churchill Ltd. for supporting the | 54 | * Aleph One Ltd. and Toby Churchill Ltd. for supporting the |
53 | * rework for 2K page size chips | 55 | * rework for 2K page size chips |
54 | * | 56 | * |
@@ -59,7 +61,7 @@ | |||
59 | * The AG-AND chips have nice features for speed improvement, | 61 | * The AG-AND chips have nice features for speed improvement, |
60 | * which are not supported yet. Read / program 4 pages in one go. | 62 | * which are not supported yet. Read / program 4 pages in one go. |
61 | * | 63 | * |
62 | * $Id: nand_base.c,v 1.147 2005/07/15 07:18:06 gleixner Exp $ | 64 | * $Id: nand_base.c,v 1.150 2005/09/15 13:58:48 vwool Exp $ |
63 | * | 65 | * |
64 | * This program is free software; you can redistribute it and/or modify | 66 | * This program is free software; you can redistribute it and/or modify |
65 | * it under the terms of the GNU General Public License version 2 as | 67 | * it under the terms of the GNU General Public License version 2 as |
@@ -103,8 +105,8 @@ static struct nand_oobinfo nand_oob_64 = { | |||
103 | .useecc = MTD_NANDECC_AUTOPLACE, | 105 | .useecc = MTD_NANDECC_AUTOPLACE, |
104 | .eccbytes = 24, | 106 | .eccbytes = 24, |
105 | .eccpos = { | 107 | .eccpos = { |
106 | 40, 41, 42, 43, 44, 45, 46, 47, | 108 | 40, 41, 42, 43, 44, 45, 46, 47, |
107 | 48, 49, 50, 51, 52, 53, 54, 55, | 109 | 48, 49, 50, 51, 52, 53, 54, 55, |
108 | 56, 57, 58, 59, 60, 61, 62, 63}, | 110 | 56, 57, 58, 59, 60, 61, 62, 63}, |
109 | .oobfree = { {2, 38} } | 111 | .oobfree = { {2, 38} } |
110 | }; | 112 | }; |
@@ -147,19 +149,19 @@ static void nand_sync (struct mtd_info *mtd); | |||
147 | static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf, | 149 | static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf, |
148 | struct nand_oobinfo *oobsel, int mode); | 150 | struct nand_oobinfo *oobsel, int mode); |
149 | #ifdef CONFIG_MTD_NAND_VERIFY_WRITE | 151 | #ifdef CONFIG_MTD_NAND_VERIFY_WRITE |
150 | static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages, | 152 | static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages, |
151 | u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode); | 153 | u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode); |
152 | #else | 154 | #else |
153 | #define nand_verify_pages(...) (0) | 155 | #define nand_verify_pages(...) (0) |
154 | #endif | 156 | #endif |
155 | 157 | ||
156 | static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state); | 158 | static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state); |
157 | 159 | ||
158 | /** | 160 | /** |
159 | * nand_release_device - [GENERIC] release chip | 161 | * nand_release_device - [GENERIC] release chip |
160 | * @mtd: MTD device structure | 162 | * @mtd: MTD device structure |
161 | * | 163 | * |
162 | * Deselect, release chip lock and wake up anyone waiting on the device | 164 | * Deselect, release chip lock and wake up anyone waiting on the device |
163 | */ | 165 | */ |
164 | static void nand_release_device (struct mtd_info *mtd) | 166 | static void nand_release_device (struct mtd_info *mtd) |
165 | { | 167 | { |
@@ -213,7 +215,7 @@ static void nand_write_byte(struct mtd_info *mtd, u_char byte) | |||
213 | * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip | 215 | * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip |
214 | * @mtd: MTD device structure | 216 | * @mtd: MTD device structure |
215 | * | 217 | * |
216 | * Default read function for 16bit buswith with | 218 | * Default read function for 16bit buswith with |
217 | * endianess conversion | 219 | * endianess conversion |
218 | */ | 220 | */ |
219 | static u_char nand_read_byte16(struct mtd_info *mtd) | 221 | static u_char nand_read_byte16(struct mtd_info *mtd) |
@@ -240,7 +242,7 @@ static void nand_write_byte16(struct mtd_info *mtd, u_char byte) | |||
240 | * nand_read_word - [DEFAULT] read one word from the chip | 242 | * nand_read_word - [DEFAULT] read one word from the chip |
241 | * @mtd: MTD device structure | 243 | * @mtd: MTD device structure |
242 | * | 244 | * |
243 | * Default read function for 16bit buswith without | 245 | * Default read function for 16bit buswith without |
244 | * endianess conversion | 246 | * endianess conversion |
245 | */ | 247 | */ |
246 | static u16 nand_read_word(struct mtd_info *mtd) | 248 | static u16 nand_read_word(struct mtd_info *mtd) |
@@ -254,7 +256,7 @@ static u16 nand_read_word(struct mtd_info *mtd) | |||
254 | * @mtd: MTD device structure | 256 | * @mtd: MTD device structure |
255 | * @word: data word to write | 257 | * @word: data word to write |
256 | * | 258 | * |
257 | * Default write function for 16bit buswith without | 259 | * Default write function for 16bit buswith without |
258 | * endianess conversion | 260 | * endianess conversion |
259 | */ | 261 | */ |
260 | static void nand_write_word(struct mtd_info *mtd, u16 word) | 262 | static void nand_write_word(struct mtd_info *mtd, u16 word) |
@@ -275,7 +277,7 @@ static void nand_select_chip(struct mtd_info *mtd, int chip) | |||
275 | struct nand_chip *this = mtd->priv; | 277 | struct nand_chip *this = mtd->priv; |
276 | switch(chip) { | 278 | switch(chip) { |
277 | case -1: | 279 | case -1: |
278 | this->hwcontrol(mtd, NAND_CTL_CLRNCE); | 280 | this->hwcontrol(mtd, NAND_CTL_CLRNCE); |
279 | break; | 281 | break; |
280 | case 0: | 282 | case 0: |
281 | this->hwcontrol(mtd, NAND_CTL_SETNCE); | 283 | this->hwcontrol(mtd, NAND_CTL_SETNCE); |
@@ -304,7 +306,7 @@ static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | |||
304 | } | 306 | } |
305 | 307 | ||
306 | /** | 308 | /** |
307 | * nand_read_buf - [DEFAULT] read chip data into buffer | 309 | * nand_read_buf - [DEFAULT] read chip data into buffer |
308 | * @mtd: MTD device structure | 310 | * @mtd: MTD device structure |
309 | * @buf: buffer to store date | 311 | * @buf: buffer to store date |
310 | * @len: number of bytes to read | 312 | * @len: number of bytes to read |
@@ -321,7 +323,7 @@ static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | |||
321 | } | 323 | } |
322 | 324 | ||
323 | /** | 325 | /** |
324 | * nand_verify_buf - [DEFAULT] Verify chip data against buffer | 326 | * nand_verify_buf - [DEFAULT] Verify chip data against buffer |
325 | * @mtd: MTD device structure | 327 | * @mtd: MTD device structure |
326 | * @buf: buffer containing the data to compare | 328 | * @buf: buffer containing the data to compare |
327 | * @len: number of bytes to compare | 329 | * @len: number of bytes to compare |
@@ -354,14 +356,14 @@ static void nand_write_buf16(struct mtd_info *mtd, const u_char *buf, int len) | |||
354 | struct nand_chip *this = mtd->priv; | 356 | struct nand_chip *this = mtd->priv; |
355 | u16 *p = (u16 *) buf; | 357 | u16 *p = (u16 *) buf; |
356 | len >>= 1; | 358 | len >>= 1; |
357 | 359 | ||
358 | for (i=0; i<len; i++) | 360 | for (i=0; i<len; i++) |
359 | writew(p[i], this->IO_ADDR_W); | 361 | writew(p[i], this->IO_ADDR_W); |
360 | 362 | ||
361 | } | 363 | } |
362 | 364 | ||
363 | /** | 365 | /** |
364 | * nand_read_buf16 - [DEFAULT] read chip data into buffer | 366 | * nand_read_buf16 - [DEFAULT] read chip data into buffer |
365 | * @mtd: MTD device structure | 367 | * @mtd: MTD device structure |
366 | * @buf: buffer to store date | 368 | * @buf: buffer to store date |
367 | * @len: number of bytes to read | 369 | * @len: number of bytes to read |
@@ -380,7 +382,7 @@ static void nand_read_buf16(struct mtd_info *mtd, u_char *buf, int len) | |||
380 | } | 382 | } |
381 | 383 | ||
382 | /** | 384 | /** |
383 | * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer | 385 | * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer |
384 | * @mtd: MTD device structure | 386 | * @mtd: MTD device structure |
385 | * @buf: buffer containing the data to compare | 387 | * @buf: buffer containing the data to compare |
386 | * @len: number of bytes to compare | 388 | * @len: number of bytes to compare |
@@ -407,7 +409,7 @@ static int nand_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len) | |||
407 | * @ofs: offset from device start | 409 | * @ofs: offset from device start |
408 | * @getchip: 0, if the chip is already selected | 410 | * @getchip: 0, if the chip is already selected |
409 | * | 411 | * |
410 | * Check, if the block is bad. | 412 | * Check, if the block is bad. |
411 | */ | 413 | */ |
412 | static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) | 414 | static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) |
413 | { | 415 | { |
@@ -424,14 +426,14 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) | |||
424 | 426 | ||
425 | /* Select the NAND device */ | 427 | /* Select the NAND device */ |
426 | this->select_chip(mtd, chipnr); | 428 | this->select_chip(mtd, chipnr); |
427 | } else | 429 | } else |
428 | page = (int) ofs; | 430 | page = (int) ofs; |
429 | 431 | ||
430 | if (this->options & NAND_BUSWIDTH_16) { | 432 | if (this->options & NAND_BUSWIDTH_16) { |
431 | this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE, page & this->pagemask); | 433 | this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE, page & this->pagemask); |
432 | bad = cpu_to_le16(this->read_word(mtd)); | 434 | bad = cpu_to_le16(this->read_word(mtd)); |
433 | if (this->badblockpos & 0x1) | 435 | if (this->badblockpos & 0x1) |
434 | bad >>= 1; | 436 | bad >>= 8; |
435 | if ((bad & 0xFF) != 0xff) | 437 | if ((bad & 0xFF) != 0xff) |
436 | res = 1; | 438 | res = 1; |
437 | } else { | 439 | } else { |
@@ -439,12 +441,12 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) | |||
439 | if (this->read_byte(mtd) != 0xff) | 441 | if (this->read_byte(mtd) != 0xff) |
440 | res = 1; | 442 | res = 1; |
441 | } | 443 | } |
442 | 444 | ||
443 | if (getchip) { | 445 | if (getchip) { |
444 | /* Deselect and wake up anyone waiting on the device */ | 446 | /* Deselect and wake up anyone waiting on the device */ |
445 | nand_release_device(mtd); | 447 | nand_release_device(mtd); |
446 | } | 448 | } |
447 | 449 | ||
448 | return res; | 450 | return res; |
449 | } | 451 | } |
450 | 452 | ||
@@ -462,7 +464,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
462 | u_char buf[2] = {0, 0}; | 464 | u_char buf[2] = {0, 0}; |
463 | size_t retlen; | 465 | size_t retlen; |
464 | int block; | 466 | int block; |
465 | 467 | ||
466 | /* Get block number */ | 468 | /* Get block number */ |
467 | block = ((int) ofs) >> this->bbt_erase_shift; | 469 | block = ((int) ofs) >> this->bbt_erase_shift; |
468 | if (this->bbt) | 470 | if (this->bbt) |
@@ -471,25 +473,25 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
471 | /* Do we have a flash based bad block table ? */ | 473 | /* Do we have a flash based bad block table ? */ |
472 | if (this->options & NAND_USE_FLASH_BBT) | 474 | if (this->options & NAND_USE_FLASH_BBT) |
473 | return nand_update_bbt (mtd, ofs); | 475 | return nand_update_bbt (mtd, ofs); |
474 | 476 | ||
475 | /* We write two bytes, so we dont have to mess with 16 bit access */ | 477 | /* We write two bytes, so we dont have to mess with 16 bit access */ |
476 | ofs += mtd->oobsize + (this->badblockpos & ~0x01); | 478 | ofs += mtd->oobsize + (this->badblockpos & ~0x01); |
477 | return nand_write_oob (mtd, ofs , 2, &retlen, buf); | 479 | return nand_write_oob (mtd, ofs , 2, &retlen, buf); |
478 | } | 480 | } |
479 | 481 | ||
480 | /** | 482 | /** |
481 | * nand_check_wp - [GENERIC] check if the chip is write protected | 483 | * nand_check_wp - [GENERIC] check if the chip is write protected |
482 | * @mtd: MTD device structure | 484 | * @mtd: MTD device structure |
483 | * Check, if the device is write protected | 485 | * Check, if the device is write protected |
484 | * | 486 | * |
485 | * The function expects, that the device is already selected | 487 | * The function expects, that the device is already selected |
486 | */ | 488 | */ |
487 | static int nand_check_wp (struct mtd_info *mtd) | 489 | static int nand_check_wp (struct mtd_info *mtd) |
488 | { | 490 | { |
489 | struct nand_chip *this = mtd->priv; | 491 | struct nand_chip *this = mtd->priv; |
490 | /* Check the WP bit */ | 492 | /* Check the WP bit */ |
491 | this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); | 493 | this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); |
492 | return (this->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1; | 494 | return (this->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1; |
493 | } | 495 | } |
494 | 496 | ||
495 | /** | 497 | /** |
@@ -505,15 +507,15 @@ static int nand_check_wp (struct mtd_info *mtd) | |||
505 | static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt) | 507 | static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt) |
506 | { | 508 | { |
507 | struct nand_chip *this = mtd->priv; | 509 | struct nand_chip *this = mtd->priv; |
508 | 510 | ||
509 | if (!this->bbt) | 511 | if (!this->bbt) |
510 | return this->block_bad(mtd, ofs, getchip); | 512 | return this->block_bad(mtd, ofs, getchip); |
511 | 513 | ||
512 | /* Return info from the table */ | 514 | /* Return info from the table */ |
513 | return nand_isbad_bbt (mtd, ofs, allowbbt); | 515 | return nand_isbad_bbt (mtd, ofs, allowbbt); |
514 | } | 516 | } |
515 | 517 | ||
516 | /* | 518 | /* |
517 | * Wait for the ready pin, after a command | 519 | * Wait for the ready pin, after a command |
518 | * The timeout is catched later. | 520 | * The timeout is catched later. |
519 | */ | 521 | */ |
@@ -527,7 +529,7 @@ static void nand_wait_ready(struct mtd_info *mtd) | |||
527 | if (this->dev_ready(mtd)) | 529 | if (this->dev_ready(mtd)) |
528 | return; | 530 | return; |
529 | touch_softlockup_watchdog(); | 531 | touch_softlockup_watchdog(); |
530 | } while (time_before(jiffies, timeo)); | 532 | } while (time_before(jiffies, timeo)); |
531 | } | 533 | } |
532 | 534 | ||
533 | /** | 535 | /** |
@@ -590,13 +592,13 @@ static void nand_command (struct mtd_info *mtd, unsigned command, int column, in | |||
590 | /* Latch in address */ | 592 | /* Latch in address */ |
591 | this->hwcontrol(mtd, NAND_CTL_CLRALE); | 593 | this->hwcontrol(mtd, NAND_CTL_CLRALE); |
592 | } | 594 | } |
593 | 595 | ||
594 | /* | 596 | /* |
595 | * program and erase have their own busy handlers | 597 | * program and erase have their own busy handlers |
596 | * status and sequential in needs no delay | 598 | * status and sequential in needs no delay |
597 | */ | 599 | */ |
598 | switch (command) { | 600 | switch (command) { |
599 | 601 | ||
600 | case NAND_CMD_PAGEPROG: | 602 | case NAND_CMD_PAGEPROG: |
601 | case NAND_CMD_ERASE1: | 603 | case NAND_CMD_ERASE1: |
602 | case NAND_CMD_ERASE2: | 604 | case NAND_CMD_ERASE2: |
@@ -605,7 +607,7 @@ static void nand_command (struct mtd_info *mtd, unsigned command, int column, in | |||
605 | return; | 607 | return; |
606 | 608 | ||
607 | case NAND_CMD_RESET: | 609 | case NAND_CMD_RESET: |
608 | if (this->dev_ready) | 610 | if (this->dev_ready) |
609 | break; | 611 | break; |
610 | udelay(this->chip_delay); | 612 | udelay(this->chip_delay); |
611 | this->hwcontrol(mtd, NAND_CTL_SETCLE); | 613 | this->hwcontrol(mtd, NAND_CTL_SETCLE); |
@@ -614,16 +616,16 @@ static void nand_command (struct mtd_info *mtd, unsigned command, int column, in | |||
614 | while ( !(this->read_byte(mtd) & NAND_STATUS_READY)); | 616 | while ( !(this->read_byte(mtd) & NAND_STATUS_READY)); |
615 | return; | 617 | return; |
616 | 618 | ||
617 | /* This applies to read commands */ | 619 | /* This applies to read commands */ |
618 | default: | 620 | default: |
619 | /* | 621 | /* |
620 | * If we don't have access to the busy pin, we apply the given | 622 | * If we don't have access to the busy pin, we apply the given |
621 | * command delay | 623 | * command delay |
622 | */ | 624 | */ |
623 | if (!this->dev_ready) { | 625 | if (!this->dev_ready) { |
624 | udelay (this->chip_delay); | 626 | udelay (this->chip_delay); |
625 | return; | 627 | return; |
626 | } | 628 | } |
627 | } | 629 | } |
628 | /* Apply this short delay always to ensure that we do wait tWB in | 630 | /* Apply this short delay always to ensure that we do wait tWB in |
629 | * any case on any machine. */ | 631 | * any case on any machine. */ |
@@ -653,8 +655,8 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, | |||
653 | column += mtd->oobblock; | 655 | column += mtd->oobblock; |
654 | command = NAND_CMD_READ0; | 656 | command = NAND_CMD_READ0; |
655 | } | 657 | } |
656 | 658 | ||
657 | 659 | ||
658 | /* Begin command latch cycle */ | 660 | /* Begin command latch cycle */ |
659 | this->hwcontrol(mtd, NAND_CTL_SETCLE); | 661 | this->hwcontrol(mtd, NAND_CTL_SETCLE); |
660 | /* Write out the command to the device. */ | 662 | /* Write out the command to the device. */ |
@@ -672,7 +674,7 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, | |||
672 | column >>= 1; | 674 | column >>= 1; |
673 | this->write_byte(mtd, column & 0xff); | 675 | this->write_byte(mtd, column & 0xff); |
674 | this->write_byte(mtd, column >> 8); | 676 | this->write_byte(mtd, column >> 8); |
675 | } | 677 | } |
676 | if (page_addr != -1) { | 678 | if (page_addr != -1) { |
677 | this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); | 679 | this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); |
678 | this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); | 680 | this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); |
@@ -683,13 +685,13 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, | |||
683 | /* Latch in address */ | 685 | /* Latch in address */ |
684 | this->hwcontrol(mtd, NAND_CTL_CLRALE); | 686 | this->hwcontrol(mtd, NAND_CTL_CLRALE); |
685 | } | 687 | } |
686 | 688 | ||
687 | /* | 689 | /* |
688 | * program and erase have their own busy handlers | 690 | * program and erase have their own busy handlers |
689 | * status, sequential in, and deplete1 need no delay | 691 | * status, sequential in, and deplete1 need no delay |
690 | */ | 692 | */ |
691 | switch (command) { | 693 | switch (command) { |
692 | 694 | ||
693 | case NAND_CMD_CACHEDPROG: | 695 | case NAND_CMD_CACHEDPROG: |
694 | case NAND_CMD_PAGEPROG: | 696 | case NAND_CMD_PAGEPROG: |
695 | case NAND_CMD_ERASE1: | 697 | case NAND_CMD_ERASE1: |
@@ -699,7 +701,7 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, | |||
699 | case NAND_CMD_DEPLETE1: | 701 | case NAND_CMD_DEPLETE1: |
700 | return; | 702 | return; |
701 | 703 | ||
702 | /* | 704 | /* |
703 | * read error status commands require only a short delay | 705 | * read error status commands require only a short delay |
704 | */ | 706 | */ |
705 | case NAND_CMD_STATUS_ERROR: | 707 | case NAND_CMD_STATUS_ERROR: |
@@ -711,7 +713,7 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, | |||
711 | return; | 713 | return; |
712 | 714 | ||
713 | case NAND_CMD_RESET: | 715 | case NAND_CMD_RESET: |
714 | if (this->dev_ready) | 716 | if (this->dev_ready) |
715 | break; | 717 | break; |
716 | udelay(this->chip_delay); | 718 | udelay(this->chip_delay); |
717 | this->hwcontrol(mtd, NAND_CTL_SETCLE); | 719 | this->hwcontrol(mtd, NAND_CTL_SETCLE); |
@@ -728,17 +730,17 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, | |||
728 | /* End command latch cycle */ | 730 | /* End command latch cycle */ |
729 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); | 731 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); |
730 | /* Fall through into ready check */ | 732 | /* Fall through into ready check */ |
731 | 733 | ||
732 | /* This applies to read commands */ | 734 | /* This applies to read commands */ |
733 | default: | 735 | default: |
734 | /* | 736 | /* |
735 | * If we don't have access to the busy pin, we apply the given | 737 | * If we don't have access to the busy pin, we apply the given |
736 | * command delay | 738 | * command delay |
737 | */ | 739 | */ |
738 | if (!this->dev_ready) { | 740 | if (!this->dev_ready) { |
739 | udelay (this->chip_delay); | 741 | udelay (this->chip_delay); |
740 | return; | 742 | return; |
741 | } | 743 | } |
742 | } | 744 | } |
743 | 745 | ||
744 | /* Apply this short delay always to ensure that we do wait tWB in | 746 | /* Apply this short delay always to ensure that we do wait tWB in |
@@ -752,11 +754,11 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, | |||
752 | * nand_get_device - [GENERIC] Get chip for selected access | 754 | * nand_get_device - [GENERIC] Get chip for selected access |
753 | * @this: the nand chip descriptor | 755 | * @this: the nand chip descriptor |
754 | * @mtd: MTD device structure | 756 | * @mtd: MTD device structure |
755 | * @new_state: the state which is requested | 757 | * @new_state: the state which is requested |
756 | * | 758 | * |
757 | * Get the device and lock it for exclusive access | 759 | * Get the device and lock it for exclusive access |
758 | */ | 760 | */ |
759 | static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state) | 761 | static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state) |
760 | { | 762 | { |
761 | struct nand_chip *active; | 763 | struct nand_chip *active; |
762 | spinlock_t *lock; | 764 | spinlock_t *lock; |
@@ -779,7 +781,11 @@ retry: | |||
779 | if (active == this && this->state == FL_READY) { | 781 | if (active == this && this->state == FL_READY) { |
780 | this->state = new_state; | 782 | this->state = new_state; |
781 | spin_unlock(lock); | 783 | spin_unlock(lock); |
782 | return; | 784 | return 0; |
785 | } | ||
786 | if (new_state == FL_PM_SUSPENDED) { | ||
787 | spin_unlock(lock); | ||
788 | return (this->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN; | ||
783 | } | 789 | } |
784 | set_current_state(TASK_UNINTERRUPTIBLE); | 790 | set_current_state(TASK_UNINTERRUPTIBLE); |
785 | add_wait_queue(wq, &wait); | 791 | add_wait_queue(wq, &wait); |
@@ -796,7 +802,7 @@ retry: | |||
796 | * @state: state to select the max. timeout value | 802 | * @state: state to select the max. timeout value |
797 | * | 803 | * |
798 | * Wait for command done. This applies to erase and program only | 804 | * Wait for command done. This applies to erase and program only |
799 | * Erase can take up to 400ms and program up to 20ms according to | 805 | * Erase can take up to 400ms and program up to 20ms according to |
800 | * general NAND and SmartMedia specs | 806 | * general NAND and SmartMedia specs |
801 | * | 807 | * |
802 | */ | 808 | */ |
@@ -805,7 +811,7 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) | |||
805 | 811 | ||
806 | unsigned long timeo = jiffies; | 812 | unsigned long timeo = jiffies; |
807 | int status; | 813 | int status; |
808 | 814 | ||
809 | if (state == FL_ERASING) | 815 | if (state == FL_ERASING) |
810 | timeo += (HZ * 400) / 1000; | 816 | timeo += (HZ * 400) / 1000; |
811 | else | 817 | else |
@@ -817,17 +823,17 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) | |||
817 | 823 | ||
818 | if ((state == FL_ERASING) && (this->options & NAND_IS_AND)) | 824 | if ((state == FL_ERASING) && (this->options & NAND_IS_AND)) |
819 | this->cmdfunc (mtd, NAND_CMD_STATUS_MULTI, -1, -1); | 825 | this->cmdfunc (mtd, NAND_CMD_STATUS_MULTI, -1, -1); |
820 | else | 826 | else |
821 | this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); | 827 | this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); |
822 | 828 | ||
823 | while (time_before(jiffies, timeo)) { | 829 | while (time_before(jiffies, timeo)) { |
824 | /* Check, if we were interrupted */ | 830 | /* Check, if we were interrupted */ |
825 | if (this->state != state) | 831 | if (this->state != state) |
826 | return 0; | 832 | return 0; |
827 | 833 | ||
828 | if (this->dev_ready) { | 834 | if (this->dev_ready) { |
829 | if (this->dev_ready(mtd)) | 835 | if (this->dev_ready(mtd)) |
830 | break; | 836 | break; |
831 | } else { | 837 | } else { |
832 | if (this->read_byte(mtd) & NAND_STATUS_READY) | 838 | if (this->read_byte(mtd) & NAND_STATUS_READY) |
833 | break; | 839 | break; |
@@ -853,7 +859,7 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) | |||
853 | * | 859 | * |
854 | * Cached programming is not supported yet. | 860 | * Cached programming is not supported yet. |
855 | */ | 861 | */ |
856 | static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, | 862 | static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, |
857 | u_char *oob_buf, struct nand_oobinfo *oobsel, int cached) | 863 | u_char *oob_buf, struct nand_oobinfo *oobsel, int cached) |
858 | { | 864 | { |
859 | int i, status; | 865 | int i, status; |
@@ -862,10 +868,10 @@ static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int pa | |||
862 | int *oob_config = oobsel->eccpos; | 868 | int *oob_config = oobsel->eccpos; |
863 | int datidx = 0, eccidx = 0, eccsteps = this->eccsteps; | 869 | int datidx = 0, eccidx = 0, eccsteps = this->eccsteps; |
864 | int eccbytes = 0; | 870 | int eccbytes = 0; |
865 | 871 | ||
866 | /* FIXME: Enable cached programming */ | 872 | /* FIXME: Enable cached programming */ |
867 | cached = 0; | 873 | cached = 0; |
868 | 874 | ||
869 | /* Send command to begin auto page programming */ | 875 | /* Send command to begin auto page programming */ |
870 | this->cmdfunc (mtd, NAND_CMD_SEQIN, 0x00, page); | 876 | this->cmdfunc (mtd, NAND_CMD_SEQIN, 0x00, page); |
871 | 877 | ||
@@ -876,7 +882,7 @@ static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int pa | |||
876 | printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n"); | 882 | printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n"); |
877 | this->write_buf(mtd, this->data_poi, mtd->oobblock); | 883 | this->write_buf(mtd, this->data_poi, mtd->oobblock); |
878 | break; | 884 | break; |
879 | 885 | ||
880 | /* Software ecc 3/256, write all */ | 886 | /* Software ecc 3/256, write all */ |
881 | case NAND_ECC_SOFT: | 887 | case NAND_ECC_SOFT: |
882 | for (; eccsteps; eccsteps--) { | 888 | for (; eccsteps; eccsteps--) { |
@@ -905,11 +911,11 @@ static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int pa | |||
905 | } | 911 | } |
906 | break; | 912 | break; |
907 | } | 913 | } |
908 | 914 | ||
909 | /* Write out OOB data */ | 915 | /* Write out OOB data */ |
910 | if (this->options & NAND_HWECC_SYNDROME) | 916 | if (this->options & NAND_HWECC_SYNDROME) |
911 | this->write_buf(mtd, &oob_buf[oobsel->eccbytes], mtd->oobsize - oobsel->eccbytes); | 917 | this->write_buf(mtd, &oob_buf[oobsel->eccbytes], mtd->oobsize - oobsel->eccbytes); |
912 | else | 918 | else |
913 | this->write_buf(mtd, oob_buf, mtd->oobsize); | 919 | this->write_buf(mtd, oob_buf, mtd->oobsize); |
914 | 920 | ||
915 | /* Send command to actually program the data */ | 921 | /* Send command to actually program the data */ |
@@ -934,7 +940,7 @@ static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int pa | |||
934 | /* wait until cache is ready*/ | 940 | /* wait until cache is ready*/ |
935 | // status = this->waitfunc (mtd, this, FL_CACHEDRPG); | 941 | // status = this->waitfunc (mtd, this, FL_CACHEDRPG); |
936 | } | 942 | } |
937 | return 0; | 943 | return 0; |
938 | } | 944 | } |
939 | 945 | ||
940 | #ifdef CONFIG_MTD_NAND_VERIFY_WRITE | 946 | #ifdef CONFIG_MTD_NAND_VERIFY_WRITE |
@@ -950,19 +956,19 @@ static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int pa | |||
950 | * @oobmode: 1 = full buffer verify, 0 = ecc only | 956 | * @oobmode: 1 = full buffer verify, 0 = ecc only |
951 | * | 957 | * |
952 | * The NAND device assumes that it is always writing to a cleanly erased page. | 958 | * The NAND device assumes that it is always writing to a cleanly erased page. |
953 | * Hence, it performs its internal write verification only on bits that | 959 | * Hence, it performs its internal write verification only on bits that |
954 | * transitioned from 1 to 0. The device does NOT verify the whole page on a | 960 | * transitioned from 1 to 0. The device does NOT verify the whole page on a |
955 | * byte by byte basis. It is possible that the page was not completely erased | 961 | * byte by byte basis. It is possible that the page was not completely erased |
956 | * or the page is becoming unusable due to wear. The read with ECC would catch | 962 | * or the page is becoming unusable due to wear. The read with ECC would catch |
957 | * the error later when the ECC page check fails, but we would rather catch | 963 | * the error later when the ECC page check fails, but we would rather catch |
958 | * it early in the page write stage. Better to write no data than invalid data. | 964 | * it early in the page write stage. Better to write no data than invalid data. |
959 | */ | 965 | */ |
960 | static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages, | 966 | static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages, |
961 | u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode) | 967 | u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode) |
962 | { | 968 | { |
963 | int i, j, datidx = 0, oobofs = 0, res = -EIO; | 969 | int i, j, datidx = 0, oobofs = 0, res = -EIO; |
964 | int eccsteps = this->eccsteps; | 970 | int eccsteps = this->eccsteps; |
965 | int hweccbytes; | 971 | int hweccbytes; |
966 | u_char oobdata[64]; | 972 | u_char oobdata[64]; |
967 | 973 | ||
968 | hweccbytes = (this->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0; | 974 | hweccbytes = (this->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0; |
@@ -1002,7 +1008,7 @@ static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int | |||
1002 | 1008 | ||
1003 | if (oobsel->useecc != MTD_NANDECC_OFF && !hweccbytes) { | 1009 | if (oobsel->useecc != MTD_NANDECC_OFF && !hweccbytes) { |
1004 | int ecccnt = oobsel->eccbytes; | 1010 | int ecccnt = oobsel->eccbytes; |
1005 | 1011 | ||
1006 | for (i = 0; i < ecccnt; i++) { | 1012 | for (i = 0; i < ecccnt; i++) { |
1007 | int idx = oobsel->eccpos[i]; | 1013 | int idx = oobsel->eccpos[i]; |
1008 | if (oobdata[idx] != oob_buf[oobofs + idx] ) { | 1014 | if (oobdata[idx] != oob_buf[oobofs + idx] ) { |
@@ -1012,20 +1018,20 @@ static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int | |||
1012 | goto out; | 1018 | goto out; |
1013 | } | 1019 | } |
1014 | } | 1020 | } |
1015 | } | 1021 | } |
1016 | } | 1022 | } |
1017 | oobofs += mtd->oobsize - hweccbytes * eccsteps; | 1023 | oobofs += mtd->oobsize - hweccbytes * eccsteps; |
1018 | page++; | 1024 | page++; |
1019 | numpages--; | 1025 | numpages--; |
1020 | 1026 | ||
1021 | /* Apply delay or wait for ready/busy pin | 1027 | /* Apply delay or wait for ready/busy pin |
1022 | * Do this before the AUTOINCR check, so no problems | 1028 | * Do this before the AUTOINCR check, so no problems |
1023 | * arise if a chip which does auto increment | 1029 | * arise if a chip which does auto increment |
1024 | * is marked as NOAUTOINCR by the board driver. | 1030 | * is marked as NOAUTOINCR by the board driver. |
1025 | * Do this also before returning, so the chip is | 1031 | * Do this also before returning, so the chip is |
1026 | * ready for the next command. | 1032 | * ready for the next command. |
1027 | */ | 1033 | */ |
1028 | if (!this->dev_ready) | 1034 | if (!this->dev_ready) |
1029 | udelay (this->chip_delay); | 1035 | udelay (this->chip_delay); |
1030 | else | 1036 | else |
1031 | nand_wait_ready(mtd); | 1037 | nand_wait_ready(mtd); |
@@ -1033,17 +1039,17 @@ static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int | |||
1033 | /* All done, return happy */ | 1039 | /* All done, return happy */ |
1034 | if (!numpages) | 1040 | if (!numpages) |
1035 | return 0; | 1041 | return 0; |
1036 | 1042 | ||
1037 | 1043 | ||
1038 | /* Check, if the chip supports auto page increment */ | 1044 | /* Check, if the chip supports auto page increment */ |
1039 | if (!NAND_CANAUTOINCR(this)) | 1045 | if (!NAND_CANAUTOINCR(this)) |
1040 | this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page); | 1046 | this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page); |
1041 | } | 1047 | } |
1042 | /* | 1048 | /* |
1043 | * Terminate the read command. We come here in case of an error | 1049 | * Terminate the read command. We come here in case of an error |
1044 | * So we must issue a reset command. | 1050 | * So we must issue a reset command. |
1045 | */ | 1051 | */ |
1046 | out: | 1052 | out: |
1047 | this->cmdfunc (mtd, NAND_CMD_RESET, -1, -1); | 1053 | this->cmdfunc (mtd, NAND_CMD_RESET, -1, -1); |
1048 | return res; | 1054 | return res; |
1049 | } | 1055 | } |
@@ -1105,7 +1111,7 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
1105 | * NAND read with ECC | 1111 | * NAND read with ECC |
1106 | */ | 1112 | */ |
1107 | int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | 1113 | int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, |
1108 | size_t * retlen, u_char * buf, u_char * oob_buf, | 1114 | size_t * retlen, u_char * buf, u_char * oob_buf, |
1109 | struct nand_oobinfo *oobsel, int flags) | 1115 | struct nand_oobinfo *oobsel, int flags) |
1110 | { | 1116 | { |
1111 | 1117 | ||
@@ -1139,7 +1145,7 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
1139 | /* Autoplace of oob data ? Use the default placement scheme */ | 1145 | /* Autoplace of oob data ? Use the default placement scheme */ |
1140 | if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) | 1146 | if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) |
1141 | oobsel = this->autooob; | 1147 | oobsel = this->autooob; |
1142 | 1148 | ||
1143 | eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE; | 1149 | eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE; |
1144 | oob_config = oobsel->eccpos; | 1150 | oob_config = oobsel->eccpos; |
1145 | 1151 | ||
@@ -1157,28 +1163,28 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
1157 | end = mtd->oobblock; | 1163 | end = mtd->oobblock; |
1158 | ecc = this->eccsize; | 1164 | ecc = this->eccsize; |
1159 | eccbytes = this->eccbytes; | 1165 | eccbytes = this->eccbytes; |
1160 | 1166 | ||
1161 | if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME)) | 1167 | if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME)) |
1162 | compareecc = 0; | 1168 | compareecc = 0; |
1163 | 1169 | ||
1164 | oobreadlen = mtd->oobsize; | 1170 | oobreadlen = mtd->oobsize; |
1165 | if (this->options & NAND_HWECC_SYNDROME) | 1171 | if (this->options & NAND_HWECC_SYNDROME) |
1166 | oobreadlen -= oobsel->eccbytes; | 1172 | oobreadlen -= oobsel->eccbytes; |
1167 | 1173 | ||
1168 | /* Loop until all data read */ | 1174 | /* Loop until all data read */ |
1169 | while (read < len) { | 1175 | while (read < len) { |
1170 | 1176 | ||
1171 | int aligned = (!col && (len - read) >= end); | 1177 | int aligned = (!col && (len - read) >= end); |
1172 | /* | 1178 | /* |
1173 | * If the read is not page aligned, we have to read into data buffer | 1179 | * If the read is not page aligned, we have to read into data buffer |
1174 | * due to ecc, else we read into return buffer direct | 1180 | * due to ecc, else we read into return buffer direct |
1175 | */ | 1181 | */ |
1176 | if (aligned) | 1182 | if (aligned) |
1177 | data_poi = &buf[read]; | 1183 | data_poi = &buf[read]; |
1178 | else | 1184 | else |
1179 | data_poi = this->data_buf; | 1185 | data_poi = this->data_buf; |
1180 | 1186 | ||
1181 | /* Check, if we have this page in the buffer | 1187 | /* Check, if we have this page in the buffer |
1182 | * | 1188 | * |
1183 | * FIXME: Make it work when we must provide oob data too, | 1189 | * FIXME: Make it work when we must provide oob data too, |
1184 | * check the usage of data_buf oob field | 1190 | * check the usage of data_buf oob field |
@@ -1194,7 +1200,7 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
1194 | if (sndcmd) { | 1200 | if (sndcmd) { |
1195 | this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page); | 1201 | this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page); |
1196 | sndcmd = 0; | 1202 | sndcmd = 0; |
1197 | } | 1203 | } |
1198 | 1204 | ||
1199 | /* get oob area, if we have no oob buffer from fs-driver */ | 1205 | /* get oob area, if we have no oob buffer from fs-driver */ |
1200 | if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE || | 1206 | if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE || |
@@ -1202,7 +1208,7 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
1202 | oob_data = &this->data_buf[end]; | 1208 | oob_data = &this->data_buf[end]; |
1203 | 1209 | ||
1204 | eccsteps = this->eccsteps; | 1210 | eccsteps = this->eccsteps; |
1205 | 1211 | ||
1206 | switch (eccmode) { | 1212 | switch (eccmode) { |
1207 | case NAND_ECC_NONE: { /* No ECC, Read in a page */ | 1213 | case NAND_ECC_NONE: { /* No ECC, Read in a page */ |
1208 | static unsigned long lastwhinge = 0; | 1214 | static unsigned long lastwhinge = 0; |
@@ -1213,12 +1219,12 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
1213 | this->read_buf(mtd, data_poi, end); | 1219 | this->read_buf(mtd, data_poi, end); |
1214 | break; | 1220 | break; |
1215 | } | 1221 | } |
1216 | 1222 | ||
1217 | case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */ | 1223 | case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */ |
1218 | this->read_buf(mtd, data_poi, end); | 1224 | this->read_buf(mtd, data_poi, end); |
1219 | for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=3, datidx += ecc) | 1225 | for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=3, datidx += ecc) |
1220 | this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]); | 1226 | this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]); |
1221 | break; | 1227 | break; |
1222 | 1228 | ||
1223 | default: | 1229 | default: |
1224 | for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=eccbytes, datidx += ecc) { | 1230 | for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=eccbytes, datidx += ecc) { |
@@ -1237,15 +1243,15 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
1237 | * does the error correction on the fly */ | 1243 | * does the error correction on the fly */ |
1238 | ecc_status = this->correct_data(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]); | 1244 | ecc_status = this->correct_data(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]); |
1239 | if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) { | 1245 | if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) { |
1240 | DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " | 1246 | DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " |
1241 | "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr); | 1247 | "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr); |
1242 | ecc_failed++; | 1248 | ecc_failed++; |
1243 | } | 1249 | } |
1244 | } else { | 1250 | } else { |
1245 | this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]); | 1251 | this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]); |
1246 | } | 1252 | } |
1247 | } | 1253 | } |
1248 | break; | 1254 | break; |
1249 | } | 1255 | } |
1250 | 1256 | ||
1251 | /* read oobdata */ | 1257 | /* read oobdata */ |
@@ -1253,8 +1259,8 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
1253 | 1259 | ||
1254 | /* Skip ECC check, if not requested (ECC_NONE or HW_ECC with syndromes) */ | 1260 | /* Skip ECC check, if not requested (ECC_NONE or HW_ECC with syndromes) */ |
1255 | if (!compareecc) | 1261 | if (!compareecc) |
1256 | goto readoob; | 1262 | goto readoob; |
1257 | 1263 | ||
1258 | /* Pick the ECC bytes out of the oob data */ | 1264 | /* Pick the ECC bytes out of the oob data */ |
1259 | for (j = 0; j < oobsel->eccbytes; j++) | 1265 | for (j = 0; j < oobsel->eccbytes; j++) |
1260 | ecc_code[j] = oob_data[oob_config[j]]; | 1266 | ecc_code[j] = oob_data[oob_config[j]]; |
@@ -1262,24 +1268,24 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
1262 | /* correct data, if neccecary */ | 1268 | /* correct data, if neccecary */ |
1263 | for (i = 0, j = 0, datidx = 0; i < this->eccsteps; i++, datidx += ecc) { | 1269 | for (i = 0, j = 0, datidx = 0; i < this->eccsteps; i++, datidx += ecc) { |
1264 | ecc_status = this->correct_data(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]); | 1270 | ecc_status = this->correct_data(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]); |
1265 | 1271 | ||
1266 | /* Get next chunk of ecc bytes */ | 1272 | /* Get next chunk of ecc bytes */ |
1267 | j += eccbytes; | 1273 | j += eccbytes; |
1268 | 1274 | ||
1269 | /* Check, if we have a fs supplied oob-buffer, | 1275 | /* Check, if we have a fs supplied oob-buffer, |
1270 | * This is the legacy mode. Used by YAFFS1 | 1276 | * This is the legacy mode. Used by YAFFS1 |
1271 | * Should go away some day | 1277 | * Should go away some day |
1272 | */ | 1278 | */ |
1273 | if (oob_buf && oobsel->useecc == MTD_NANDECC_PLACE) { | 1279 | if (oob_buf && oobsel->useecc == MTD_NANDECC_PLACE) { |
1274 | int *p = (int *)(&oob_data[mtd->oobsize]); | 1280 | int *p = (int *)(&oob_data[mtd->oobsize]); |
1275 | p[i] = ecc_status; | 1281 | p[i] = ecc_status; |
1276 | } | 1282 | } |
1277 | 1283 | ||
1278 | if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) { | 1284 | if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) { |
1279 | DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page); | 1285 | DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page); |
1280 | ecc_failed++; | 1286 | ecc_failed++; |
1281 | } | 1287 | } |
1282 | } | 1288 | } |
1283 | 1289 | ||
1284 | readoob: | 1290 | readoob: |
1285 | /* check, if we have a fs supplied oob-buffer */ | 1291 | /* check, if we have a fs supplied oob-buffer */ |
@@ -1305,25 +1311,25 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
1305 | } | 1311 | } |
1306 | readdata: | 1312 | readdata: |
1307 | /* Partial page read, transfer data into fs buffer */ | 1313 | /* Partial page read, transfer data into fs buffer */ |
1308 | if (!aligned) { | 1314 | if (!aligned) { |
1309 | for (j = col; j < end && read < len; j++) | 1315 | for (j = col; j < end && read < len; j++) |
1310 | buf[read++] = data_poi[j]; | 1316 | buf[read++] = data_poi[j]; |
1311 | this->pagebuf = realpage; | 1317 | this->pagebuf = realpage; |
1312 | } else | 1318 | } else |
1313 | read += mtd->oobblock; | 1319 | read += mtd->oobblock; |
1314 | 1320 | ||
1315 | /* Apply delay or wait for ready/busy pin | 1321 | /* Apply delay or wait for ready/busy pin |
1316 | * Do this before the AUTOINCR check, so no problems | 1322 | * Do this before the AUTOINCR check, so no problems |
1317 | * arise if a chip which does auto increment | 1323 | * arise if a chip which does auto increment |
1318 | * is marked as NOAUTOINCR by the board driver. | 1324 | * is marked as NOAUTOINCR by the board driver. |
1319 | */ | 1325 | */ |
1320 | if (!this->dev_ready) | 1326 | if (!this->dev_ready) |
1321 | udelay (this->chip_delay); | 1327 | udelay (this->chip_delay); |
1322 | else | 1328 | else |
1323 | nand_wait_ready(mtd); | 1329 | nand_wait_ready(mtd); |
1324 | 1330 | ||
1325 | if (read == len) | 1331 | if (read == len) |
1326 | break; | 1332 | break; |
1327 | 1333 | ||
1328 | /* For subsequent reads align to page boundary. */ | 1334 | /* For subsequent reads align to page boundary. */ |
1329 | col = 0; | 1335 | col = 0; |
@@ -1337,11 +1343,11 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
1337 | this->select_chip(mtd, -1); | 1343 | this->select_chip(mtd, -1); |
1338 | this->select_chip(mtd, chipnr); | 1344 | this->select_chip(mtd, chipnr); |
1339 | } | 1345 | } |
1340 | /* Check, if the chip supports auto page increment | 1346 | /* Check, if the chip supports auto page increment |
1341 | * or if we have hit a block boundary. | 1347 | * or if we have hit a block boundary. |
1342 | */ | 1348 | */ |
1343 | if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) | 1349 | if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) |
1344 | sndcmd = 1; | 1350 | sndcmd = 1; |
1345 | } | 1351 | } |
1346 | 1352 | ||
1347 | /* Deselect and wake up anyone waiting on the device */ | 1353 | /* Deselect and wake up anyone waiting on the device */ |
@@ -1378,7 +1384,7 @@ static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t | |||
1378 | /* Shift to get page */ | 1384 | /* Shift to get page */ |
1379 | page = (int)(from >> this->page_shift); | 1385 | page = (int)(from >> this->page_shift); |
1380 | chipnr = (int)(from >> this->chip_shift); | 1386 | chipnr = (int)(from >> this->chip_shift); |
1381 | 1387 | ||
1382 | /* Mask to get column */ | 1388 | /* Mask to get column */ |
1383 | col = from & (mtd->oobsize - 1); | 1389 | col = from & (mtd->oobsize - 1); |
1384 | 1390 | ||
@@ -1400,7 +1406,7 @@ static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t | |||
1400 | 1406 | ||
1401 | /* Send the read command */ | 1407 | /* Send the read command */ |
1402 | this->cmdfunc (mtd, NAND_CMD_READOOB, col, page & this->pagemask); | 1408 | this->cmdfunc (mtd, NAND_CMD_READOOB, col, page & this->pagemask); |
1403 | /* | 1409 | /* |
1404 | * Read the data, if we read more than one page | 1410 | * Read the data, if we read more than one page |
1405 | * oob data, let the device transfer the data ! | 1411 | * oob data, let the device transfer the data ! |
1406 | */ | 1412 | */ |
@@ -1422,20 +1428,20 @@ static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t | |||
1422 | this->select_chip(mtd, -1); | 1428 | this->select_chip(mtd, -1); |
1423 | this->select_chip(mtd, chipnr); | 1429 | this->select_chip(mtd, chipnr); |
1424 | } | 1430 | } |
1425 | 1431 | ||
1426 | /* Apply delay or wait for ready/busy pin | 1432 | /* Apply delay or wait for ready/busy pin |
1427 | * Do this before the AUTOINCR check, so no problems | 1433 | * Do this before the AUTOINCR check, so no problems |
1428 | * arise if a chip which does auto increment | 1434 | * arise if a chip which does auto increment |
1429 | * is marked as NOAUTOINCR by the board driver. | 1435 | * is marked as NOAUTOINCR by the board driver. |
1430 | */ | 1436 | */ |
1431 | if (!this->dev_ready) | 1437 | if (!this->dev_ready) |
1432 | udelay (this->chip_delay); | 1438 | udelay (this->chip_delay); |
1433 | else | 1439 | else |
1434 | nand_wait_ready(mtd); | 1440 | nand_wait_ready(mtd); |
1435 | 1441 | ||
1436 | /* Check, if the chip supports auto page increment | 1442 | /* Check, if the chip supports auto page increment |
1437 | * or if we have hit a block boundary. | 1443 | * or if we have hit a block boundary. |
1438 | */ | 1444 | */ |
1439 | if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) { | 1445 | if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) { |
1440 | /* For subsequent page reads set offset to 0 */ | 1446 | /* For subsequent page reads set offset to 0 */ |
1441 | this->cmdfunc (mtd, NAND_CMD_READOOB, 0x0, page & this->pagemask); | 1447 | this->cmdfunc (mtd, NAND_CMD_READOOB, 0x0, page & this->pagemask); |
@@ -1481,27 +1487,27 @@ int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, | |||
1481 | nand_get_device (this, mtd , FL_READING); | 1487 | nand_get_device (this, mtd , FL_READING); |
1482 | 1488 | ||
1483 | this->select_chip (mtd, chip); | 1489 | this->select_chip (mtd, chip); |
1484 | 1490 | ||
1485 | /* Add requested oob length */ | 1491 | /* Add requested oob length */ |
1486 | len += ooblen; | 1492 | len += ooblen; |
1487 | 1493 | ||
1488 | while (len) { | 1494 | while (len) { |
1489 | if (sndcmd) | 1495 | if (sndcmd) |
1490 | this->cmdfunc (mtd, NAND_CMD_READ0, 0, page & this->pagemask); | 1496 | this->cmdfunc (mtd, NAND_CMD_READ0, 0, page & this->pagemask); |
1491 | sndcmd = 0; | 1497 | sndcmd = 0; |
1492 | 1498 | ||
1493 | this->read_buf (mtd, &buf[cnt], pagesize); | 1499 | this->read_buf (mtd, &buf[cnt], pagesize); |
1494 | 1500 | ||
1495 | len -= pagesize; | 1501 | len -= pagesize; |
1496 | cnt += pagesize; | 1502 | cnt += pagesize; |
1497 | page++; | 1503 | page++; |
1498 | 1504 | ||
1499 | if (!this->dev_ready) | 1505 | if (!this->dev_ready) |
1500 | udelay (this->chip_delay); | 1506 | udelay (this->chip_delay); |
1501 | else | 1507 | else |
1502 | nand_wait_ready(mtd); | 1508 | nand_wait_ready(mtd); |
1503 | 1509 | ||
1504 | /* Check, if the chip supports auto page increment */ | 1510 | /* Check, if the chip supports auto page increment */ |
1505 | if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) | 1511 | if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) |
1506 | sndcmd = 1; | 1512 | sndcmd = 1; |
1507 | } | 1513 | } |
@@ -1512,8 +1518,8 @@ int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, | |||
1512 | } | 1518 | } |
1513 | 1519 | ||
1514 | 1520 | ||
1515 | /** | 1521 | /** |
1516 | * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer | 1522 | * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer |
1517 | * @mtd: MTD device structure | 1523 | * @mtd: MTD device structure |
1518 | * @fsbuf: buffer given by fs driver | 1524 | * @fsbuf: buffer given by fs driver |
1519 | * @oobsel: out of band selection structre | 1525 | * @oobsel: out of band selection structre |
@@ -1542,20 +1548,20 @@ static u_char * nand_prepare_oobbuf (struct mtd_info *mtd, u_char *fsbuf, struct | |||
1542 | int i, len, ofs; | 1548 | int i, len, ofs; |
1543 | 1549 | ||
1544 | /* Zero copy fs supplied buffer */ | 1550 | /* Zero copy fs supplied buffer */ |
1545 | if (fsbuf && !autoplace) | 1551 | if (fsbuf && !autoplace) |
1546 | return fsbuf; | 1552 | return fsbuf; |
1547 | 1553 | ||
1548 | /* Check, if the buffer must be filled with ff again */ | 1554 | /* Check, if the buffer must be filled with ff again */ |
1549 | if (this->oobdirty) { | 1555 | if (this->oobdirty) { |
1550 | memset (this->oob_buf, 0xff, | 1556 | memset (this->oob_buf, 0xff, |
1551 | mtd->oobsize << (this->phys_erase_shift - this->page_shift)); | 1557 | mtd->oobsize << (this->phys_erase_shift - this->page_shift)); |
1552 | this->oobdirty = 0; | 1558 | this->oobdirty = 0; |
1553 | } | 1559 | } |
1554 | 1560 | ||
1555 | /* If we have no autoplacement or no fs buffer use the internal one */ | 1561 | /* If we have no autoplacement or no fs buffer use the internal one */ |
1556 | if (!autoplace || !fsbuf) | 1562 | if (!autoplace || !fsbuf) |
1557 | return this->oob_buf; | 1563 | return this->oob_buf; |
1558 | 1564 | ||
1559 | /* Walk through the pages and place the data */ | 1565 | /* Walk through the pages and place the data */ |
1560 | this->oobdirty = 1; | 1566 | this->oobdirty = 1; |
1561 | ofs = 0; | 1567 | ofs = 0; |
@@ -1589,7 +1595,7 @@ static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * ret | |||
1589 | { | 1595 | { |
1590 | return (nand_write_ecc (mtd, to, len, retlen, buf, NULL, NULL)); | 1596 | return (nand_write_ecc (mtd, to, len, retlen, buf, NULL, NULL)); |
1591 | } | 1597 | } |
1592 | 1598 | ||
1593 | /** | 1599 | /** |
1594 | * nand_write_ecc - [MTD Interface] NAND write with ECC | 1600 | * nand_write_ecc - [MTD Interface] NAND write with ECC |
1595 | * @mtd: MTD device structure | 1601 | * @mtd: MTD device structure |
@@ -1622,7 +1628,7 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, | |||
1622 | return -EINVAL; | 1628 | return -EINVAL; |
1623 | } | 1629 | } |
1624 | 1630 | ||
1625 | /* reject writes, which are not page aligned */ | 1631 | /* reject writes, which are not page aligned */ |
1626 | if (NOTALIGNED (to) || NOTALIGNED(len)) { | 1632 | if (NOTALIGNED (to) || NOTALIGNED(len)) { |
1627 | printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n"); | 1633 | printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n"); |
1628 | return -EINVAL; | 1634 | return -EINVAL; |
@@ -1641,14 +1647,14 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, | |||
1641 | goto out; | 1647 | goto out; |
1642 | 1648 | ||
1643 | /* if oobsel is NULL, use chip defaults */ | 1649 | /* if oobsel is NULL, use chip defaults */ |
1644 | if (oobsel == NULL) | 1650 | if (oobsel == NULL) |
1645 | oobsel = &mtd->oobinfo; | 1651 | oobsel = &mtd->oobinfo; |
1646 | 1652 | ||
1647 | /* Autoplace of oob data ? Use the default placement scheme */ | 1653 | /* Autoplace of oob data ? Use the default placement scheme */ |
1648 | if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) { | 1654 | if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) { |
1649 | oobsel = this->autooob; | 1655 | oobsel = this->autooob; |
1650 | autoplace = 1; | 1656 | autoplace = 1; |
1651 | } | 1657 | } |
1652 | if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR) | 1658 | if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR) |
1653 | autoplace = 1; | 1659 | autoplace = 1; |
1654 | 1660 | ||
@@ -1656,9 +1662,9 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, | |||
1656 | totalpages = len >> this->page_shift; | 1662 | totalpages = len >> this->page_shift; |
1657 | page = (int) (to >> this->page_shift); | 1663 | page = (int) (to >> this->page_shift); |
1658 | /* Invalidate the page cache, if we write to the cached page */ | 1664 | /* Invalidate the page cache, if we write to the cached page */ |
1659 | if (page <= this->pagebuf && this->pagebuf < (page + totalpages)) | 1665 | if (page <= this->pagebuf && this->pagebuf < (page + totalpages)) |
1660 | this->pagebuf = -1; | 1666 | this->pagebuf = -1; |
1661 | 1667 | ||
1662 | /* Set it relative to chip */ | 1668 | /* Set it relative to chip */ |
1663 | page &= this->pagemask; | 1669 | page &= this->pagemask; |
1664 | startpage = page; | 1670 | startpage = page; |
@@ -1680,14 +1686,14 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, | |||
1680 | if (ret) { | 1686 | if (ret) { |
1681 | DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: write_page failed %d\n", ret); | 1687 | DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: write_page failed %d\n", ret); |
1682 | goto out; | 1688 | goto out; |
1683 | } | 1689 | } |
1684 | /* Next oob page */ | 1690 | /* Next oob page */ |
1685 | oob += mtd->oobsize; | 1691 | oob += mtd->oobsize; |
1686 | /* Update written bytes count */ | 1692 | /* Update written bytes count */ |
1687 | written += mtd->oobblock; | 1693 | written += mtd->oobblock; |
1688 | if (written == len) | 1694 | if (written == len) |
1689 | goto cmp; | 1695 | goto cmp; |
1690 | 1696 | ||
1691 | /* Increment page address */ | 1697 | /* Increment page address */ |
1692 | page++; | 1698 | page++; |
1693 | 1699 | ||
@@ -1698,13 +1704,13 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, | |||
1698 | if (!(page & (ppblock - 1))){ | 1704 | if (!(page & (ppblock - 1))){ |
1699 | int ofs; | 1705 | int ofs; |
1700 | this->data_poi = bufstart; | 1706 | this->data_poi = bufstart; |
1701 | ret = nand_verify_pages (mtd, this, startpage, | 1707 | ret = nand_verify_pages (mtd, this, startpage, |
1702 | page - startpage, | 1708 | page - startpage, |
1703 | oobbuf, oobsel, chipnr, (eccbuf != NULL)); | 1709 | oobbuf, oobsel, chipnr, (eccbuf != NULL)); |
1704 | if (ret) { | 1710 | if (ret) { |
1705 | DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret); | 1711 | DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret); |
1706 | goto out; | 1712 | goto out; |
1707 | } | 1713 | } |
1708 | *retlen = written; | 1714 | *retlen = written; |
1709 | 1715 | ||
1710 | ofs = autoplace ? mtd->oobavail : mtd->oobsize; | 1716 | ofs = autoplace ? mtd->oobavail : mtd->oobsize; |
@@ -1714,8 +1720,9 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, | |||
1714 | numpages = min (totalpages, ppblock); | 1720 | numpages = min (totalpages, ppblock); |
1715 | page &= this->pagemask; | 1721 | page &= this->pagemask; |
1716 | startpage = page; | 1722 | startpage = page; |
1717 | oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel, | 1723 | oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel, |
1718 | autoplace, numpages); | 1724 | autoplace, numpages); |
1725 | oob = 0; | ||
1719 | /* Check, if we cross a chip boundary */ | 1726 | /* Check, if we cross a chip boundary */ |
1720 | if (!page) { | 1727 | if (!page) { |
1721 | chipnr++; | 1728 | chipnr++; |
@@ -1731,7 +1738,7 @@ cmp: | |||
1731 | oobbuf, oobsel, chipnr, (eccbuf != NULL)); | 1738 | oobbuf, oobsel, chipnr, (eccbuf != NULL)); |
1732 | if (!ret) | 1739 | if (!ret) |
1733 | *retlen = written; | 1740 | *retlen = written; |
1734 | else | 1741 | else |
1735 | DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret); | 1742 | DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret); |
1736 | 1743 | ||
1737 | out: | 1744 | out: |
@@ -1791,7 +1798,7 @@ static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * | |||
1791 | /* Check, if it is write protected */ | 1798 | /* Check, if it is write protected */ |
1792 | if (nand_check_wp(mtd)) | 1799 | if (nand_check_wp(mtd)) |
1793 | goto out; | 1800 | goto out; |
1794 | 1801 | ||
1795 | /* Invalidate the page cache, if we write to the cached page */ | 1802 | /* Invalidate the page cache, if we write to the cached page */ |
1796 | if (page == this->pagebuf) | 1803 | if (page == this->pagebuf) |
1797 | this->pagebuf = -1; | 1804 | this->pagebuf = -1; |
@@ -1854,10 +1861,10 @@ out: | |||
1854 | * | 1861 | * |
1855 | * NAND write with kvec. This just calls the ecc function | 1862 | * NAND write with kvec. This just calls the ecc function |
1856 | */ | 1863 | */ |
1857 | static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, | 1864 | static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, |
1858 | loff_t to, size_t * retlen) | 1865 | loff_t to, size_t * retlen) |
1859 | { | 1866 | { |
1860 | return (nand_writev_ecc (mtd, vecs, count, to, retlen, NULL, NULL)); | 1867 | return (nand_writev_ecc (mtd, vecs, count, to, retlen, NULL, NULL)); |
1861 | } | 1868 | } |
1862 | 1869 | ||
1863 | /** | 1870 | /** |
@@ -1872,7 +1879,7 @@ static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned | |||
1872 | * | 1879 | * |
1873 | * NAND write with iovec with ecc | 1880 | * NAND write with iovec with ecc |
1874 | */ | 1881 | */ |
1875 | static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, | 1882 | static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, |
1876 | loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel) | 1883 | loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel) |
1877 | { | 1884 | { |
1878 | int i, page, len, total_len, ret = -EIO, written = 0, chipnr; | 1885 | int i, page, len, total_len, ret = -EIO, written = 0, chipnr; |
@@ -1898,7 +1905,7 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig | |||
1898 | return -EINVAL; | 1905 | return -EINVAL; |
1899 | } | 1906 | } |
1900 | 1907 | ||
1901 | /* reject writes, which are not page aligned */ | 1908 | /* reject writes, which are not page aligned */ |
1902 | if (NOTALIGNED (to) || NOTALIGNED(total_len)) { | 1909 | if (NOTALIGNED (to) || NOTALIGNED(total_len)) { |
1903 | printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n"); | 1910 | printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n"); |
1904 | return -EINVAL; | 1911 | return -EINVAL; |
@@ -1917,21 +1924,21 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig | |||
1917 | goto out; | 1924 | goto out; |
1918 | 1925 | ||
1919 | /* if oobsel is NULL, use chip defaults */ | 1926 | /* if oobsel is NULL, use chip defaults */ |
1920 | if (oobsel == NULL) | 1927 | if (oobsel == NULL) |
1921 | oobsel = &mtd->oobinfo; | 1928 | oobsel = &mtd->oobinfo; |
1922 | 1929 | ||
1923 | /* Autoplace of oob data ? Use the default placement scheme */ | 1930 | /* Autoplace of oob data ? Use the default placement scheme */ |
1924 | if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) { | 1931 | if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) { |
1925 | oobsel = this->autooob; | 1932 | oobsel = this->autooob; |
1926 | autoplace = 1; | 1933 | autoplace = 1; |
1927 | } | 1934 | } |
1928 | if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR) | 1935 | if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR) |
1929 | autoplace = 1; | 1936 | autoplace = 1; |
1930 | 1937 | ||
1931 | /* Setup start page */ | 1938 | /* Setup start page */ |
1932 | page = (int) (to >> this->page_shift); | 1939 | page = (int) (to >> this->page_shift); |
1933 | /* Invalidate the page cache, if we write to the cached page */ | 1940 | /* Invalidate the page cache, if we write to the cached page */ |
1934 | if (page <= this->pagebuf && this->pagebuf < ((to + total_len) >> this->page_shift)) | 1941 | if (page <= this->pagebuf && this->pagebuf < ((to + total_len) >> this->page_shift)) |
1935 | this->pagebuf = -1; | 1942 | this->pagebuf = -1; |
1936 | 1943 | ||
1937 | startpage = page & this->pagemask; | 1944 | startpage = page & this->pagemask; |
@@ -1955,10 +1962,10 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig | |||
1955 | oob = 0; | 1962 | oob = 0; |
1956 | for (i = 1; i <= numpages; i++) { | 1963 | for (i = 1; i <= numpages; i++) { |
1957 | /* Write one page. If this is the last page to write | 1964 | /* Write one page. If this is the last page to write |
1958 | * then use the real pageprogram command, else select | 1965 | * then use the real pageprogram command, else select |
1959 | * cached programming if supported by the chip. | 1966 | * cached programming if supported by the chip. |
1960 | */ | 1967 | */ |
1961 | ret = nand_write_page (mtd, this, page & this->pagemask, | 1968 | ret = nand_write_page (mtd, this, page & this->pagemask, |
1962 | &oobbuf[oob], oobsel, i != numpages); | 1969 | &oobbuf[oob], oobsel, i != numpages); |
1963 | if (ret) | 1970 | if (ret) |
1964 | goto out; | 1971 | goto out; |
@@ -1974,12 +1981,12 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig | |||
1974 | count--; | 1981 | count--; |
1975 | } | 1982 | } |
1976 | } else { | 1983 | } else { |
1977 | /* We must use the internal buffer, read data out of each | 1984 | /* We must use the internal buffer, read data out of each |
1978 | * tuple until we have a full page to write | 1985 | * tuple until we have a full page to write |
1979 | */ | 1986 | */ |
1980 | int cnt = 0; | 1987 | int cnt = 0; |
1981 | while (cnt < mtd->oobblock) { | 1988 | while (cnt < mtd->oobblock) { |
1982 | if (vecs->iov_base != NULL && vecs->iov_len) | 1989 | if (vecs->iov_base != NULL && vecs->iov_len) |
1983 | this->data_buf[cnt++] = ((u_char *) vecs->iov_base)[len++]; | 1990 | this->data_buf[cnt++] = ((u_char *) vecs->iov_base)[len++]; |
1984 | /* Check, if we have to switch to the next tuple */ | 1991 | /* Check, if we have to switch to the next tuple */ |
1985 | if (len >= (int) vecs->iov_len) { | 1992 | if (len >= (int) vecs->iov_len) { |
@@ -1988,10 +1995,10 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig | |||
1988 | count--; | 1995 | count--; |
1989 | } | 1996 | } |
1990 | } | 1997 | } |
1991 | this->pagebuf = page; | 1998 | this->pagebuf = page; |
1992 | this->data_poi = this->data_buf; | 1999 | this->data_poi = this->data_buf; |
1993 | bufstart = this->data_poi; | 2000 | bufstart = this->data_poi; |
1994 | numpages = 1; | 2001 | numpages = 1; |
1995 | oobbuf = nand_prepare_oobbuf (mtd, NULL, oobsel, autoplace, numpages); | 2002 | oobbuf = nand_prepare_oobbuf (mtd, NULL, oobsel, autoplace, numpages); |
1996 | ret = nand_write_page (mtd, this, page & this->pagemask, | 2003 | ret = nand_write_page (mtd, this, page & this->pagemask, |
1997 | oobbuf, oobsel, 0); | 2004 | oobbuf, oobsel, 0); |
@@ -2004,7 +2011,7 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig | |||
2004 | ret = nand_verify_pages (mtd, this, startpage, numpages, oobbuf, oobsel, chipnr, 0); | 2011 | ret = nand_verify_pages (mtd, this, startpage, numpages, oobbuf, oobsel, chipnr, 0); |
2005 | if (ret) | 2012 | if (ret) |
2006 | goto out; | 2013 | goto out; |
2007 | 2014 | ||
2008 | written += mtd->oobblock * numpages; | 2015 | written += mtd->oobblock * numpages; |
2009 | /* All done ? */ | 2016 | /* All done ? */ |
2010 | if (!count) | 2017 | if (!count) |
@@ -2072,7 +2079,7 @@ static int nand_erase (struct mtd_info *mtd, struct erase_info *instr) | |||
2072 | { | 2079 | { |
2073 | return nand_erase_nand (mtd, instr, 0); | 2080 | return nand_erase_nand (mtd, instr, 0); |
2074 | } | 2081 | } |
2075 | 2082 | ||
2076 | #define BBT_PAGE_MASK 0xffffff3f | 2083 | #define BBT_PAGE_MASK 0xffffff3f |
2077 | /** | 2084 | /** |
2078 | * nand_erase_intern - [NAND Interface] erase block(s) | 2085 | * nand_erase_intern - [NAND Interface] erase block(s) |
@@ -2154,14 +2161,14 @@ int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbb | |||
2154 | instr->state = MTD_ERASE_FAILED; | 2161 | instr->state = MTD_ERASE_FAILED; |
2155 | goto erase_exit; | 2162 | goto erase_exit; |
2156 | } | 2163 | } |
2157 | 2164 | ||
2158 | /* Invalidate the page cache, if we erase the block which contains | 2165 | /* Invalidate the page cache, if we erase the block which contains |
2159 | the current cached page */ | 2166 | the current cached page */ |
2160 | if (page <= this->pagebuf && this->pagebuf < (page + pages_per_block)) | 2167 | if (page <= this->pagebuf && this->pagebuf < (page + pages_per_block)) |
2161 | this->pagebuf = -1; | 2168 | this->pagebuf = -1; |
2162 | 2169 | ||
2163 | this->erase_cmd (mtd, page & this->pagemask); | 2170 | this->erase_cmd (mtd, page & this->pagemask); |
2164 | 2171 | ||
2165 | status = this->waitfunc (mtd, this, FL_ERASING); | 2172 | status = this->waitfunc (mtd, this, FL_ERASING); |
2166 | 2173 | ||
2167 | /* See if operation failed and additional status checks are available */ | 2174 | /* See if operation failed and additional status checks are available */ |
@@ -2179,12 +2186,12 @@ int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbb | |||
2179 | 2186 | ||
2180 | /* if BBT requires refresh, set the BBT rewrite flag to the page being erased */ | 2187 | /* if BBT requires refresh, set the BBT rewrite flag to the page being erased */ |
2181 | if (this->options & BBT_AUTO_REFRESH) { | 2188 | if (this->options & BBT_AUTO_REFRESH) { |
2182 | if (((page & BBT_PAGE_MASK) == bbt_masked_page) && | 2189 | if (((page & BBT_PAGE_MASK) == bbt_masked_page) && |
2183 | (page != this->bbt_td->pages[chipnr])) { | 2190 | (page != this->bbt_td->pages[chipnr])) { |
2184 | rewrite_bbt[chipnr] = (page << this->page_shift); | 2191 | rewrite_bbt[chipnr] = (page << this->page_shift); |
2185 | } | 2192 | } |
2186 | } | 2193 | } |
2187 | 2194 | ||
2188 | /* Increment page address and decrement length */ | 2195 | /* Increment page address and decrement length */ |
2189 | len -= (1 << this->phys_erase_shift); | 2196 | len -= (1 << this->phys_erase_shift); |
2190 | page += pages_per_block; | 2197 | page += pages_per_block; |
@@ -2195,7 +2202,7 @@ int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbb | |||
2195 | this->select_chip(mtd, -1); | 2202 | this->select_chip(mtd, -1); |
2196 | this->select_chip(mtd, chipnr); | 2203 | this->select_chip(mtd, chipnr); |
2197 | 2204 | ||
2198 | /* if BBT requires refresh and BBT-PERCHIP, | 2205 | /* if BBT requires refresh and BBT-PERCHIP, |
2199 | * set the BBT page mask to see if this BBT should be rewritten */ | 2206 | * set the BBT page mask to see if this BBT should be rewritten */ |
2200 | if ((this->options & BBT_AUTO_REFRESH) && (this->bbt_td->options & NAND_BBT_PERCHIP)) { | 2207 | if ((this->options & BBT_AUTO_REFRESH) && (this->bbt_td->options & NAND_BBT_PERCHIP)) { |
2201 | bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK; | 2208 | bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK; |
@@ -2220,7 +2227,7 @@ erase_exit: | |||
2220 | for (chipnr = 0; chipnr < this->numchips; chipnr++) { | 2227 | for (chipnr = 0; chipnr < this->numchips; chipnr++) { |
2221 | if (rewrite_bbt[chipnr]) { | 2228 | if (rewrite_bbt[chipnr]) { |
2222 | /* update the BBT for chip */ | 2229 | /* update the BBT for chip */ |
2223 | DEBUG (MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt (%d:0x%0x 0x%0x)\n", | 2230 | DEBUG (MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt (%d:0x%0x 0x%0x)\n", |
2224 | chipnr, rewrite_bbt[chipnr], this->bbt_td->pages[chipnr]); | 2231 | chipnr, rewrite_bbt[chipnr], this->bbt_td->pages[chipnr]); |
2225 | nand_update_bbt (mtd, rewrite_bbt[chipnr]); | 2232 | nand_update_bbt (mtd, rewrite_bbt[chipnr]); |
2226 | } | 2233 | } |
@@ -2258,9 +2265,9 @@ static void nand_sync (struct mtd_info *mtd) | |||
2258 | static int nand_block_isbad (struct mtd_info *mtd, loff_t ofs) | 2265 | static int nand_block_isbad (struct mtd_info *mtd, loff_t ofs) |
2259 | { | 2266 | { |
2260 | /* Check for invalid offset */ | 2267 | /* Check for invalid offset */ |
2261 | if (ofs > mtd->size) | 2268 | if (ofs > mtd->size) |
2262 | return -EINVAL; | 2269 | return -EINVAL; |
2263 | 2270 | ||
2264 | return nand_block_checkbad (mtd, ofs, 1, 0); | 2271 | return nand_block_checkbad (mtd, ofs, 1, 0); |
2265 | } | 2272 | } |
2266 | 2273 | ||
@@ -2285,6 +2292,34 @@ static int nand_block_markbad (struct mtd_info *mtd, loff_t ofs) | |||
2285 | } | 2292 | } |
2286 | 2293 | ||
2287 | /** | 2294 | /** |
2295 | * nand_suspend - [MTD Interface] Suspend the NAND flash | ||
2296 | * @mtd: MTD device structure | ||
2297 | */ | ||
2298 | static int nand_suspend(struct mtd_info *mtd) | ||
2299 | { | ||
2300 | struct nand_chip *this = mtd->priv; | ||
2301 | |||
2302 | return nand_get_device (this, mtd, FL_PM_SUSPENDED); | ||
2303 | } | ||
2304 | |||
2305 | /** | ||
2306 | * nand_resume - [MTD Interface] Resume the NAND flash | ||
2307 | * @mtd: MTD device structure | ||
2308 | */ | ||
2309 | static void nand_resume(struct mtd_info *mtd) | ||
2310 | { | ||
2311 | struct nand_chip *this = mtd->priv; | ||
2312 | |||
2313 | if (this->state == FL_PM_SUSPENDED) | ||
2314 | nand_release_device(mtd); | ||
2315 | else | ||
2316 | printk(KERN_ERR "resume() called for the chip which is not " | ||
2317 | "in suspended state\n"); | ||
2318 | |||
2319 | } | ||
2320 | |||
2321 | |||
2322 | /** | ||
2288 | * nand_scan - [NAND Interface] Scan for the NAND device | 2323 | * nand_scan - [NAND Interface] Scan for the NAND device |
2289 | * @mtd: MTD device structure | 2324 | * @mtd: MTD device structure |
2290 | * @maxchips: Number of chips to scan for | 2325 | * @maxchips: Number of chips to scan for |
@@ -2351,13 +2386,13 @@ int nand_scan (struct mtd_info *mtd, int maxchips) | |||
2351 | 2386 | ||
2352 | /* Print and store flash device information */ | 2387 | /* Print and store flash device information */ |
2353 | for (i = 0; nand_flash_ids[i].name != NULL; i++) { | 2388 | for (i = 0; nand_flash_ids[i].name != NULL; i++) { |
2354 | 2389 | ||
2355 | if (nand_dev_id != nand_flash_ids[i].id) | 2390 | if (nand_dev_id != nand_flash_ids[i].id) |
2356 | continue; | 2391 | continue; |
2357 | 2392 | ||
2358 | if (!mtd->name) mtd->name = nand_flash_ids[i].name; | 2393 | if (!mtd->name) mtd->name = nand_flash_ids[i].name; |
2359 | this->chipsize = nand_flash_ids[i].chipsize << 20; | 2394 | this->chipsize = nand_flash_ids[i].chipsize << 20; |
2360 | 2395 | ||
2361 | /* New devices have all the information in additional id bytes */ | 2396 | /* New devices have all the information in additional id bytes */ |
2362 | if (!nand_flash_ids[i].pagesize) { | 2397 | if (!nand_flash_ids[i].pagesize) { |
2363 | int extid; | 2398 | int extid; |
@@ -2369,14 +2404,14 @@ int nand_scan (struct mtd_info *mtd, int maxchips) | |||
2369 | mtd->oobblock = 1024 << (extid & 0x3); | 2404 | mtd->oobblock = 1024 << (extid & 0x3); |
2370 | extid >>= 2; | 2405 | extid >>= 2; |
2371 | /* Calc oobsize */ | 2406 | /* Calc oobsize */ |
2372 | mtd->oobsize = (8 << (extid & 0x03)) * (mtd->oobblock / 512); | 2407 | mtd->oobsize = (8 << (extid & 0x01)) * (mtd->oobblock >> 9); |
2373 | extid >>= 2; | 2408 | extid >>= 2; |
2374 | /* Calc blocksize. Blocksize is multiples of 64KiB */ | 2409 | /* Calc blocksize. Blocksize is multiples of 64KiB */ |
2375 | mtd->erasesize = (64 * 1024) << (extid & 0x03); | 2410 | mtd->erasesize = (64 * 1024) << (extid & 0x03); |
2376 | extid >>= 2; | 2411 | extid >>= 2; |
2377 | /* Get buswidth information */ | 2412 | /* Get buswidth information */ |
2378 | busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; | 2413 | busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; |
2379 | 2414 | ||
2380 | } else { | 2415 | } else { |
2381 | /* Old devices have this data hardcoded in the | 2416 | /* Old devices have this data hardcoded in the |
2382 | * device id table */ | 2417 | * device id table */ |
@@ -2396,23 +2431,23 @@ int nand_scan (struct mtd_info *mtd, int maxchips) | |||
2396 | * this correct ! */ | 2431 | * this correct ! */ |
2397 | if (busw != (this->options & NAND_BUSWIDTH_16)) { | 2432 | if (busw != (this->options & NAND_BUSWIDTH_16)) { |
2398 | printk (KERN_INFO "NAND device: Manufacturer ID:" | 2433 | printk (KERN_INFO "NAND device: Manufacturer ID:" |
2399 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, | 2434 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, |
2400 | nand_manuf_ids[maf_id].name , mtd->name); | 2435 | nand_manuf_ids[maf_id].name , mtd->name); |
2401 | printk (KERN_WARNING | 2436 | printk (KERN_WARNING |
2402 | "NAND bus width %d instead %d bit\n", | 2437 | "NAND bus width %d instead %d bit\n", |
2403 | (this->options & NAND_BUSWIDTH_16) ? 16 : 8, | 2438 | (this->options & NAND_BUSWIDTH_16) ? 16 : 8, |
2404 | busw ? 16 : 8); | 2439 | busw ? 16 : 8); |
2405 | this->select_chip(mtd, -1); | 2440 | this->select_chip(mtd, -1); |
2406 | return 1; | 2441 | return 1; |
2407 | } | 2442 | } |
2408 | 2443 | ||
2409 | /* Calculate the address shift from the page size */ | 2444 | /* Calculate the address shift from the page size */ |
2410 | this->page_shift = ffs(mtd->oobblock) - 1; | 2445 | this->page_shift = ffs(mtd->oobblock) - 1; |
2411 | this->bbt_erase_shift = this->phys_erase_shift = ffs(mtd->erasesize) - 1; | 2446 | this->bbt_erase_shift = this->phys_erase_shift = ffs(mtd->erasesize) - 1; |
2412 | this->chip_shift = ffs(this->chipsize) - 1; | 2447 | this->chip_shift = ffs(this->chipsize) - 1; |
2413 | 2448 | ||
2414 | /* Set the bad block position */ | 2449 | /* Set the bad block position */ |
2415 | this->badblockpos = mtd->oobblock > 512 ? | 2450 | this->badblockpos = mtd->oobblock > 512 ? |
2416 | NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS; | 2451 | NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS; |
2417 | 2452 | ||
2418 | /* Get chip options, preserve non chip based options */ | 2453 | /* Get chip options, preserve non chip based options */ |
@@ -2422,10 +2457,10 @@ int nand_scan (struct mtd_info *mtd, int maxchips) | |||
2422 | this->options |= NAND_NO_AUTOINCR; | 2457 | this->options |= NAND_NO_AUTOINCR; |
2423 | /* Check if this is a not a samsung device. Do not clear the options | 2458 | /* Check if this is a not a samsung device. Do not clear the options |
2424 | * for chips which are not having an extended id. | 2459 | * for chips which are not having an extended id. |
2425 | */ | 2460 | */ |
2426 | if (nand_maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize) | 2461 | if (nand_maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize) |
2427 | this->options &= ~NAND_SAMSUNG_LP_OPTIONS; | 2462 | this->options &= ~NAND_SAMSUNG_LP_OPTIONS; |
2428 | 2463 | ||
2429 | /* Check for AND chips with 4 page planes */ | 2464 | /* Check for AND chips with 4 page planes */ |
2430 | if (this->options & NAND_4PAGE_ARRAY) | 2465 | if (this->options & NAND_4PAGE_ARRAY) |
2431 | this->erase_cmd = multi_erase_cmd; | 2466 | this->erase_cmd = multi_erase_cmd; |
@@ -2435,9 +2470,9 @@ int nand_scan (struct mtd_info *mtd, int maxchips) | |||
2435 | /* Do not replace user supplied command function ! */ | 2470 | /* Do not replace user supplied command function ! */ |
2436 | if (mtd->oobblock > 512 && this->cmdfunc == nand_command) | 2471 | if (mtd->oobblock > 512 && this->cmdfunc == nand_command) |
2437 | this->cmdfunc = nand_command_lp; | 2472 | this->cmdfunc = nand_command_lp; |
2438 | 2473 | ||
2439 | printk (KERN_INFO "NAND device: Manufacturer ID:" | 2474 | printk (KERN_INFO "NAND device: Manufacturer ID:" |
2440 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, | 2475 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, |
2441 | nand_manuf_ids[maf_id].name , nand_flash_ids[i].name); | 2476 | nand_manuf_ids[maf_id].name , nand_flash_ids[i].name); |
2442 | break; | 2477 | break; |
2443 | } | 2478 | } |
@@ -2461,7 +2496,7 @@ int nand_scan (struct mtd_info *mtd, int maxchips) | |||
2461 | } | 2496 | } |
2462 | if (i > 1) | 2497 | if (i > 1) |
2463 | printk(KERN_INFO "%d NAND chips detected\n", i); | 2498 | printk(KERN_INFO "%d NAND chips detected\n", i); |
2464 | 2499 | ||
2465 | /* Allocate buffers, if neccecary */ | 2500 | /* Allocate buffers, if neccecary */ |
2466 | if (!this->oob_buf) { | 2501 | if (!this->oob_buf) { |
2467 | size_t len; | 2502 | size_t len; |
@@ -2473,7 +2508,7 @@ int nand_scan (struct mtd_info *mtd, int maxchips) | |||
2473 | } | 2508 | } |
2474 | this->options |= NAND_OOBBUF_ALLOC; | 2509 | this->options |= NAND_OOBBUF_ALLOC; |
2475 | } | 2510 | } |
2476 | 2511 | ||
2477 | if (!this->data_buf) { | 2512 | if (!this->data_buf) { |
2478 | size_t len; | 2513 | size_t len; |
2479 | len = mtd->oobblock + mtd->oobsize; | 2514 | len = mtd->oobblock + mtd->oobsize; |
@@ -2500,7 +2535,7 @@ int nand_scan (struct mtd_info *mtd, int maxchips) | |||
2500 | if (!this->autooob) { | 2535 | if (!this->autooob) { |
2501 | /* Select the appropriate default oob placement scheme for | 2536 | /* Select the appropriate default oob placement scheme for |
2502 | * placement agnostic filesystems */ | 2537 | * placement agnostic filesystems */ |
2503 | switch (mtd->oobsize) { | 2538 | switch (mtd->oobsize) { |
2504 | case 8: | 2539 | case 8: |
2505 | this->autooob = &nand_oob_8; | 2540 | this->autooob = &nand_oob_8; |
2506 | break; | 2541 | break; |
@@ -2516,19 +2551,19 @@ int nand_scan (struct mtd_info *mtd, int maxchips) | |||
2516 | BUG(); | 2551 | BUG(); |
2517 | } | 2552 | } |
2518 | } | 2553 | } |
2519 | 2554 | ||
2520 | /* The number of bytes available for the filesystem to place fs dependend | 2555 | /* The number of bytes available for the filesystem to place fs dependend |
2521 | * oob data */ | 2556 | * oob data */ |
2522 | mtd->oobavail = 0; | 2557 | mtd->oobavail = 0; |
2523 | for (i = 0; this->autooob->oobfree[i][1]; i++) | 2558 | for (i = 0; this->autooob->oobfree[i][1]; i++) |
2524 | mtd->oobavail += this->autooob->oobfree[i][1]; | 2559 | mtd->oobavail += this->autooob->oobfree[i][1]; |
2525 | 2560 | ||
2526 | /* | 2561 | /* |
2527 | * check ECC mode, default to software | 2562 | * check ECC mode, default to software |
2528 | * if 3byte/512byte hardware ECC is selected and we have 256 byte pagesize | 2563 | * if 3byte/512byte hardware ECC is selected and we have 256 byte pagesize |
2529 | * fallback to software ECC | 2564 | * fallback to software ECC |
2530 | */ | 2565 | */ |
2531 | this->eccsize = 256; /* set default eccsize */ | 2566 | this->eccsize = 256; /* set default eccsize */ |
2532 | this->eccbytes = 3; | 2567 | this->eccbytes = 3; |
2533 | 2568 | ||
2534 | switch (this->eccmode) { | 2569 | switch (this->eccmode) { |
@@ -2543,56 +2578,56 @@ int nand_scan (struct mtd_info *mtd, int maxchips) | |||
2543 | this->eccsize = 2048; | 2578 | this->eccsize = 2048; |
2544 | break; | 2579 | break; |
2545 | 2580 | ||
2546 | case NAND_ECC_HW3_512: | 2581 | case NAND_ECC_HW3_512: |
2547 | case NAND_ECC_HW6_512: | 2582 | case NAND_ECC_HW6_512: |
2548 | case NAND_ECC_HW8_512: | 2583 | case NAND_ECC_HW8_512: |
2549 | if (mtd->oobblock == 256) { | 2584 | if (mtd->oobblock == 256) { |
2550 | printk (KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n"); | 2585 | printk (KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n"); |
2551 | this->eccmode = NAND_ECC_SOFT; | 2586 | this->eccmode = NAND_ECC_SOFT; |
2552 | this->calculate_ecc = nand_calculate_ecc; | 2587 | this->calculate_ecc = nand_calculate_ecc; |
2553 | this->correct_data = nand_correct_data; | 2588 | this->correct_data = nand_correct_data; |
2554 | } else | 2589 | } else |
2555 | this->eccsize = 512; /* set eccsize to 512 */ | 2590 | this->eccsize = 512; /* set eccsize to 512 */ |
2556 | break; | 2591 | break; |
2557 | 2592 | ||
2558 | case NAND_ECC_HW3_256: | 2593 | case NAND_ECC_HW3_256: |
2559 | break; | 2594 | break; |
2560 | 2595 | ||
2561 | case NAND_ECC_NONE: | 2596 | case NAND_ECC_NONE: |
2562 | printk (KERN_WARNING "NAND_ECC_NONE selected by board driver. This is not recommended !!\n"); | 2597 | printk (KERN_WARNING "NAND_ECC_NONE selected by board driver. This is not recommended !!\n"); |
2563 | this->eccmode = NAND_ECC_NONE; | 2598 | this->eccmode = NAND_ECC_NONE; |
2564 | break; | 2599 | break; |
2565 | 2600 | ||
2566 | case NAND_ECC_SOFT: | 2601 | case NAND_ECC_SOFT: |
2567 | this->calculate_ecc = nand_calculate_ecc; | 2602 | this->calculate_ecc = nand_calculate_ecc; |
2568 | this->correct_data = nand_correct_data; | 2603 | this->correct_data = nand_correct_data; |
2569 | break; | 2604 | break; |
2570 | 2605 | ||
2571 | default: | 2606 | default: |
2572 | printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode); | 2607 | printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode); |
2573 | BUG(); | 2608 | BUG(); |
2574 | } | 2609 | } |
2575 | 2610 | ||
2576 | /* Check hardware ecc function availability and adjust number of ecc bytes per | 2611 | /* Check hardware ecc function availability and adjust number of ecc bytes per |
2577 | * calculation step | 2612 | * calculation step |
2578 | */ | 2613 | */ |
2579 | switch (this->eccmode) { | 2614 | switch (this->eccmode) { |
2580 | case NAND_ECC_HW12_2048: | 2615 | case NAND_ECC_HW12_2048: |
2581 | this->eccbytes += 4; | 2616 | this->eccbytes += 4; |
2582 | case NAND_ECC_HW8_512: | 2617 | case NAND_ECC_HW8_512: |
2583 | this->eccbytes += 2; | 2618 | this->eccbytes += 2; |
2584 | case NAND_ECC_HW6_512: | 2619 | case NAND_ECC_HW6_512: |
2585 | this->eccbytes += 3; | 2620 | this->eccbytes += 3; |
2586 | case NAND_ECC_HW3_512: | 2621 | case NAND_ECC_HW3_512: |
2587 | case NAND_ECC_HW3_256: | 2622 | case NAND_ECC_HW3_256: |
2588 | if (this->calculate_ecc && this->correct_data && this->enable_hwecc) | 2623 | if (this->calculate_ecc && this->correct_data && this->enable_hwecc) |
2589 | break; | 2624 | break; |
2590 | printk (KERN_WARNING "No ECC functions supplied, Hardware ECC not possible\n"); | 2625 | printk (KERN_WARNING "No ECC functions supplied, Hardware ECC not possible\n"); |
2591 | BUG(); | 2626 | BUG(); |
2592 | } | 2627 | } |
2593 | 2628 | ||
2594 | mtd->eccsize = this->eccsize; | 2629 | mtd->eccsize = this->eccsize; |
2595 | 2630 | ||
2596 | /* Set the number of read / write steps for one page to ensure ECC generation */ | 2631 | /* Set the number of read / write steps for one page to ensure ECC generation */ |
2597 | switch (this->eccmode) { | 2632 | switch (this->eccmode) { |
2598 | case NAND_ECC_HW12_2048: | 2633 | case NAND_ECC_HW12_2048: |
@@ -2604,15 +2639,15 @@ int nand_scan (struct mtd_info *mtd, int maxchips) | |||
2604 | this->eccsteps = mtd->oobblock / 512; | 2639 | this->eccsteps = mtd->oobblock / 512; |
2605 | break; | 2640 | break; |
2606 | case NAND_ECC_HW3_256: | 2641 | case NAND_ECC_HW3_256: |
2607 | case NAND_ECC_SOFT: | 2642 | case NAND_ECC_SOFT: |
2608 | this->eccsteps = mtd->oobblock / 256; | 2643 | this->eccsteps = mtd->oobblock / 256; |
2609 | break; | 2644 | break; |
2610 | 2645 | ||
2611 | case NAND_ECC_NONE: | 2646 | case NAND_ECC_NONE: |
2612 | this->eccsteps = 1; | 2647 | this->eccsteps = 1; |
2613 | break; | 2648 | break; |
2614 | } | 2649 | } |
2615 | 2650 | ||
2616 | /* Initialize state, waitqueue and spinlock */ | 2651 | /* Initialize state, waitqueue and spinlock */ |
2617 | this->state = FL_READY; | 2652 | this->state = FL_READY; |
2618 | init_waitqueue_head (&this->wq); | 2653 | init_waitqueue_head (&this->wq); |
@@ -2643,8 +2678,8 @@ int nand_scan (struct mtd_info *mtd, int maxchips) | |||
2643 | mtd->sync = nand_sync; | 2678 | mtd->sync = nand_sync; |
2644 | mtd->lock = NULL; | 2679 | mtd->lock = NULL; |
2645 | mtd->unlock = NULL; | 2680 | mtd->unlock = NULL; |
2646 | mtd->suspend = NULL; | 2681 | mtd->suspend = nand_suspend; |
2647 | mtd->resume = NULL; | 2682 | mtd->resume = nand_resume; |
2648 | mtd->block_isbad = nand_block_isbad; | 2683 | mtd->block_isbad = nand_block_isbad; |
2649 | mtd->block_markbad = nand_block_markbad; | 2684 | mtd->block_markbad = nand_block_markbad; |
2650 | 2685 | ||
@@ -2652,7 +2687,7 @@ int nand_scan (struct mtd_info *mtd, int maxchips) | |||
2652 | memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo)); | 2687 | memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo)); |
2653 | 2688 | ||
2654 | mtd->owner = THIS_MODULE; | 2689 | mtd->owner = THIS_MODULE; |
2655 | 2690 | ||
2656 | /* Check, if we should skip the bad block table scan */ | 2691 | /* Check, if we should skip the bad block table scan */ |
2657 | if (this->options & NAND_SKIP_BBTSCAN) | 2692 | if (this->options & NAND_SKIP_BBTSCAN) |
2658 | return 0; | 2693 | return 0; |
@@ -2662,7 +2697,7 @@ int nand_scan (struct mtd_info *mtd, int maxchips) | |||
2662 | } | 2697 | } |
2663 | 2698 | ||
2664 | /** | 2699 | /** |
2665 | * nand_release - [NAND Interface] Free resources held by the NAND device | 2700 | * nand_release - [NAND Interface] Free resources held by the NAND device |
2666 | * @mtd: MTD device structure | 2701 | * @mtd: MTD device structure |
2667 | */ | 2702 | */ |
2668 | void nand_release (struct mtd_info *mtd) | 2703 | void nand_release (struct mtd_info *mtd) |
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 7535ef53685e..ca286999fe08 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c | |||
@@ -3,10 +3,10 @@ | |||
3 | * | 3 | * |
4 | * Overview: | 4 | * Overview: |
5 | * Bad block table support for the NAND driver | 5 | * Bad block table support for the NAND driver |
6 | * | 6 | * |
7 | * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) | 7 | * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) |
8 | * | 8 | * |
9 | * $Id: nand_bbt.c,v 1.35 2005/07/15 13:53:47 gleixner Exp $ | 9 | * $Id: nand_bbt.c,v 1.36 2005/11/07 11:14:30 gleixner Exp $ |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2 as | 12 | * it under the terms of the GNU General Public License version 2 as |
@@ -14,23 +14,23 @@ | |||
14 | * | 14 | * |
15 | * Description: | 15 | * Description: |
16 | * | 16 | * |
17 | * When nand_scan_bbt is called, then it tries to find the bad block table | 17 | * When nand_scan_bbt is called, then it tries to find the bad block table |
18 | * depending on the options in the bbt descriptor(s). If a bbt is found | 18 | * depending on the options in the bbt descriptor(s). If a bbt is found |
19 | * then the contents are read and the memory based bbt is created. If a | 19 | * then the contents are read and the memory based bbt is created. If a |
20 | * mirrored bbt is selected then the mirror is searched too and the | 20 | * mirrored bbt is selected then the mirror is searched too and the |
21 | * versions are compared. If the mirror has a greater version number | 21 | * versions are compared. If the mirror has a greater version number |
22 | * than the mirror bbt is used to build the memory based bbt. | 22 | * than the mirror bbt is used to build the memory based bbt. |
23 | * If the tables are not versioned, then we "or" the bad block information. | 23 | * If the tables are not versioned, then we "or" the bad block information. |
24 | * If one of the bbt's is out of date or does not exist it is (re)created. | 24 | * If one of the bbt's is out of date or does not exist it is (re)created. |
25 | * If no bbt exists at all then the device is scanned for factory marked | 25 | * If no bbt exists at all then the device is scanned for factory marked |
26 | * good / bad blocks and the bad block tables are created. | 26 | * good / bad blocks and the bad block tables are created. |
27 | * | 27 | * |
28 | * For manufacturer created bbts like the one found on M-SYS DOC devices | 28 | * For manufacturer created bbts like the one found on M-SYS DOC devices |
29 | * the bbt is searched and read but never created | 29 | * the bbt is searched and read but never created |
30 | * | 30 | * |
31 | * The autogenerated bad block table is located in the last good blocks | 31 | * The autogenerated bad block table is located in the last good blocks |
32 | * of the device. The table is mirrored, so it can be updated eventually. | 32 | * of the device. The table is mirrored, so it can be updated eventually. |
33 | * The table is marked in the oob area with an ident pattern and a version | 33 | * The table is marked in the oob area with an ident pattern and a version |
34 | * number which indicates which of both tables is more up to date. | 34 | * number which indicates which of both tables is more up to date. |
35 | * | 35 | * |
36 | * The table uses 2 bits per block | 36 | * The table uses 2 bits per block |
@@ -43,13 +43,13 @@ | |||
43 | * 01b: block is marked bad due to wear | 43 | * 01b: block is marked bad due to wear |
44 | * 10b: block is reserved (to protect the bbt area) | 44 | * 10b: block is reserved (to protect the bbt area) |
45 | * 11b: block is factory marked bad | 45 | * 11b: block is factory marked bad |
46 | * | 46 | * |
47 | * Multichip devices like DOC store the bad block info per floor. | 47 | * Multichip devices like DOC store the bad block info per floor. |
48 | * | 48 | * |
49 | * Following assumptions are made: | 49 | * Following assumptions are made: |
50 | * - bbts start at a page boundary, if autolocated on a block boundary | 50 | * - bbts start at a page boundary, if autolocated on a block boundary |
51 | * - the space neccecary for a bbt in FLASH does not exceed a block boundary | 51 | * - the space neccecary for a bbt in FLASH does not exceed a block boundary |
52 | * | 52 | * |
53 | */ | 53 | */ |
54 | 54 | ||
55 | #include <linux/slab.h> | 55 | #include <linux/slab.h> |
@@ -62,7 +62,7 @@ | |||
62 | #include <linux/delay.h> | 62 | #include <linux/delay.h> |
63 | 63 | ||
64 | 64 | ||
65 | /** | 65 | /** |
66 | * check_pattern - [GENERIC] check if a pattern is in the buffer | 66 | * check_pattern - [GENERIC] check if a pattern is in the buffer |
67 | * @buf: the buffer to search | 67 | * @buf: the buffer to search |
68 | * @len: the length of buffer to search | 68 | * @len: the length of buffer to search |
@@ -86,9 +86,9 @@ static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_des | |||
86 | if (p[i] != 0xff) | 86 | if (p[i] != 0xff) |
87 | return -1; | 87 | return -1; |
88 | } | 88 | } |
89 | } | 89 | } |
90 | p += end; | 90 | p += end; |
91 | 91 | ||
92 | /* Compare the pattern */ | 92 | /* Compare the pattern */ |
93 | for (i = 0; i < td->len; i++) { | 93 | for (i = 0; i < td->len; i++) { |
94 | if (p[i] != td->pattern[i]) | 94 | if (p[i] != td->pattern[i]) |
@@ -106,13 +106,13 @@ static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_des | |||
106 | return 0; | 106 | return 0; |
107 | } | 107 | } |
108 | 108 | ||
109 | /** | 109 | /** |
110 | * check_short_pattern - [GENERIC] check if a pattern is in the buffer | 110 | * check_short_pattern - [GENERIC] check if a pattern is in the buffer |
111 | * @buf: the buffer to search | 111 | * @buf: the buffer to search |
112 | * @td: search pattern descriptor | 112 | * @td: search pattern descriptor |
113 | * | 113 | * |
114 | * Check for a pattern at the given place. Used to search bad block | 114 | * Check for a pattern at the given place. Used to search bad block |
115 | * tables and good / bad block identifiers. Same as check_pattern, but | 115 | * tables and good / bad block identifiers. Same as check_pattern, but |
116 | * no optional empty check | 116 | * no optional empty check |
117 | * | 117 | * |
118 | */ | 118 | */ |
@@ -142,7 +142,7 @@ static int check_short_pattern (uint8_t *buf, struct nand_bbt_descr *td) | |||
142 | * Read the bad block table starting from page. | 142 | * Read the bad block table starting from page. |
143 | * | 143 | * |
144 | */ | 144 | */ |
145 | static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, | 145 | static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, |
146 | int bits, int offs, int reserved_block_code) | 146 | int bits, int offs, int reserved_block_code) |
147 | { | 147 | { |
148 | int res, i, j, act = 0; | 148 | int res, i, j, act = 0; |
@@ -153,7 +153,7 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, | |||
153 | 153 | ||
154 | totlen = (num * bits) >> 3; | 154 | totlen = (num * bits) >> 3; |
155 | from = ((loff_t)page) << this->page_shift; | 155 | from = ((loff_t)page) << this->page_shift; |
156 | 156 | ||
157 | while (totlen) { | 157 | while (totlen) { |
158 | len = min (totlen, (size_t) (1 << this->bbt_erase_shift)); | 158 | len = min (totlen, (size_t) (1 << this->bbt_erase_shift)); |
159 | res = mtd->read_ecc (mtd, from, len, &retlen, buf, NULL, this->autooob); | 159 | res = mtd->read_ecc (mtd, from, len, &retlen, buf, NULL, this->autooob); |
@@ -163,7 +163,7 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, | |||
163 | return res; | 163 | return res; |
164 | } | 164 | } |
165 | printk (KERN_WARNING "nand_bbt: ECC error while reading bad block table\n"); | 165 | printk (KERN_WARNING "nand_bbt: ECC error while reading bad block table\n"); |
166 | } | 166 | } |
167 | 167 | ||
168 | /* Analyse data */ | 168 | /* Analyse data */ |
169 | for (i = 0; i < len; i++) { | 169 | for (i = 0; i < len; i++) { |
@@ -183,12 +183,12 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, | |||
183 | * message to MTD_DEBUG_LEVEL0 */ | 183 | * message to MTD_DEBUG_LEVEL0 */ |
184 | printk (KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n", | 184 | printk (KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n", |
185 | ((offs << 2) + (act >> 1)) << this->bbt_erase_shift); | 185 | ((offs << 2) + (act >> 1)) << this->bbt_erase_shift); |
186 | /* Factory marked bad or worn out ? */ | 186 | /* Factory marked bad or worn out ? */ |
187 | if (tmp == 0) | 187 | if (tmp == 0) |
188 | this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06); | 188 | this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06); |
189 | else | 189 | else |
190 | this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06); | 190 | this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06); |
191 | } | 191 | } |
192 | } | 192 | } |
193 | totlen -= len; | 193 | totlen -= len; |
194 | from += len; | 194 | from += len; |
@@ -200,7 +200,7 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, | |||
200 | * read_abs_bbt - [GENERIC] Read the bad block table starting at a given page | 200 | * read_abs_bbt - [GENERIC] Read the bad block table starting at a given page |
201 | * @mtd: MTD device structure | 201 | * @mtd: MTD device structure |
202 | * @buf: temporary buffer | 202 | * @buf: temporary buffer |
203 | * @td: descriptor for the bad block table | 203 | * @td: descriptor for the bad block table |
204 | * @chip: read the table for a specific chip, -1 read all chips. | 204 | * @chip: read the table for a specific chip, -1 read all chips. |
205 | * Applies only if NAND_BBT_PERCHIP option is set | 205 | * Applies only if NAND_BBT_PERCHIP option is set |
206 | * | 206 | * |
@@ -235,7 +235,7 @@ static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des | |||
235 | * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page | 235 | * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page |
236 | * @mtd: MTD device structure | 236 | * @mtd: MTD device structure |
237 | * @buf: temporary buffer | 237 | * @buf: temporary buffer |
238 | * @td: descriptor for the bad block table | 238 | * @td: descriptor for the bad block table |
239 | * @md: descriptor for the bad block table mirror | 239 | * @md: descriptor for the bad block table mirror |
240 | * | 240 | * |
241 | * Read the bad block table(s) for all chips starting at a given page | 241 | * Read the bad block table(s) for all chips starting at a given page |
@@ -247,16 +247,16 @@ static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_de | |||
247 | { | 247 | { |
248 | struct nand_chip *this = mtd->priv; | 248 | struct nand_chip *this = mtd->priv; |
249 | 249 | ||
250 | /* Read the primary version, if available */ | 250 | /* Read the primary version, if available */ |
251 | if (td->options & NAND_BBT_VERSION) { | 251 | if (td->options & NAND_BBT_VERSION) { |
252 | nand_read_raw (mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize); | 252 | nand_read_raw (mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize); |
253 | td->version[0] = buf[mtd->oobblock + td->veroffs]; | 253 | td->version[0] = buf[mtd->oobblock + td->veroffs]; |
254 | printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", td->pages[0], td->version[0]); | 254 | printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", td->pages[0], td->version[0]); |
255 | } | 255 | } |
256 | 256 | ||
257 | /* Read the mirror version, if available */ | 257 | /* Read the mirror version, if available */ |
258 | if (md && (md->options & NAND_BBT_VERSION)) { | 258 | if (md && (md->options & NAND_BBT_VERSION)) { |
259 | nand_read_raw (mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize); | 259 | nand_read_raw (mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize); |
260 | md->version[0] = buf[mtd->oobblock + md->veroffs]; | 260 | md->version[0] = buf[mtd->oobblock + md->veroffs]; |
261 | printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]); | 261 | printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]); |
262 | } | 262 | } |
@@ -290,7 +290,7 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
290 | else { | 290 | else { |
291 | if (bd->options & NAND_BBT_SCAN2NDPAGE) | 291 | if (bd->options & NAND_BBT_SCAN2NDPAGE) |
292 | len = 2; | 292 | len = 2; |
293 | else | 293 | else |
294 | len = 1; | 294 | len = 1; |
295 | } | 295 | } |
296 | 296 | ||
@@ -322,10 +322,10 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
322 | numblocks += startblock; | 322 | numblocks += startblock; |
323 | from = startblock << (this->bbt_erase_shift - 1); | 323 | from = startblock << (this->bbt_erase_shift - 1); |
324 | } | 324 | } |
325 | 325 | ||
326 | for (i = startblock; i < numblocks;) { | 326 | for (i = startblock; i < numblocks;) { |
327 | int ret; | 327 | int ret; |
328 | 328 | ||
329 | if (bd->options & NAND_BBT_SCANEMPTY) | 329 | if (bd->options & NAND_BBT_SCANEMPTY) |
330 | if ((ret = nand_read_raw (mtd, buf, from, readlen, ooblen))) | 330 | if ((ret = nand_read_raw (mtd, buf, from, readlen, ooblen))) |
331 | return ret; | 331 | return ret; |
@@ -333,8 +333,8 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
333 | for (j = 0; j < len; j++) { | 333 | for (j = 0; j < len; j++) { |
334 | if (!(bd->options & NAND_BBT_SCANEMPTY)) { | 334 | if (!(bd->options & NAND_BBT_SCANEMPTY)) { |
335 | size_t retlen; | 335 | size_t retlen; |
336 | 336 | ||
337 | /* Read the full oob until read_oob is fixed to | 337 | /* Read the full oob until read_oob is fixed to |
338 | * handle single byte reads for 16 bit buswidth */ | 338 | * handle single byte reads for 16 bit buswidth */ |
339 | ret = mtd->read_oob(mtd, from + j * mtd->oobblock, | 339 | ret = mtd->read_oob(mtd, from + j * mtd->oobblock, |
340 | mtd->oobsize, &retlen, buf); | 340 | mtd->oobsize, &retlen, buf); |
@@ -343,14 +343,14 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
343 | 343 | ||
344 | if (check_short_pattern (buf, bd)) { | 344 | if (check_short_pattern (buf, bd)) { |
345 | this->bbt[i >> 3] |= 0x03 << (i & 0x6); | 345 | this->bbt[i >> 3] |= 0x03 << (i & 0x6); |
346 | printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", | 346 | printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", |
347 | i >> 1, (unsigned int) from); | 347 | i >> 1, (unsigned int) from); |
348 | break; | 348 | break; |
349 | } | 349 | } |
350 | } else { | 350 | } else { |
351 | if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) { | 351 | if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) { |
352 | this->bbt[i >> 3] |= 0x03 << (i & 0x6); | 352 | this->bbt[i >> 3] |= 0x03 << (i & 0x6); |
353 | printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", | 353 | printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", |
354 | i >> 1, (unsigned int) from); | 354 | i >> 1, (unsigned int) from); |
355 | break; | 355 | break; |
356 | } | 356 | } |
@@ -369,15 +369,15 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
369 | * @td: descriptor for the bad block table | 369 | * @td: descriptor for the bad block table |
370 | * | 370 | * |
371 | * Read the bad block table by searching for a given ident pattern. | 371 | * Read the bad block table by searching for a given ident pattern. |
372 | * Search is preformed either from the beginning up or from the end of | 372 | * Search is preformed either from the beginning up or from the end of |
373 | * the device downwards. The search starts always at the start of a | 373 | * the device downwards. The search starts always at the start of a |
374 | * block. | 374 | * block. |
375 | * If the option NAND_BBT_PERCHIP is given, each chip is searched | 375 | * If the option NAND_BBT_PERCHIP is given, each chip is searched |
376 | * for a bbt, which contains the bad block information of this chip. | 376 | * for a bbt, which contains the bad block information of this chip. |
377 | * This is neccecary to provide support for certain DOC devices. | 377 | * This is neccecary to provide support for certain DOC devices. |
378 | * | 378 | * |
379 | * The bbt ident pattern resides in the oob area of the first page | 379 | * The bbt ident pattern resides in the oob area of the first page |
380 | * in a block. | 380 | * in a block. |
381 | */ | 381 | */ |
382 | static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td) | 382 | static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td) |
383 | { | 383 | { |
@@ -392,10 +392,10 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
392 | startblock = (mtd->size >> this->bbt_erase_shift) -1; | 392 | startblock = (mtd->size >> this->bbt_erase_shift) -1; |
393 | dir = -1; | 393 | dir = -1; |
394 | } else { | 394 | } else { |
395 | startblock = 0; | 395 | startblock = 0; |
396 | dir = 1; | 396 | dir = 1; |
397 | } | 397 | } |
398 | 398 | ||
399 | /* Do we have a bbt per chip ? */ | 399 | /* Do we have a bbt per chip ? */ |
400 | if (td->options & NAND_BBT_PERCHIP) { | 400 | if (td->options & NAND_BBT_PERCHIP) { |
401 | chips = this->numchips; | 401 | chips = this->numchips; |
@@ -405,19 +405,19 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
405 | chips = 1; | 405 | chips = 1; |
406 | bbtblocks = mtd->size >> this->bbt_erase_shift; | 406 | bbtblocks = mtd->size >> this->bbt_erase_shift; |
407 | } | 407 | } |
408 | 408 | ||
409 | /* Number of bits for each erase block in the bbt */ | 409 | /* Number of bits for each erase block in the bbt */ |
410 | bits = td->options & NAND_BBT_NRBITS_MSK; | 410 | bits = td->options & NAND_BBT_NRBITS_MSK; |
411 | 411 | ||
412 | for (i = 0; i < chips; i++) { | 412 | for (i = 0; i < chips; i++) { |
413 | /* Reset version information */ | 413 | /* Reset version information */ |
414 | td->version[i] = 0; | 414 | td->version[i] = 0; |
415 | td->pages[i] = -1; | 415 | td->pages[i] = -1; |
416 | /* Scan the maximum number of blocks */ | 416 | /* Scan the maximum number of blocks */ |
417 | for (block = 0; block < td->maxblocks; block++) { | 417 | for (block = 0; block < td->maxblocks; block++) { |
418 | int actblock = startblock + dir * block; | 418 | int actblock = startblock + dir * block; |
419 | /* Read first page */ | 419 | /* Read first page */ |
420 | nand_read_raw (mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize); | 420 | nand_read_raw (mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize); |
421 | if (!check_pattern(buf, scanlen, mtd->oobblock, td)) { | 421 | if (!check_pattern(buf, scanlen, mtd->oobblock, td)) { |
422 | td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift); | 422 | td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift); |
423 | if (td->options & NAND_BBT_VERSION) { | 423 | if (td->options & NAND_BBT_VERSION) { |
@@ -435,46 +435,46 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
435 | else | 435 | else |
436 | printk (KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i], td->version[i]); | 436 | printk (KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i], td->version[i]); |
437 | } | 437 | } |
438 | return 0; | 438 | return 0; |
439 | } | 439 | } |
440 | 440 | ||
441 | /** | 441 | /** |
442 | * search_read_bbts - [GENERIC] scan the device for bad block table(s) | 442 | * search_read_bbts - [GENERIC] scan the device for bad block table(s) |
443 | * @mtd: MTD device structure | 443 | * @mtd: MTD device structure |
444 | * @buf: temporary buffer | 444 | * @buf: temporary buffer |
445 | * @td: descriptor for the bad block table | 445 | * @td: descriptor for the bad block table |
446 | * @md: descriptor for the bad block table mirror | 446 | * @md: descriptor for the bad block table mirror |
447 | * | 447 | * |
448 | * Search and read the bad block table(s) | 448 | * Search and read the bad block table(s) |
449 | */ | 449 | */ |
450 | static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf, | 450 | static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf, |
451 | struct nand_bbt_descr *td, struct nand_bbt_descr *md) | 451 | struct nand_bbt_descr *td, struct nand_bbt_descr *md) |
452 | { | 452 | { |
453 | /* Search the primary table */ | 453 | /* Search the primary table */ |
454 | search_bbt (mtd, buf, td); | 454 | search_bbt (mtd, buf, td); |
455 | 455 | ||
456 | /* Search the mirror table */ | 456 | /* Search the mirror table */ |
457 | if (md) | 457 | if (md) |
458 | search_bbt (mtd, buf, md); | 458 | search_bbt (mtd, buf, md); |
459 | 459 | ||
460 | /* Force result check */ | 460 | /* Force result check */ |
461 | return 1; | 461 | return 1; |
462 | } | 462 | } |
463 | |||
464 | 463 | ||
465 | /** | 464 | |
465 | /** | ||
466 | * write_bbt - [GENERIC] (Re)write the bad block table | 466 | * write_bbt - [GENERIC] (Re)write the bad block table |
467 | * | 467 | * |
468 | * @mtd: MTD device structure | 468 | * @mtd: MTD device structure |
469 | * @buf: temporary buffer | 469 | * @buf: temporary buffer |
470 | * @td: descriptor for the bad block table | 470 | * @td: descriptor for the bad block table |
471 | * @md: descriptor for the bad block table mirror | 471 | * @md: descriptor for the bad block table mirror |
472 | * @chipsel: selector for a specific chip, -1 for all | 472 | * @chipsel: selector for a specific chip, -1 for all |
473 | * | 473 | * |
474 | * (Re)write the bad block table | 474 | * (Re)write the bad block table |
475 | * | 475 | * |
476 | */ | 476 | */ |
477 | static int write_bbt (struct mtd_info *mtd, uint8_t *buf, | 477 | static int write_bbt (struct mtd_info *mtd, uint8_t *buf, |
478 | struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel) | 478 | struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel) |
479 | { | 479 | { |
480 | struct nand_chip *this = mtd->priv; | 480 | struct nand_chip *this = mtd->priv; |
@@ -493,7 +493,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf, | |||
493 | /* Write bad block table per chip rather than per device ? */ | 493 | /* Write bad block table per chip rather than per device ? */ |
494 | if (td->options & NAND_BBT_PERCHIP) { | 494 | if (td->options & NAND_BBT_PERCHIP) { |
495 | numblocks = (int) (this->chipsize >> this->bbt_erase_shift); | 495 | numblocks = (int) (this->chipsize >> this->bbt_erase_shift); |
496 | /* Full device write or specific chip ? */ | 496 | /* Full device write or specific chip ? */ |
497 | if (chipsel == -1) { | 497 | if (chipsel == -1) { |
498 | nrchips = this->numchips; | 498 | nrchips = this->numchips; |
499 | } else { | 499 | } else { |
@@ -503,19 +503,19 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf, | |||
503 | } else { | 503 | } else { |
504 | numblocks = (int) (mtd->size >> this->bbt_erase_shift); | 504 | numblocks = (int) (mtd->size >> this->bbt_erase_shift); |
505 | nrchips = 1; | 505 | nrchips = 1; |
506 | } | 506 | } |
507 | 507 | ||
508 | /* Loop through the chips */ | 508 | /* Loop through the chips */ |
509 | for (; chip < nrchips; chip++) { | 509 | for (; chip < nrchips; chip++) { |
510 | 510 | ||
511 | /* There was already a version of the table, reuse the page | 511 | /* There was already a version of the table, reuse the page |
512 | * This applies for absolute placement too, as we have the | 512 | * This applies for absolute placement too, as we have the |
513 | * page nr. in td->pages. | 513 | * page nr. in td->pages. |
514 | */ | 514 | */ |
515 | if (td->pages[chip] != -1) { | 515 | if (td->pages[chip] != -1) { |
516 | page = td->pages[chip]; | 516 | page = td->pages[chip]; |
517 | goto write; | 517 | goto write; |
518 | } | 518 | } |
519 | 519 | ||
520 | /* Automatic placement of the bad block table */ | 520 | /* Automatic placement of the bad block table */ |
521 | /* Search direction top -> down ? */ | 521 | /* Search direction top -> down ? */ |
@@ -525,7 +525,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf, | |||
525 | } else { | 525 | } else { |
526 | startblock = chip * numblocks; | 526 | startblock = chip * numblocks; |
527 | dir = 1; | 527 | dir = 1; |
528 | } | 528 | } |
529 | 529 | ||
530 | for (i = 0; i < td->maxblocks; i++) { | 530 | for (i = 0; i < td->maxblocks; i++) { |
531 | int block = startblock + dir * i; | 531 | int block = startblock + dir * i; |
@@ -542,7 +542,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf, | |||
542 | } | 542 | } |
543 | printk (KERN_ERR "No space left to write bad block table\n"); | 543 | printk (KERN_ERR "No space left to write bad block table\n"); |
544 | return -ENOSPC; | 544 | return -ENOSPC; |
545 | write: | 545 | write: |
546 | 546 | ||
547 | /* Set up shift count and masks for the flash table */ | 547 | /* Set up shift count and masks for the flash table */ |
548 | bits = td->options & NAND_BBT_NRBITS_MSK; | 548 | bits = td->options & NAND_BBT_NRBITS_MSK; |
@@ -553,14 +553,14 @@ write: | |||
553 | case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; msk[2] = ~rcode; msk[3] = 0xff; break; | 553 | case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; msk[2] = ~rcode; msk[3] = 0xff; break; |
554 | default: return -EINVAL; | 554 | default: return -EINVAL; |
555 | } | 555 | } |
556 | 556 | ||
557 | bbtoffs = chip * (numblocks >> 2); | 557 | bbtoffs = chip * (numblocks >> 2); |
558 | 558 | ||
559 | to = ((loff_t) page) << this->page_shift; | 559 | to = ((loff_t) page) << this->page_shift; |
560 | 560 | ||
561 | memcpy (&oobinfo, this->autooob, sizeof(oobinfo)); | 561 | memcpy (&oobinfo, this->autooob, sizeof(oobinfo)); |
562 | oobinfo.useecc = MTD_NANDECC_PLACEONLY; | 562 | oobinfo.useecc = MTD_NANDECC_PLACEONLY; |
563 | 563 | ||
564 | /* Must we save the block contents ? */ | 564 | /* Must we save the block contents ? */ |
565 | if (td->options & NAND_BBT_SAVECONTENT) { | 565 | if (td->options & NAND_BBT_SAVECONTENT) { |
566 | /* Make it block aligned */ | 566 | /* Make it block aligned */ |
@@ -599,7 +599,7 @@ write: | |||
599 | buf[len + td->veroffs] = td->version[chip]; | 599 | buf[len + td->veroffs] = td->version[chip]; |
600 | } | 600 | } |
601 | } | 601 | } |
602 | 602 | ||
603 | /* walk through the memory table */ | 603 | /* walk through the memory table */ |
604 | for (i = 0; i < numblocks; ) { | 604 | for (i = 0; i < numblocks; ) { |
605 | uint8_t dat; | 605 | uint8_t dat; |
@@ -611,7 +611,7 @@ write: | |||
611 | dat >>= 2; | 611 | dat >>= 2; |
612 | } | 612 | } |
613 | } | 613 | } |
614 | 614 | ||
615 | memset (&einfo, 0, sizeof (einfo)); | 615 | memset (&einfo, 0, sizeof (einfo)); |
616 | einfo.mtd = mtd; | 616 | einfo.mtd = mtd; |
617 | einfo.addr = (unsigned long) to; | 617 | einfo.addr = (unsigned long) to; |
@@ -621,18 +621,18 @@ write: | |||
621 | printk (KERN_WARNING "nand_bbt: Error during block erase: %d\n", res); | 621 | printk (KERN_WARNING "nand_bbt: Error during block erase: %d\n", res); |
622 | return res; | 622 | return res; |
623 | } | 623 | } |
624 | 624 | ||
625 | res = mtd->write_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo); | 625 | res = mtd->write_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo); |
626 | if (res < 0) { | 626 | if (res < 0) { |
627 | printk (KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res); | 627 | printk (KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res); |
628 | return res; | 628 | return res; |
629 | } | 629 | } |
630 | printk (KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n", | 630 | printk (KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n", |
631 | (unsigned int) to, td->version[chip]); | 631 | (unsigned int) to, td->version[chip]); |
632 | 632 | ||
633 | /* Mark it as used */ | 633 | /* Mark it as used */ |
634 | td->pages[chip] = page; | 634 | td->pages[chip] = page; |
635 | } | 635 | } |
636 | return 0; | 636 | return 0; |
637 | } | 637 | } |
638 | 638 | ||
@@ -641,7 +641,7 @@ write: | |||
641 | * @mtd: MTD device structure | 641 | * @mtd: MTD device structure |
642 | * @bd: descriptor for the good/bad block search pattern | 642 | * @bd: descriptor for the good/bad block search pattern |
643 | * | 643 | * |
644 | * The function creates a memory based bbt by scanning the device | 644 | * The function creates a memory based bbt by scanning the device |
645 | * for manufacturer / software marked good / bad blocks | 645 | * for manufacturer / software marked good / bad blocks |
646 | */ | 646 | */ |
647 | static inline int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) | 647 | static inline int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) |
@@ -673,11 +673,11 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des | |||
673 | struct nand_bbt_descr *rd, *rd2; | 673 | struct nand_bbt_descr *rd, *rd2; |
674 | 674 | ||
675 | /* Do we have a bbt per chip ? */ | 675 | /* Do we have a bbt per chip ? */ |
676 | if (td->options & NAND_BBT_PERCHIP) | 676 | if (td->options & NAND_BBT_PERCHIP) |
677 | chips = this->numchips; | 677 | chips = this->numchips; |
678 | else | 678 | else |
679 | chips = 1; | 679 | chips = 1; |
680 | 680 | ||
681 | for (i = 0; i < chips; i++) { | 681 | for (i = 0; i < chips; i++) { |
682 | writeops = 0; | 682 | writeops = 0; |
683 | rd = NULL; | 683 | rd = NULL; |
@@ -692,7 +692,7 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des | |||
692 | } | 692 | } |
693 | 693 | ||
694 | if (td->pages[i] == -1) { | 694 | if (td->pages[i] == -1) { |
695 | rd = md; | 695 | rd = md; |
696 | td->version[i] = md->version[i]; | 696 | td->version[i] = md->version[i]; |
697 | writeops = 1; | 697 | writeops = 1; |
698 | goto writecheck; | 698 | goto writecheck; |
@@ -710,7 +710,7 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des | |||
710 | if (!(td->options & NAND_BBT_VERSION)) | 710 | if (!(td->options & NAND_BBT_VERSION)) |
711 | rd2 = md; | 711 | rd2 = md; |
712 | goto writecheck; | 712 | goto writecheck; |
713 | } | 713 | } |
714 | 714 | ||
715 | if (((int8_t) (td->version[i] - md->version[i])) > 0) { | 715 | if (((int8_t) (td->version[i] - md->version[i])) > 0) { |
716 | rd = td; | 716 | rd = td; |
@@ -735,15 +735,15 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des | |||
735 | create: | 735 | create: |
736 | /* Create the bad block table by scanning the device ? */ | 736 | /* Create the bad block table by scanning the device ? */ |
737 | if (!(td->options & NAND_BBT_CREATE)) | 737 | if (!(td->options & NAND_BBT_CREATE)) |
738 | continue; | 738 | continue; |
739 | 739 | ||
740 | /* Create the table in memory by scanning the chip(s) */ | 740 | /* Create the table in memory by scanning the chip(s) */ |
741 | create_bbt (mtd, buf, bd, chipsel); | 741 | create_bbt (mtd, buf, bd, chipsel); |
742 | 742 | ||
743 | td->version[i] = 1; | 743 | td->version[i] = 1; |
744 | if (md) | 744 | if (md) |
745 | md->version[i] = 1; | 745 | md->version[i] = 1; |
746 | writecheck: | 746 | writecheck: |
747 | /* read back first ? */ | 747 | /* read back first ? */ |
748 | if (rd) | 748 | if (rd) |
749 | read_abs_bbt (mtd, buf, rd, chipsel); | 749 | read_abs_bbt (mtd, buf, rd, chipsel); |
@@ -757,7 +757,7 @@ writecheck: | |||
757 | if (res < 0) | 757 | if (res < 0) |
758 | return res; | 758 | return res; |
759 | } | 759 | } |
760 | 760 | ||
761 | /* Write the mirror bad block table to the device ? */ | 761 | /* Write the mirror bad block table to the device ? */ |
762 | if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) { | 762 | if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) { |
763 | res = write_bbt (mtd, buf, md, td, chipsel); | 763 | res = write_bbt (mtd, buf, md, td, chipsel); |
@@ -765,11 +765,11 @@ writecheck: | |||
765 | return res; | 765 | return res; |
766 | } | 766 | } |
767 | } | 767 | } |
768 | return 0; | 768 | return 0; |
769 | } | 769 | } |
770 | 770 | ||
771 | /** | 771 | /** |
772 | * mark_bbt_regions - [GENERIC] mark the bad block table regions | 772 | * mark_bbt_regions - [GENERIC] mark the bad block table regions |
773 | * @mtd: MTD device structure | 773 | * @mtd: MTD device structure |
774 | * @td: bad block table descriptor | 774 | * @td: bad block table descriptor |
775 | * | 775 | * |
@@ -790,14 +790,14 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td) | |||
790 | } else { | 790 | } else { |
791 | chips = 1; | 791 | chips = 1; |
792 | nrblocks = (int)(mtd->size >> this->bbt_erase_shift); | 792 | nrblocks = (int)(mtd->size >> this->bbt_erase_shift); |
793 | } | 793 | } |
794 | 794 | ||
795 | for (i = 0; i < chips; i++) { | 795 | for (i = 0; i < chips; i++) { |
796 | if ((td->options & NAND_BBT_ABSPAGE) || | 796 | if ((td->options & NAND_BBT_ABSPAGE) || |
797 | !(td->options & NAND_BBT_WRITE)) { | 797 | !(td->options & NAND_BBT_WRITE)) { |
798 | if (td->pages[i] == -1) continue; | 798 | if (td->pages[i] == -1) continue; |
799 | block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift); | 799 | block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift); |
800 | block <<= 1; | 800 | block <<= 1; |
801 | oldval = this->bbt[(block >> 3)]; | 801 | oldval = this->bbt[(block >> 3)]; |
802 | newval = oldval | (0x2 << (block & 0x06)); | 802 | newval = oldval | (0x2 << (block & 0x06)); |
803 | this->bbt[(block >> 3)] = newval; | 803 | this->bbt[(block >> 3)] = newval; |
@@ -808,16 +808,16 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td) | |||
808 | update = 0; | 808 | update = 0; |
809 | if (td->options & NAND_BBT_LASTBLOCK) | 809 | if (td->options & NAND_BBT_LASTBLOCK) |
810 | block = ((i + 1) * nrblocks) - td->maxblocks; | 810 | block = ((i + 1) * nrblocks) - td->maxblocks; |
811 | else | 811 | else |
812 | block = i * nrblocks; | 812 | block = i * nrblocks; |
813 | block <<= 1; | 813 | block <<= 1; |
814 | for (j = 0; j < td->maxblocks; j++) { | 814 | for (j = 0; j < td->maxblocks; j++) { |
815 | oldval = this->bbt[(block >> 3)]; | 815 | oldval = this->bbt[(block >> 3)]; |
816 | newval = oldval | (0x2 << (block & 0x06)); | 816 | newval = oldval | (0x2 << (block & 0x06)); |
817 | this->bbt[(block >> 3)] = newval; | 817 | this->bbt[(block >> 3)] = newval; |
818 | if (oldval != newval) update = 1; | 818 | if (oldval != newval) update = 1; |
819 | block += 2; | 819 | block += 2; |
820 | } | 820 | } |
821 | /* If we want reserved blocks to be recorded to flash, and some | 821 | /* If we want reserved blocks to be recorded to flash, and some |
822 | new ones have been marked, then we need to update the stored | 822 | new ones have been marked, then we need to update the stored |
823 | bbts. This should only happen once. */ | 823 | bbts. This should only happen once. */ |
@@ -831,7 +831,7 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td) | |||
831 | * @mtd: MTD device structure | 831 | * @mtd: MTD device structure |
832 | * @bd: descriptor for the good/bad block search pattern | 832 | * @bd: descriptor for the good/bad block search pattern |
833 | * | 833 | * |
834 | * The function checks, if a bad block table(s) is/are already | 834 | * The function checks, if a bad block table(s) is/are already |
835 | * available. If not it scans the device for manufacturer | 835 | * available. If not it scans the device for manufacturer |
836 | * marked good / bad blocks and writes the bad block table(s) to | 836 | * marked good / bad blocks and writes the bad block table(s) to |
837 | * the selected place. | 837 | * the selected place. |
@@ -880,30 +880,30 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) | |||
880 | this->bbt = NULL; | 880 | this->bbt = NULL; |
881 | return -ENOMEM; | 881 | return -ENOMEM; |
882 | } | 882 | } |
883 | 883 | ||
884 | /* Is the bbt at a given page ? */ | 884 | /* Is the bbt at a given page ? */ |
885 | if (td->options & NAND_BBT_ABSPAGE) { | 885 | if (td->options & NAND_BBT_ABSPAGE) { |
886 | res = read_abs_bbts (mtd, buf, td, md); | 886 | res = read_abs_bbts (mtd, buf, td, md); |
887 | } else { | 887 | } else { |
888 | /* Search the bad block table using a pattern in oob */ | 888 | /* Search the bad block table using a pattern in oob */ |
889 | res = search_read_bbts (mtd, buf, td, md); | 889 | res = search_read_bbts (mtd, buf, td, md); |
890 | } | 890 | } |
891 | 891 | ||
892 | if (res) | 892 | if (res) |
893 | res = check_create (mtd, buf, bd); | 893 | res = check_create (mtd, buf, bd); |
894 | 894 | ||
895 | /* Prevent the bbt regions from erasing / writing */ | 895 | /* Prevent the bbt regions from erasing / writing */ |
896 | mark_bbt_region (mtd, td); | 896 | mark_bbt_region (mtd, td); |
897 | if (md) | 897 | if (md) |
898 | mark_bbt_region (mtd, md); | 898 | mark_bbt_region (mtd, md); |
899 | 899 | ||
900 | kfree (buf); | 900 | kfree (buf); |
901 | return res; | 901 | return res; |
902 | } | 902 | } |
903 | 903 | ||
904 | 904 | ||
905 | /** | 905 | /** |
906 | * nand_update_bbt - [NAND Interface] update bad block table(s) | 906 | * nand_update_bbt - [NAND Interface] update bad block table(s) |
907 | * @mtd: MTD device structure | 907 | * @mtd: MTD device structure |
908 | * @offs: the offset of the newly marked block | 908 | * @offs: the offset of the newly marked block |
909 | * | 909 | * |
@@ -930,7 +930,7 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs) | |||
930 | printk (KERN_ERR "nand_update_bbt: Out of memory\n"); | 930 | printk (KERN_ERR "nand_update_bbt: Out of memory\n"); |
931 | return -ENOMEM; | 931 | return -ENOMEM; |
932 | } | 932 | } |
933 | 933 | ||
934 | writeops = md != NULL ? 0x03 : 0x01; | 934 | writeops = md != NULL ? 0x03 : 0x01; |
935 | 935 | ||
936 | /* Do we have a bbt per chip ? */ | 936 | /* Do we have a bbt per chip ? */ |
@@ -944,7 +944,7 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs) | |||
944 | 944 | ||
945 | td->version[chip]++; | 945 | td->version[chip]++; |
946 | if (md) | 946 | if (md) |
947 | md->version[chip]++; | 947 | md->version[chip]++; |
948 | 948 | ||
949 | /* Write the bad block table to the device ? */ | 949 | /* Write the bad block table to the device ? */ |
950 | if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { | 950 | if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { |
@@ -957,12 +957,12 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs) | |||
957 | res = write_bbt (mtd, buf, md, td, chipsel); | 957 | res = write_bbt (mtd, buf, md, td, chipsel); |
958 | } | 958 | } |
959 | 959 | ||
960 | out: | 960 | out: |
961 | kfree (buf); | 961 | kfree (buf); |
962 | return res; | 962 | return res; |
963 | } | 963 | } |
964 | 964 | ||
965 | /* Define some generic bad / good block scan pattern which are used | 965 | /* Define some generic bad / good block scan pattern which are used |
966 | * while scanning a device for factory marked good / bad blocks. */ | 966 | * while scanning a device for factory marked good / bad blocks. */ |
967 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; | 967 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; |
968 | 968 | ||
@@ -1009,7 +1009,7 @@ static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; | |||
1009 | static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' }; | 1009 | static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' }; |
1010 | 1010 | ||
1011 | static struct nand_bbt_descr bbt_main_descr = { | 1011 | static struct nand_bbt_descr bbt_main_descr = { |
1012 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | 1012 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
1013 | | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, | 1013 | | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, |
1014 | .offs = 8, | 1014 | .offs = 8, |
1015 | .len = 4, | 1015 | .len = 4, |
@@ -1019,7 +1019,7 @@ static struct nand_bbt_descr bbt_main_descr = { | |||
1019 | }; | 1019 | }; |
1020 | 1020 | ||
1021 | static struct nand_bbt_descr bbt_mirror_descr = { | 1021 | static struct nand_bbt_descr bbt_mirror_descr = { |
1022 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | 1022 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
1023 | | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, | 1023 | | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, |
1024 | .offs = 8, | 1024 | .offs = 8, |
1025 | .len = 4, | 1025 | .len = 4, |
@@ -1029,7 +1029,7 @@ static struct nand_bbt_descr bbt_mirror_descr = { | |||
1029 | }; | 1029 | }; |
1030 | 1030 | ||
1031 | /** | 1031 | /** |
1032 | * nand_default_bbt - [NAND Interface] Select a default bad block table for the device | 1032 | * nand_default_bbt - [NAND Interface] Select a default bad block table for the device |
1033 | * @mtd: MTD device structure | 1033 | * @mtd: MTD device structure |
1034 | * | 1034 | * |
1035 | * This function selects the default bad block table | 1035 | * This function selects the default bad block table |
@@ -1039,29 +1039,29 @@ static struct nand_bbt_descr bbt_mirror_descr = { | |||
1039 | int nand_default_bbt (struct mtd_info *mtd) | 1039 | int nand_default_bbt (struct mtd_info *mtd) |
1040 | { | 1040 | { |
1041 | struct nand_chip *this = mtd->priv; | 1041 | struct nand_chip *this = mtd->priv; |
1042 | 1042 | ||
1043 | /* Default for AG-AND. We must use a flash based | 1043 | /* Default for AG-AND. We must use a flash based |
1044 | * bad block table as the devices have factory marked | 1044 | * bad block table as the devices have factory marked |
1045 | * _good_ blocks. Erasing those blocks leads to loss | 1045 | * _good_ blocks. Erasing those blocks leads to loss |
1046 | * of the good / bad information, so we _must_ store | 1046 | * of the good / bad information, so we _must_ store |
1047 | * this information in a good / bad table during | 1047 | * this information in a good / bad table during |
1048 | * startup | 1048 | * startup |
1049 | */ | 1049 | */ |
1050 | if (this->options & NAND_IS_AND) { | 1050 | if (this->options & NAND_IS_AND) { |
1051 | /* Use the default pattern descriptors */ | 1051 | /* Use the default pattern descriptors */ |
1052 | if (!this->bbt_td) { | 1052 | if (!this->bbt_td) { |
1053 | this->bbt_td = &bbt_main_descr; | 1053 | this->bbt_td = &bbt_main_descr; |
1054 | this->bbt_md = &bbt_mirror_descr; | 1054 | this->bbt_md = &bbt_mirror_descr; |
1055 | } | 1055 | } |
1056 | this->options |= NAND_USE_FLASH_BBT; | 1056 | this->options |= NAND_USE_FLASH_BBT; |
1057 | return nand_scan_bbt (mtd, &agand_flashbased); | 1057 | return nand_scan_bbt (mtd, &agand_flashbased); |
1058 | } | 1058 | } |
1059 | 1059 | ||
1060 | 1060 | ||
1061 | /* Is a flash based bad block table requested ? */ | 1061 | /* Is a flash based bad block table requested ? */ |
1062 | if (this->options & NAND_USE_FLASH_BBT) { | 1062 | if (this->options & NAND_USE_FLASH_BBT) { |
1063 | /* Use the default pattern descriptors */ | 1063 | /* Use the default pattern descriptors */ |
1064 | if (!this->bbt_td) { | 1064 | if (!this->bbt_td) { |
1065 | this->bbt_td = &bbt_main_descr; | 1065 | this->bbt_td = &bbt_main_descr; |
1066 | this->bbt_md = &bbt_mirror_descr; | 1066 | this->bbt_md = &bbt_mirror_descr; |
1067 | } | 1067 | } |
@@ -1081,7 +1081,7 @@ int nand_default_bbt (struct mtd_info *mtd) | |||
1081 | } | 1081 | } |
1082 | 1082 | ||
1083 | /** | 1083 | /** |
1084 | * nand_isbad_bbt - [NAND Interface] Check if a block is bad | 1084 | * nand_isbad_bbt - [NAND Interface] Check if a block is bad |
1085 | * @mtd: MTD device structure | 1085 | * @mtd: MTD device structure |
1086 | * @offs: offset in the device | 1086 | * @offs: offset in the device |
1087 | * @allowbbt: allow access to bad block table region | 1087 | * @allowbbt: allow access to bad block table region |
@@ -1092,12 +1092,12 @@ int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt) | |||
1092 | struct nand_chip *this = mtd->priv; | 1092 | struct nand_chip *this = mtd->priv; |
1093 | int block; | 1093 | int block; |
1094 | uint8_t res; | 1094 | uint8_t res; |
1095 | 1095 | ||
1096 | /* Get block number * 2 */ | 1096 | /* Get block number * 2 */ |
1097 | block = (int) (offs >> (this->bbt_erase_shift - 1)); | 1097 | block = (int) (offs >> (this->bbt_erase_shift - 1)); |
1098 | res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03; | 1098 | res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03; |
1099 | 1099 | ||
1100 | DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n", | 1100 | DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n", |
1101 | (unsigned int)offs, block >> 1, res); | 1101 | (unsigned int)offs, block >> 1, res); |
1102 | 1102 | ||
1103 | switch ((int)res) { | 1103 | switch ((int)res) { |
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c index 2e341b75437a..40ac909150a3 100644 --- a/drivers/mtd/nand/nand_ecc.c +++ b/drivers/mtd/nand/nand_ecc.c | |||
@@ -7,22 +7,22 @@ | |||
7 | * Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com) | 7 | * Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com) |
8 | * Toshiba America Electronics Components, Inc. | 8 | * Toshiba America Electronics Components, Inc. |
9 | * | 9 | * |
10 | * $Id: nand_ecc.c,v 1.14 2004/06/16 15:34:37 gleixner Exp $ | 10 | * $Id: nand_ecc.c,v 1.15 2005/11/07 11:14:30 gleixner Exp $ |
11 | * | 11 | * |
12 | * This file is free software; you can redistribute it and/or modify it | 12 | * This file is free software; you can redistribute it and/or modify it |
13 | * under the terms of the GNU General Public License as published by the | 13 | * under the terms of the GNU General Public License as published by the |
14 | * Free Software Foundation; either version 2 or (at your option) any | 14 | * Free Software Foundation; either version 2 or (at your option) any |
15 | * later version. | 15 | * later version. |
16 | * | 16 | * |
17 | * This file is distributed in the hope that it will be useful, but WITHOUT | 17 | * This file is distributed in the hope that it will be useful, but WITHOUT |
18 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 18 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
19 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | 19 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
20 | * for more details. | 20 | * for more details. |
21 | * | 21 | * |
22 | * You should have received a copy of the GNU General Public License along | 22 | * You should have received a copy of the GNU General Public License along |
23 | * with this file; if not, write to the Free Software Foundation, Inc., | 23 | * with this file; if not, write to the Free Software Foundation, Inc., |
24 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | 24 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
25 | * | 25 | * |
26 | * As a special exception, if other files instantiate templates or use | 26 | * As a special exception, if other files instantiate templates or use |
27 | * macros or inline functions from these files, or you compile these | 27 | * macros or inline functions from these files, or you compile these |
28 | * files and link them with other works to produce a work based on these | 28 | * files and link them with other works to produce a work based on these |
@@ -30,7 +30,7 @@ | |||
30 | * covered by the GNU General Public License. However the source code for | 30 | * covered by the GNU General Public License. However the source code for |
31 | * these files must still be made available in accordance with section (3) | 31 | * these files must still be made available in accordance with section (3) |
32 | * of the GNU General Public License. | 32 | * of the GNU General Public License. |
33 | * | 33 | * |
34 | * This exception does not invalidate any other reasons why a work based on | 34 | * This exception does not invalidate any other reasons why a work based on |
35 | * this file might be covered by the GNU General Public License. | 35 | * this file might be covered by the GNU General Public License. |
36 | */ | 36 | */ |
@@ -67,7 +67,7 @@ static const u_char nand_ecc_precalc_table[] = { | |||
67 | * nand_trans_result - [GENERIC] create non-inverted ECC | 67 | * nand_trans_result - [GENERIC] create non-inverted ECC |
68 | * @reg2: line parity reg 2 | 68 | * @reg2: line parity reg 2 |
69 | * @reg3: line parity reg 3 | 69 | * @reg3: line parity reg 3 |
70 | * @ecc_code: ecc | 70 | * @ecc_code: ecc |
71 | * | 71 | * |
72 | * Creates non-inverted ECC code from line parity | 72 | * Creates non-inverted ECC code from line parity |
73 | */ | 73 | */ |
@@ -75,11 +75,11 @@ static void nand_trans_result(u_char reg2, u_char reg3, | |||
75 | u_char *ecc_code) | 75 | u_char *ecc_code) |
76 | { | 76 | { |
77 | u_char a, b, i, tmp1, tmp2; | 77 | u_char a, b, i, tmp1, tmp2; |
78 | 78 | ||
79 | /* Initialize variables */ | 79 | /* Initialize variables */ |
80 | a = b = 0x80; | 80 | a = b = 0x80; |
81 | tmp1 = tmp2 = 0; | 81 | tmp1 = tmp2 = 0; |
82 | 82 | ||
83 | /* Calculate first ECC byte */ | 83 | /* Calculate first ECC byte */ |
84 | for (i = 0; i < 4; i++) { | 84 | for (i = 0; i < 4; i++) { |
85 | if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */ | 85 | if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */ |
@@ -90,7 +90,7 @@ static void nand_trans_result(u_char reg2, u_char reg3, | |||
90 | b >>= 1; | 90 | b >>= 1; |
91 | a >>= 1; | 91 | a >>= 1; |
92 | } | 92 | } |
93 | 93 | ||
94 | /* Calculate second ECC byte */ | 94 | /* Calculate second ECC byte */ |
95 | b = 0x80; | 95 | b = 0x80; |
96 | for (i = 0; i < 4; i++) { | 96 | for (i = 0; i < 4; i++) { |
@@ -102,7 +102,7 @@ static void nand_trans_result(u_char reg2, u_char reg3, | |||
102 | b >>= 1; | 102 | b >>= 1; |
103 | a >>= 1; | 103 | a >>= 1; |
104 | } | 104 | } |
105 | 105 | ||
106 | /* Store two of the ECC bytes */ | 106 | /* Store two of the ECC bytes */ |
107 | ecc_code[0] = tmp1; | 107 | ecc_code[0] = tmp1; |
108 | ecc_code[1] = tmp2; | 108 | ecc_code[1] = tmp2; |
@@ -118,28 +118,28 @@ int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code | |||
118 | { | 118 | { |
119 | u_char idx, reg1, reg2, reg3; | 119 | u_char idx, reg1, reg2, reg3; |
120 | int j; | 120 | int j; |
121 | 121 | ||
122 | /* Initialize variables */ | 122 | /* Initialize variables */ |
123 | reg1 = reg2 = reg3 = 0; | 123 | reg1 = reg2 = reg3 = 0; |
124 | ecc_code[0] = ecc_code[1] = ecc_code[2] = 0; | 124 | ecc_code[0] = ecc_code[1] = ecc_code[2] = 0; |
125 | 125 | ||
126 | /* Build up column parity */ | 126 | /* Build up column parity */ |
127 | for(j = 0; j < 256; j++) { | 127 | for(j = 0; j < 256; j++) { |
128 | 128 | ||
129 | /* Get CP0 - CP5 from table */ | 129 | /* Get CP0 - CP5 from table */ |
130 | idx = nand_ecc_precalc_table[dat[j]]; | 130 | idx = nand_ecc_precalc_table[dat[j]]; |
131 | reg1 ^= (idx & 0x3f); | 131 | reg1 ^= (idx & 0x3f); |
132 | 132 | ||
133 | /* All bit XOR = 1 ? */ | 133 | /* All bit XOR = 1 ? */ |
134 | if (idx & 0x40) { | 134 | if (idx & 0x40) { |
135 | reg3 ^= (u_char) j; | 135 | reg3 ^= (u_char) j; |
136 | reg2 ^= ~((u_char) j); | 136 | reg2 ^= ~((u_char) j); |
137 | } | 137 | } |
138 | } | 138 | } |
139 | 139 | ||
140 | /* Create non-inverted ECC code from line parity */ | 140 | /* Create non-inverted ECC code from line parity */ |
141 | nand_trans_result(reg2, reg3, ecc_code); | 141 | nand_trans_result(reg2, reg3, ecc_code); |
142 | 142 | ||
143 | /* Calculate final ECC code */ | 143 | /* Calculate final ECC code */ |
144 | ecc_code[0] = ~ecc_code[0]; | 144 | ecc_code[0] = ~ecc_code[0]; |
145 | ecc_code[1] = ~ecc_code[1]; | 145 | ecc_code[1] = ~ecc_code[1]; |
@@ -159,12 +159,12 @@ int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code | |||
159 | int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) | 159 | int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) |
160 | { | 160 | { |
161 | u_char a, b, c, d1, d2, d3, add, bit, i; | 161 | u_char a, b, c, d1, d2, d3, add, bit, i; |
162 | 162 | ||
163 | /* Do error detection */ | 163 | /* Do error detection */ |
164 | d1 = calc_ecc[0] ^ read_ecc[0]; | 164 | d1 = calc_ecc[0] ^ read_ecc[0]; |
165 | d2 = calc_ecc[1] ^ read_ecc[1]; | 165 | d2 = calc_ecc[1] ^ read_ecc[1]; |
166 | d3 = calc_ecc[2] ^ read_ecc[2]; | 166 | d3 = calc_ecc[2] ^ read_ecc[2]; |
167 | 167 | ||
168 | if ((d1 | d2 | d3) == 0) { | 168 | if ((d1 | d2 | d3) == 0) { |
169 | /* No errors */ | 169 | /* No errors */ |
170 | return 0; | 170 | return 0; |
@@ -173,7 +173,7 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_cha | |||
173 | a = (d1 ^ (d1 >> 1)) & 0x55; | 173 | a = (d1 ^ (d1 >> 1)) & 0x55; |
174 | b = (d2 ^ (d2 >> 1)) & 0x55; | 174 | b = (d2 ^ (d2 >> 1)) & 0x55; |
175 | c = (d3 ^ (d3 >> 1)) & 0x54; | 175 | c = (d3 ^ (d3 >> 1)) & 0x54; |
176 | 176 | ||
177 | /* Found and will correct single bit error in the data */ | 177 | /* Found and will correct single bit error in the data */ |
178 | if ((a == 0x55) && (b == 0x55) && (c == 0x54)) { | 178 | if ((a == 0x55) && (b == 0x55) && (c == 0x54)) { |
179 | c = 0x80; | 179 | c = 0x80; |
@@ -237,7 +237,7 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_cha | |||
237 | } | 237 | } |
238 | } | 238 | } |
239 | } | 239 | } |
240 | 240 | ||
241 | /* Should never happen */ | 241 | /* Should never happen */ |
242 | return -1; | 242 | return -1; |
243 | } | 243 | } |
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index efe246961b69..dbc7e55a4247 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de) | 4 | * Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de) |
5 | * | 5 | * |
6 | * $Id: nand_ids.c,v 1.14 2005/06/23 09:38:50 gleixner Exp $ | 6 | * $Id: nand_ids.c,v 1.16 2005/11/07 11:14:31 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 |
@@ -14,14 +14,14 @@ | |||
14 | #include <linux/mtd/nand.h> | 14 | #include <linux/mtd/nand.h> |
15 | /* | 15 | /* |
16 | * Chip ID list | 16 | * Chip ID list |
17 | * | 17 | * |
18 | * Name. ID code, pagesize, chipsize in MegaByte, eraseblock size, | 18 | * Name. ID code, pagesize, chipsize in MegaByte, eraseblock size, |
19 | * options | 19 | * options |
20 | * | 20 | * |
21 | * Pagesize; 0, 256, 512 | 21 | * Pagesize; 0, 256, 512 |
22 | * 0 get this information from the extended chip ID | 22 | * 0 get this information from the extended chip ID |
23 | + 256 256 Byte page size | 23 | + 256 256 Byte page size |
24 | * 512 512 Byte page size | 24 | * 512 512 Byte page size |
25 | */ | 25 | */ |
26 | struct nand_flash_dev nand_flash_ids[] = { | 26 | struct nand_flash_dev nand_flash_ids[] = { |
27 | {"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0}, | 27 | {"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0}, |
@@ -34,27 +34,27 @@ struct nand_flash_dev nand_flash_ids[] = { | |||
34 | {"NAND 4MiB 3,3V 8-bit", 0xe3, 512, 4, 0x2000, 0}, | 34 | {"NAND 4MiB 3,3V 8-bit", 0xe3, 512, 4, 0x2000, 0}, |
35 | {"NAND 4MiB 3,3V 8-bit", 0xe5, 512, 4, 0x2000, 0}, | 35 | {"NAND 4MiB 3,3V 8-bit", 0xe5, 512, 4, 0x2000, 0}, |
36 | {"NAND 8MiB 3,3V 8-bit", 0xd6, 512, 8, 0x2000, 0}, | 36 | {"NAND 8MiB 3,3V 8-bit", 0xd6, 512, 8, 0x2000, 0}, |
37 | 37 | ||
38 | {"NAND 8MiB 1,8V 8-bit", 0x39, 512, 8, 0x2000, 0}, | 38 | {"NAND 8MiB 1,8V 8-bit", 0x39, 512, 8, 0x2000, 0}, |
39 | {"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, 0}, | 39 | {"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, 0}, |
40 | {"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16}, | 40 | {"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16}, |
41 | {"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16}, | 41 | {"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16}, |
42 | 42 | ||
43 | {"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0}, | 43 | {"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0}, |
44 | {"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0}, | 44 | {"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0}, |
45 | {"NAND 16MiB 1,8V 16-bit", 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16}, | 45 | {"NAND 16MiB 1,8V 16-bit", 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16}, |
46 | {"NAND 16MiB 3,3V 16-bit", 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16}, | 46 | {"NAND 16MiB 3,3V 16-bit", 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16}, |
47 | 47 | ||
48 | {"NAND 32MiB 1,8V 8-bit", 0x35, 512, 32, 0x4000, 0}, | 48 | {"NAND 32MiB 1,8V 8-bit", 0x35, 512, 32, 0x4000, 0}, |
49 | {"NAND 32MiB 3,3V 8-bit", 0x75, 512, 32, 0x4000, 0}, | 49 | {"NAND 32MiB 3,3V 8-bit", 0x75, 512, 32, 0x4000, 0}, |
50 | {"NAND 32MiB 1,8V 16-bit", 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16}, | 50 | {"NAND 32MiB 1,8V 16-bit", 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16}, |
51 | {"NAND 32MiB 3,3V 16-bit", 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16}, | 51 | {"NAND 32MiB 3,3V 16-bit", 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16}, |
52 | 52 | ||
53 | {"NAND 64MiB 1,8V 8-bit", 0x36, 512, 64, 0x4000, 0}, | 53 | {"NAND 64MiB 1,8V 8-bit", 0x36, 512, 64, 0x4000, 0}, |
54 | {"NAND 64MiB 3,3V 8-bit", 0x76, 512, 64, 0x4000, 0}, | 54 | {"NAND 64MiB 3,3V 8-bit", 0x76, 512, 64, 0x4000, 0}, |
55 | {"NAND 64MiB 1,8V 16-bit", 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16}, | 55 | {"NAND 64MiB 1,8V 16-bit", 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16}, |
56 | {"NAND 64MiB 3,3V 16-bit", 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16}, | 56 | {"NAND 64MiB 3,3V 16-bit", 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16}, |
57 | 57 | ||
58 | {"NAND 128MiB 1,8V 8-bit", 0x78, 512, 128, 0x4000, 0}, | 58 | {"NAND 128MiB 1,8V 8-bit", 0x78, 512, 128, 0x4000, 0}, |
59 | {"NAND 128MiB 1,8V 8-bit", 0x39, 512, 128, 0x4000, 0}, | 59 | {"NAND 128MiB 1,8V 8-bit", 0x39, 512, 128, 0x4000, 0}, |
60 | {"NAND 128MiB 3,3V 8-bit", 0x79, 512, 128, 0x4000, 0}, | 60 | {"NAND 128MiB 3,3V 8-bit", 0x79, 512, 128, 0x4000, 0}, |
@@ -62,7 +62,7 @@ struct nand_flash_dev nand_flash_ids[] = { | |||
62 | {"NAND 128MiB 1,8V 16-bit", 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16}, | 62 | {"NAND 128MiB 1,8V 16-bit", 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16}, |
63 | {"NAND 128MiB 3,3V 16-bit", 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16}, | 63 | {"NAND 128MiB 3,3V 16-bit", 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16}, |
64 | {"NAND 128MiB 3,3V 16-bit", 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16}, | 64 | {"NAND 128MiB 3,3V 16-bit", 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16}, |
65 | 65 | ||
66 | {"NAND 256MiB 3,3V 8-bit", 0x71, 512, 256, 0x4000, 0}, | 66 | {"NAND 256MiB 3,3V 8-bit", 0x71, 512, 256, 0x4000, 0}, |
67 | 67 | ||
68 | /* These are the new chips with large page size. The pagesize | 68 | /* These are the new chips with large page size. The pagesize |
@@ -73,7 +73,7 @@ struct nand_flash_dev nand_flash_ids[] = { | |||
73 | {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, | 73 | {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, |
74 | {"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, | 74 | {"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, |
75 | {"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, | 75 | {"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, |
76 | 76 | ||
77 | /* 1 Gigabit */ | 77 | /* 1 Gigabit */ |
78 | {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, | 78 | {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, |
79 | {"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, | 79 | {"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, |
@@ -85,13 +85,13 @@ struct nand_flash_dev nand_flash_ids[] = { | |||
85 | {"NAND 256MiB 3,3V 8-bit", 0xDA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, | 85 | {"NAND 256MiB 3,3V 8-bit", 0xDA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, |
86 | {"NAND 256MiB 1,8V 16-bit", 0xBA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, | 86 | {"NAND 256MiB 1,8V 16-bit", 0xBA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, |
87 | {"NAND 256MiB 3,3V 16-bit", 0xCA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, | 87 | {"NAND 256MiB 3,3V 16-bit", 0xCA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, |
88 | 88 | ||
89 | /* 4 Gigabit */ | 89 | /* 4 Gigabit */ |
90 | {"NAND 512MiB 1,8V 8-bit", 0xAC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, | 90 | {"NAND 512MiB 1,8V 8-bit", 0xAC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, |
91 | {"NAND 512MiB 3,3V 8-bit", 0xDC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, | 91 | {"NAND 512MiB 3,3V 8-bit", 0xDC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, |
92 | {"NAND 512MiB 1,8V 16-bit", 0xBC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, | 92 | {"NAND 512MiB 1,8V 16-bit", 0xBC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, |
93 | {"NAND 512MiB 3,3V 16-bit", 0xCC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, | 93 | {"NAND 512MiB 3,3V 16-bit", 0xCC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, |
94 | 94 | ||
95 | /* 8 Gigabit */ | 95 | /* 8 Gigabit */ |
96 | {"NAND 1GiB 1,8V 8-bit", 0xA3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, | 96 | {"NAND 1GiB 1,8V 8-bit", 0xA3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, |
97 | {"NAND 1GiB 3,3V 8-bit", 0xD3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, | 97 | {"NAND 1GiB 3,3V 8-bit", 0xD3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, |
@@ -104,11 +104,11 @@ struct nand_flash_dev nand_flash_ids[] = { | |||
104 | {"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, | 104 | {"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, |
105 | {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, | 105 | {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, |
106 | 106 | ||
107 | /* Renesas AND 1 Gigabit. Those chips do not support extended id and have a strange page/block layout ! | 107 | /* Renesas AND 1 Gigabit. Those chips do not support extended id and have a strange page/block layout ! |
108 | * The chosen minimum erasesize is 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page planes | 108 | * The chosen minimum erasesize is 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page planes |
109 | * 1 block = 2 pages, but due to plane arrangement the blocks 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7 | 109 | * 1 block = 2 pages, but due to plane arrangement the blocks 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7 |
110 | * Anyway JFFS2 would increase the eraseblock size so we chose a combined one which can be erased in one go | 110 | * Anyway JFFS2 would increase the eraseblock size so we chose a combined one which can be erased in one go |
111 | * There are more speed improvements for reads and writes possible, but not implemented now | 111 | * There are more speed improvements for reads and writes possible, but not implemented now |
112 | */ | 112 | */ |
113 | {"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY | BBT_AUTO_REFRESH}, | 113 | {"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY | BBT_AUTO_REFRESH}, |
114 | 114 | ||
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 754b6ed7ce14..de4500395300 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Author: Artem B. Bityuckiy <dedekind@oktetlabs.ru>, <dedekind@infradead.org> | 4 | * Author: Artem B. Bityuckiy <dedekind@oktetlabs.ru>, <dedekind@infradead.org> |
5 | * | 5 | * |
6 | * Copyright (C) 2004 Nokia Corporation | 6 | * Copyright (C) 2004 Nokia Corporation |
7 | * | 7 | * |
8 | * Note: NS means "NAND Simulator". | 8 | * Note: NS means "NAND Simulator". |
9 | * Note: Input means input TO flash chip, output means output FROM chip. | 9 | * Note: Input means input TO flash chip, output means output FROM chip. |
@@ -126,7 +126,7 @@ MODULE_PARM_DESC(dbg, "Output debug information if not zero"); | |||
126 | 126 | ||
127 | /* The largest possible page size */ | 127 | /* The largest possible page size */ |
128 | #define NS_LARGEST_PAGE_SIZE 2048 | 128 | #define NS_LARGEST_PAGE_SIZE 2048 |
129 | 129 | ||
130 | /* The prefix for simulator output */ | 130 | /* The prefix for simulator output */ |
131 | #define NS_OUTPUT_PREFIX "[nandsim]" | 131 | #define NS_OUTPUT_PREFIX "[nandsim]" |
132 | 132 | ||
@@ -145,7 +145,7 @@ MODULE_PARM_DESC(dbg, "Output debug information if not zero"); | |||
145 | do { if (do_delays) udelay(us); } while(0) | 145 | do { if (do_delays) udelay(us); } while(0) |
146 | #define NS_MDELAY(us) \ | 146 | #define NS_MDELAY(us) \ |
147 | do { if (do_delays) mdelay(us); } while(0) | 147 | do { if (do_delays) mdelay(us); } while(0) |
148 | 148 | ||
149 | /* Is the nandsim structure initialized ? */ | 149 | /* Is the nandsim structure initialized ? */ |
150 | #define NS_IS_INITIALIZED(ns) ((ns)->geom.totsz != 0) | 150 | #define NS_IS_INITIALIZED(ns) ((ns)->geom.totsz != 0) |
151 | 151 | ||
@@ -153,12 +153,12 @@ MODULE_PARM_DESC(dbg, "Output debug information if not zero"); | |||
153 | #define NS_STATUS_OK(ns) (NAND_STATUS_READY | (NAND_STATUS_WP * ((ns)->lines.wp == 0))) | 153 | #define NS_STATUS_OK(ns) (NAND_STATUS_READY | (NAND_STATUS_WP * ((ns)->lines.wp == 0))) |
154 | 154 | ||
155 | /* Operation failed completion status */ | 155 | /* Operation failed completion status */ |
156 | #define NS_STATUS_FAILED(ns) (NAND_STATUS_FAIL | NS_STATUS_OK(ns)) | 156 | #define NS_STATUS_FAILED(ns) (NAND_STATUS_FAIL | NS_STATUS_OK(ns)) |
157 | 157 | ||
158 | /* Calculate the page offset in flash RAM image by (row, column) address */ | 158 | /* Calculate the page offset in flash RAM image by (row, column) address */ |
159 | #define NS_RAW_OFFSET(ns) \ | 159 | #define NS_RAW_OFFSET(ns) \ |
160 | (((ns)->regs.row << (ns)->geom.pgshift) + ((ns)->regs.row * (ns)->geom.oobsz) + (ns)->regs.column) | 160 | (((ns)->regs.row << (ns)->geom.pgshift) + ((ns)->regs.row * (ns)->geom.oobsz) + (ns)->regs.column) |
161 | 161 | ||
162 | /* Calculate the OOB offset in flash RAM image by (row, column) address */ | 162 | /* Calculate the OOB offset in flash RAM image by (row, column) address */ |
163 | #define NS_RAW_OFFSET_OOB(ns) (NS_RAW_OFFSET(ns) + ns->geom.pgsz) | 163 | #define NS_RAW_OFFSET_OOB(ns) (NS_RAW_OFFSET(ns) + ns->geom.pgsz) |
164 | 164 | ||
@@ -223,15 +223,15 @@ MODULE_PARM_DESC(dbg, "Output debug information if not zero"); | |||
223 | 223 | ||
224 | /* Remove action bits ftom state */ | 224 | /* Remove action bits ftom state */ |
225 | #define NS_STATE(x) ((x) & ~ACTION_MASK) | 225 | #define NS_STATE(x) ((x) & ~ACTION_MASK) |
226 | 226 | ||
227 | /* | 227 | /* |
228 | * Maximum previous states which need to be saved. Currently saving is | 228 | * Maximum previous states which need to be saved. Currently saving is |
229 | * only needed for page programm operation with preceeded read command | 229 | * only needed for page programm operation with preceeded read command |
230 | * (which is only valid for 512-byte pages). | 230 | * (which is only valid for 512-byte pages). |
231 | */ | 231 | */ |
232 | #define NS_MAX_PREVSTATES 1 | 232 | #define NS_MAX_PREVSTATES 1 |
233 | 233 | ||
234 | /* | 234 | /* |
235 | * The structure which describes all the internal simulator data. | 235 | * The structure which describes all the internal simulator data. |
236 | */ | 236 | */ |
237 | struct nandsim { | 237 | struct nandsim { |
@@ -242,7 +242,7 @@ struct nandsim { | |||
242 | uint32_t options; /* chip's characteristic bits */ | 242 | uint32_t options; /* chip's characteristic bits */ |
243 | uint32_t state; /* current chip state */ | 243 | uint32_t state; /* current chip state */ |
244 | uint32_t nxstate; /* next expected state */ | 244 | uint32_t nxstate; /* next expected state */ |
245 | 245 | ||
246 | uint32_t *op; /* current operation, NULL operations isn't known yet */ | 246 | uint32_t *op; /* current operation, NULL operations isn't known yet */ |
247 | uint32_t pstates[NS_MAX_PREVSTATES]; /* previous states */ | 247 | uint32_t pstates[NS_MAX_PREVSTATES]; /* previous states */ |
248 | uint16_t npstates; /* number of previous states saved */ | 248 | uint16_t npstates; /* number of previous states saved */ |
@@ -413,7 +413,7 @@ init_nandsim(struct mtd_info *mtd) | |||
413 | ns->geom.secaddrbytes = 3; | 413 | ns->geom.secaddrbytes = 3; |
414 | } | 414 | } |
415 | } | 415 | } |
416 | 416 | ||
417 | /* Detect how many ID bytes the NAND chip outputs */ | 417 | /* Detect how many ID bytes the NAND chip outputs */ |
418 | for (i = 0; nand_flash_ids[i].name != NULL; i++) { | 418 | for (i = 0; nand_flash_ids[i].name != NULL; i++) { |
419 | if (second_id_byte != nand_flash_ids[i].id) | 419 | if (second_id_byte != nand_flash_ids[i].id) |
@@ -444,7 +444,7 @@ init_nandsim(struct mtd_info *mtd) | |||
444 | #ifdef CONFIG_NS_ABS_POS | 444 | #ifdef CONFIG_NS_ABS_POS |
445 | ns->mem.byte = ioremap(CONFIG_NS_ABS_POS, ns->geom.totszoob); | 445 | ns->mem.byte = ioremap(CONFIG_NS_ABS_POS, ns->geom.totszoob); |
446 | if (!ns->mem.byte) { | 446 | if (!ns->mem.byte) { |
447 | NS_ERR("init_nandsim: failed to map the NAND flash image at address %p\n", | 447 | NS_ERR("init_nandsim: failed to map the NAND flash image at address %p\n", |
448 | (void *)CONFIG_NS_ABS_POS); | 448 | (void *)CONFIG_NS_ABS_POS); |
449 | return -ENOMEM; | 449 | return -ENOMEM; |
450 | } | 450 | } |
@@ -567,7 +567,7 @@ static int | |||
567 | check_command(int cmd) | 567 | check_command(int cmd) |
568 | { | 568 | { |
569 | switch (cmd) { | 569 | switch (cmd) { |
570 | 570 | ||
571 | case NAND_CMD_READ0: | 571 | case NAND_CMD_READ0: |
572 | case NAND_CMD_READSTART: | 572 | case NAND_CMD_READSTART: |
573 | case NAND_CMD_PAGEPROG: | 573 | case NAND_CMD_PAGEPROG: |
@@ -580,7 +580,7 @@ check_command(int cmd) | |||
580 | case NAND_CMD_RESET: | 580 | case NAND_CMD_RESET: |
581 | case NAND_CMD_READ1: | 581 | case NAND_CMD_READ1: |
582 | return 0; | 582 | return 0; |
583 | 583 | ||
584 | case NAND_CMD_STATUS_MULTI: | 584 | case NAND_CMD_STATUS_MULTI: |
585 | default: | 585 | default: |
586 | return 1; | 586 | return 1; |
@@ -631,7 +631,7 @@ static inline void | |||
631 | accept_addr_byte(struct nandsim *ns, u_char bt) | 631 | accept_addr_byte(struct nandsim *ns, u_char bt) |
632 | { | 632 | { |
633 | uint byte = (uint)bt; | 633 | uint byte = (uint)bt; |
634 | 634 | ||
635 | if (ns->regs.count < (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) | 635 | if (ns->regs.count < (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) |
636 | ns->regs.column |= (byte << 8 * ns->regs.count); | 636 | ns->regs.column |= (byte << 8 * ns->regs.count); |
637 | else { | 637 | else { |
@@ -642,11 +642,11 @@ accept_addr_byte(struct nandsim *ns, u_char bt) | |||
642 | 642 | ||
643 | return; | 643 | return; |
644 | } | 644 | } |
645 | 645 | ||
646 | /* | 646 | /* |
647 | * Switch to STATE_READY state. | 647 | * Switch to STATE_READY state. |
648 | */ | 648 | */ |
649 | static inline void | 649 | static inline void |
650 | switch_to_ready_state(struct nandsim *ns, u_char status) | 650 | switch_to_ready_state(struct nandsim *ns, u_char status) |
651 | { | 651 | { |
652 | NS_DBG("switch_to_ready_state: switch to %s state\n", get_state_name(STATE_READY)); | 652 | NS_DBG("switch_to_ready_state: switch to %s state\n", get_state_name(STATE_READY)); |
@@ -675,7 +675,7 @@ switch_to_ready_state(struct nandsim *ns, u_char status) | |||
675 | * (for example program from the second half and read from the | 675 | * (for example program from the second half and read from the |
676 | * second half operations both begin with the READ1 command). In this | 676 | * second half operations both begin with the READ1 command). In this |
677 | * case the ns->pstates[] array contains previous states. | 677 | * case the ns->pstates[] array contains previous states. |
678 | * | 678 | * |
679 | * Thus, the function tries to find operation containing the following | 679 | * Thus, the function tries to find operation containing the following |
680 | * states (if the 'flag' parameter is 0): | 680 | * states (if the 'flag' parameter is 0): |
681 | * ns->pstates[0], ... ns->pstates[ns->npstates], ns->state | 681 | * ns->pstates[0], ... ns->pstates[ns->npstates], ns->state |
@@ -683,7 +683,7 @@ switch_to_ready_state(struct nandsim *ns, u_char status) | |||
683 | * If (one and only one) matching operation is found, it is accepted ( | 683 | * If (one and only one) matching operation is found, it is accepted ( |
684 | * ns->ops, ns->state, ns->nxstate are initialized, ns->npstate is | 684 | * ns->ops, ns->state, ns->nxstate are initialized, ns->npstate is |
685 | * zeroed). | 685 | * zeroed). |
686 | * | 686 | * |
687 | * If there are several maches, the current state is pushed to the | 687 | * If there are several maches, the current state is pushed to the |
688 | * ns->pstates. | 688 | * ns->pstates. |
689 | * | 689 | * |
@@ -692,7 +692,7 @@ switch_to_ready_state(struct nandsim *ns, u_char status) | |||
692 | * In such situation the function is called with 'flag' != 0, and the | 692 | * In such situation the function is called with 'flag' != 0, and the |
693 | * operation is searched using the following pattern: | 693 | * operation is searched using the following pattern: |
694 | * ns->pstates[0], ... ns->pstates[ns->npstates], <address input> | 694 | * ns->pstates[0], ... ns->pstates[ns->npstates], <address input> |
695 | * | 695 | * |
696 | * It is supposed that this pattern must either match one operation on | 696 | * It is supposed that this pattern must either match one operation on |
697 | * none. There can't be ambiguity in that case. | 697 | * none. There can't be ambiguity in that case. |
698 | * | 698 | * |
@@ -711,15 +711,15 @@ find_operation(struct nandsim *ns, uint32_t flag) | |||
711 | { | 711 | { |
712 | int opsfound = 0; | 712 | int opsfound = 0; |
713 | int i, j, idx = 0; | 713 | int i, j, idx = 0; |
714 | 714 | ||
715 | for (i = 0; i < NS_OPER_NUM; i++) { | 715 | for (i = 0; i < NS_OPER_NUM; i++) { |
716 | 716 | ||
717 | int found = 1; | 717 | int found = 1; |
718 | 718 | ||
719 | if (!(ns->options & ops[i].reqopts)) | 719 | if (!(ns->options & ops[i].reqopts)) |
720 | /* Ignore operations we can't perform */ | 720 | /* Ignore operations we can't perform */ |
721 | continue; | 721 | continue; |
722 | 722 | ||
723 | if (flag) { | 723 | if (flag) { |
724 | if (!(ops[i].states[ns->npstates] & STATE_ADDR_MASK)) | 724 | if (!(ops[i].states[ns->npstates] & STATE_ADDR_MASK)) |
725 | continue; | 725 | continue; |
@@ -728,7 +728,7 @@ find_operation(struct nandsim *ns, uint32_t flag) | |||
728 | continue; | 728 | continue; |
729 | } | 729 | } |
730 | 730 | ||
731 | for (j = 0; j < ns->npstates; j++) | 731 | for (j = 0; j < ns->npstates; j++) |
732 | if (NS_STATE(ops[i].states[j]) != NS_STATE(ns->pstates[j]) | 732 | if (NS_STATE(ops[i].states[j]) != NS_STATE(ns->pstates[j]) |
733 | && (ns->options & ops[idx].reqopts)) { | 733 | && (ns->options & ops[idx].reqopts)) { |
734 | found = 0; | 734 | found = 0; |
@@ -745,7 +745,7 @@ find_operation(struct nandsim *ns, uint32_t flag) | |||
745 | /* Exact match */ | 745 | /* Exact match */ |
746 | ns->op = &ops[idx].states[0]; | 746 | ns->op = &ops[idx].states[0]; |
747 | if (flag) { | 747 | if (flag) { |
748 | /* | 748 | /* |
749 | * In this case the find_operation function was | 749 | * In this case the find_operation function was |
750 | * called when address has just began input. But it isn't | 750 | * called when address has just began input. But it isn't |
751 | * yet fully input and the current state must | 751 | * yet fully input and the current state must |
@@ -763,7 +763,7 @@ find_operation(struct nandsim *ns, uint32_t flag) | |||
763 | idx, get_state_name(ns->state), get_state_name(ns->nxstate)); | 763 | idx, get_state_name(ns->state), get_state_name(ns->nxstate)); |
764 | return 0; | 764 | return 0; |
765 | } | 765 | } |
766 | 766 | ||
767 | if (opsfound == 0) { | 767 | if (opsfound == 0) { |
768 | /* Nothing was found. Try to ignore previous commands (if any) and search again */ | 768 | /* Nothing was found. Try to ignore previous commands (if any) and search again */ |
769 | if (ns->npstates != 0) { | 769 | if (ns->npstates != 0) { |
@@ -777,13 +777,13 @@ find_operation(struct nandsim *ns, uint32_t flag) | |||
777 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | 777 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); |
778 | return -2; | 778 | return -2; |
779 | } | 779 | } |
780 | 780 | ||
781 | if (flag) { | 781 | if (flag) { |
782 | /* This shouldn't happen */ | 782 | /* This shouldn't happen */ |
783 | NS_DBG("find_operation: BUG, operation must be known if address is input\n"); | 783 | NS_DBG("find_operation: BUG, operation must be known if address is input\n"); |
784 | return -2; | 784 | return -2; |
785 | } | 785 | } |
786 | 786 | ||
787 | NS_DBG("find_operation: there is still ambiguity\n"); | 787 | NS_DBG("find_operation: there is still ambiguity\n"); |
788 | 788 | ||
789 | ns->pstates[ns->npstates++] = ns->state; | 789 | ns->pstates[ns->npstates++] = ns->state; |
@@ -803,7 +803,7 @@ do_state_action(struct nandsim *ns, uint32_t action) | |||
803 | int busdiv = ns->busw == 8 ? 1 : 2; | 803 | int busdiv = ns->busw == 8 ? 1 : 2; |
804 | 804 | ||
805 | action &= ACTION_MASK; | 805 | action &= ACTION_MASK; |
806 | 806 | ||
807 | /* Check that page address input is correct */ | 807 | /* Check that page address input is correct */ |
808 | if (action != ACTION_SECERASE && ns->regs.row >= ns->geom.pgnum) { | 808 | if (action != ACTION_SECERASE && ns->regs.row >= ns->geom.pgnum) { |
809 | NS_WARN("do_state_action: wrong page number (%#x)\n", ns->regs.row); | 809 | NS_WARN("do_state_action: wrong page number (%#x)\n", ns->regs.row); |
@@ -827,14 +827,14 @@ do_state_action(struct nandsim *ns, uint32_t action) | |||
827 | 827 | ||
828 | NS_DBG("do_state_action: (ACTION_CPY:) copy %d bytes to int buf, raw offset %d\n", | 828 | NS_DBG("do_state_action: (ACTION_CPY:) copy %d bytes to int buf, raw offset %d\n", |
829 | num, NS_RAW_OFFSET(ns) + ns->regs.off); | 829 | num, NS_RAW_OFFSET(ns) + ns->regs.off); |
830 | 830 | ||
831 | if (ns->regs.off == 0) | 831 | if (ns->regs.off == 0) |
832 | NS_LOG("read page %d\n", ns->regs.row); | 832 | NS_LOG("read page %d\n", ns->regs.row); |
833 | else if (ns->regs.off < ns->geom.pgsz) | 833 | else if (ns->regs.off < ns->geom.pgsz) |
834 | NS_LOG("read page %d (second half)\n", ns->regs.row); | 834 | NS_LOG("read page %d (second half)\n", ns->regs.row); |
835 | else | 835 | else |
836 | NS_LOG("read OOB of page %d\n", ns->regs.row); | 836 | NS_LOG("read OOB of page %d\n", ns->regs.row); |
837 | 837 | ||
838 | NS_UDELAY(access_delay); | 838 | NS_UDELAY(access_delay); |
839 | NS_UDELAY(input_cycle * ns->geom.pgsz / 1000 / busdiv); | 839 | NS_UDELAY(input_cycle * ns->geom.pgsz / 1000 / busdiv); |
840 | 840 | ||
@@ -844,30 +844,30 @@ do_state_action(struct nandsim *ns, uint32_t action) | |||
844 | /* | 844 | /* |
845 | * Erase sector. | 845 | * Erase sector. |
846 | */ | 846 | */ |
847 | 847 | ||
848 | if (ns->lines.wp) { | 848 | if (ns->lines.wp) { |
849 | NS_ERR("do_state_action: device is write-protected, ignore sector erase\n"); | 849 | NS_ERR("do_state_action: device is write-protected, ignore sector erase\n"); |
850 | return -1; | 850 | return -1; |
851 | } | 851 | } |
852 | 852 | ||
853 | if (ns->regs.row >= ns->geom.pgnum - ns->geom.pgsec | 853 | if (ns->regs.row >= ns->geom.pgnum - ns->geom.pgsec |
854 | || (ns->regs.row & ~(ns->geom.secsz - 1))) { | 854 | || (ns->regs.row & ~(ns->geom.secsz - 1))) { |
855 | NS_ERR("do_state_action: wrong sector address (%#x)\n", ns->regs.row); | 855 | NS_ERR("do_state_action: wrong sector address (%#x)\n", ns->regs.row); |
856 | return -1; | 856 | return -1; |
857 | } | 857 | } |
858 | 858 | ||
859 | ns->regs.row = (ns->regs.row << | 859 | ns->regs.row = (ns->regs.row << |
860 | 8 * (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) | ns->regs.column; | 860 | 8 * (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) | ns->regs.column; |
861 | ns->regs.column = 0; | 861 | ns->regs.column = 0; |
862 | 862 | ||
863 | NS_DBG("do_state_action: erase sector at address %#x, off = %d\n", | 863 | NS_DBG("do_state_action: erase sector at address %#x, off = %d\n", |
864 | ns->regs.row, NS_RAW_OFFSET(ns)); | 864 | ns->regs.row, NS_RAW_OFFSET(ns)); |
865 | NS_LOG("erase sector %d\n", ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift)); | 865 | NS_LOG("erase sector %d\n", ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift)); |
866 | 866 | ||
867 | memset(ns->mem.byte + NS_RAW_OFFSET(ns), 0xFF, ns->geom.secszoob); | 867 | memset(ns->mem.byte + NS_RAW_OFFSET(ns), 0xFF, ns->geom.secszoob); |
868 | 868 | ||
869 | NS_MDELAY(erase_delay); | 869 | NS_MDELAY(erase_delay); |
870 | 870 | ||
871 | break; | 871 | break; |
872 | 872 | ||
873 | case ACTION_PRGPAGE: | 873 | case ACTION_PRGPAGE: |
@@ -893,12 +893,12 @@ do_state_action(struct nandsim *ns, uint32_t action) | |||
893 | NS_DBG("do_state_action: copy %d bytes from int buf to (%#x, %#x), raw off = %d\n", | 893 | NS_DBG("do_state_action: copy %d bytes from int buf to (%#x, %#x), raw off = %d\n", |
894 | num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off); | 894 | num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off); |
895 | NS_LOG("programm page %d\n", ns->regs.row); | 895 | NS_LOG("programm page %d\n", ns->regs.row); |
896 | 896 | ||
897 | NS_UDELAY(programm_delay); | 897 | NS_UDELAY(programm_delay); |
898 | NS_UDELAY(output_cycle * ns->geom.pgsz / 1000 / busdiv); | 898 | NS_UDELAY(output_cycle * ns->geom.pgsz / 1000 / busdiv); |
899 | 899 | ||
900 | break; | 900 | break; |
901 | 901 | ||
902 | case ACTION_ZEROOFF: | 902 | case ACTION_ZEROOFF: |
903 | NS_DBG("do_state_action: set internal offset to 0\n"); | 903 | NS_DBG("do_state_action: set internal offset to 0\n"); |
904 | ns->regs.off = 0; | 904 | ns->regs.off = 0; |
@@ -918,7 +918,7 @@ do_state_action(struct nandsim *ns, uint32_t action) | |||
918 | NS_DBG("do_state_action: set internal offset to %d\n", ns->geom.pgsz); | 918 | NS_DBG("do_state_action: set internal offset to %d\n", ns->geom.pgsz); |
919 | ns->regs.off = ns->geom.pgsz; | 919 | ns->regs.off = ns->geom.pgsz; |
920 | break; | 920 | break; |
921 | 921 | ||
922 | default: | 922 | default: |
923 | NS_DBG("do_state_action: BUG! unknown action\n"); | 923 | NS_DBG("do_state_action: BUG! unknown action\n"); |
924 | } | 924 | } |
@@ -937,7 +937,7 @@ switch_state(struct nandsim *ns) | |||
937 | * The current operation have already been identified. | 937 | * The current operation have already been identified. |
938 | * Just follow the states chain. | 938 | * Just follow the states chain. |
939 | */ | 939 | */ |
940 | 940 | ||
941 | ns->stateidx += 1; | 941 | ns->stateidx += 1; |
942 | ns->state = ns->nxstate; | 942 | ns->state = ns->nxstate; |
943 | ns->nxstate = ns->op[ns->stateidx + 1]; | 943 | ns->nxstate = ns->op[ns->stateidx + 1]; |
@@ -951,14 +951,14 @@ switch_state(struct nandsim *ns) | |||
951 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | 951 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); |
952 | return; | 952 | return; |
953 | } | 953 | } |
954 | 954 | ||
955 | } else { | 955 | } else { |
956 | /* | 956 | /* |
957 | * We don't yet know which operation we perform. | 957 | * We don't yet know which operation we perform. |
958 | * Try to identify it. | 958 | * Try to identify it. |
959 | */ | 959 | */ |
960 | 960 | ||
961 | /* | 961 | /* |
962 | * The only event causing the switch_state function to | 962 | * The only event causing the switch_state function to |
963 | * be called with yet unknown operation is new command. | 963 | * be called with yet unknown operation is new command. |
964 | */ | 964 | */ |
@@ -987,7 +987,7 @@ switch_state(struct nandsim *ns) | |||
987 | */ | 987 | */ |
988 | 988 | ||
989 | u_char status = NS_STATUS_OK(ns); | 989 | u_char status = NS_STATUS_OK(ns); |
990 | 990 | ||
991 | /* In case of data states, see if all bytes were input/output */ | 991 | /* In case of data states, see if all bytes were input/output */ |
992 | if ((ns->state & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) | 992 | if ((ns->state & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) |
993 | && ns->regs.count != ns->regs.num) { | 993 | && ns->regs.count != ns->regs.num) { |
@@ -995,17 +995,17 @@ switch_state(struct nandsim *ns) | |||
995 | ns->regs.num - ns->regs.count); | 995 | ns->regs.num - ns->regs.count); |
996 | status = NS_STATUS_FAILED(ns); | 996 | status = NS_STATUS_FAILED(ns); |
997 | } | 997 | } |
998 | 998 | ||
999 | NS_DBG("switch_state: operation complete, switch to STATE_READY state\n"); | 999 | NS_DBG("switch_state: operation complete, switch to STATE_READY state\n"); |
1000 | 1000 | ||
1001 | switch_to_ready_state(ns, status); | 1001 | switch_to_ready_state(ns, status); |
1002 | 1002 | ||
1003 | return; | 1003 | return; |
1004 | } else if (ns->nxstate & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) { | 1004 | } else if (ns->nxstate & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) { |
1005 | /* | 1005 | /* |
1006 | * If the next state is data input/output, switch to it now | 1006 | * If the next state is data input/output, switch to it now |
1007 | */ | 1007 | */ |
1008 | 1008 | ||
1009 | ns->state = ns->nxstate; | 1009 | ns->state = ns->nxstate; |
1010 | ns->nxstate = ns->op[++ns->stateidx + 1]; | 1010 | ns->nxstate = ns->op[++ns->stateidx + 1]; |
1011 | ns->regs.num = ns->regs.count = 0; | 1011 | ns->regs.num = ns->regs.count = 0; |
@@ -1023,16 +1023,16 @@ switch_state(struct nandsim *ns) | |||
1023 | case STATE_DATAOUT: | 1023 | case STATE_DATAOUT: |
1024 | ns->regs.num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; | 1024 | ns->regs.num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; |
1025 | break; | 1025 | break; |
1026 | 1026 | ||
1027 | case STATE_DATAOUT_ID: | 1027 | case STATE_DATAOUT_ID: |
1028 | ns->regs.num = ns->geom.idbytes; | 1028 | ns->regs.num = ns->geom.idbytes; |
1029 | break; | 1029 | break; |
1030 | 1030 | ||
1031 | case STATE_DATAOUT_STATUS: | 1031 | case STATE_DATAOUT_STATUS: |
1032 | case STATE_DATAOUT_STATUS_M: | 1032 | case STATE_DATAOUT_STATUS_M: |
1033 | ns->regs.count = ns->regs.num = 0; | 1033 | ns->regs.count = ns->regs.num = 0; |
1034 | break; | 1034 | break; |
1035 | 1035 | ||
1036 | default: | 1036 | default: |
1037 | NS_ERR("switch_state: BUG! unknown data state\n"); | 1037 | NS_ERR("switch_state: BUG! unknown data state\n"); |
1038 | } | 1038 | } |
@@ -1044,16 +1044,16 @@ switch_state(struct nandsim *ns) | |||
1044 | */ | 1044 | */ |
1045 | 1045 | ||
1046 | ns->regs.count = 0; | 1046 | ns->regs.count = 0; |
1047 | 1047 | ||
1048 | switch (NS_STATE(ns->nxstate)) { | 1048 | switch (NS_STATE(ns->nxstate)) { |
1049 | case STATE_ADDR_PAGE: | 1049 | case STATE_ADDR_PAGE: |
1050 | ns->regs.num = ns->geom.pgaddrbytes; | 1050 | ns->regs.num = ns->geom.pgaddrbytes; |
1051 | 1051 | ||
1052 | break; | 1052 | break; |
1053 | case STATE_ADDR_SEC: | 1053 | case STATE_ADDR_SEC: |
1054 | ns->regs.num = ns->geom.secaddrbytes; | 1054 | ns->regs.num = ns->geom.secaddrbytes; |
1055 | break; | 1055 | break; |
1056 | 1056 | ||
1057 | case STATE_ADDR_ZERO: | 1057 | case STATE_ADDR_ZERO: |
1058 | ns->regs.num = 1; | 1058 | ns->regs.num = 1; |
1059 | break; | 1059 | break; |
@@ -1062,7 +1062,7 @@ switch_state(struct nandsim *ns) | |||
1062 | NS_ERR("switch_state: BUG! unknown address state\n"); | 1062 | NS_ERR("switch_state: BUG! unknown address state\n"); |
1063 | } | 1063 | } |
1064 | } else { | 1064 | } else { |
1065 | /* | 1065 | /* |
1066 | * Just reset internal counters. | 1066 | * Just reset internal counters. |
1067 | */ | 1067 | */ |
1068 | 1068 | ||
@@ -1184,7 +1184,7 @@ ns_nand_read_byte(struct mtd_info *mtd) | |||
1184 | default: | 1184 | default: |
1185 | BUG(); | 1185 | BUG(); |
1186 | } | 1186 | } |
1187 | 1187 | ||
1188 | if (ns->regs.count == ns->regs.num) { | 1188 | if (ns->regs.count == ns->regs.num) { |
1189 | NS_DBG("read_byte: all bytes were read\n"); | 1189 | NS_DBG("read_byte: all bytes were read\n"); |
1190 | 1190 | ||
@@ -1201,9 +1201,9 @@ ns_nand_read_byte(struct mtd_info *mtd) | |||
1201 | } | 1201 | } |
1202 | else if (NS_STATE(ns->nxstate) == STATE_READY) | 1202 | else if (NS_STATE(ns->nxstate) == STATE_READY) |
1203 | switch_state(ns); | 1203 | switch_state(ns); |
1204 | 1204 | ||
1205 | } | 1205 | } |
1206 | 1206 | ||
1207 | return outb; | 1207 | return outb; |
1208 | } | 1208 | } |
1209 | 1209 | ||
@@ -1211,7 +1211,7 @@ static void | |||
1211 | ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | 1211 | ns_nand_write_byte(struct mtd_info *mtd, u_char byte) |
1212 | { | 1212 | { |
1213 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | 1213 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; |
1214 | 1214 | ||
1215 | /* Sanity and correctness checks */ | 1215 | /* Sanity and correctness checks */ |
1216 | if (!ns->lines.ce) { | 1216 | if (!ns->lines.ce) { |
1217 | NS_ERR("write_byte: chip is disabled, ignore write\n"); | 1217 | NS_ERR("write_byte: chip is disabled, ignore write\n"); |
@@ -1221,7 +1221,7 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | |||
1221 | NS_ERR("write_byte: ALE and CLE pins are high simultaneously, ignore write\n"); | 1221 | NS_ERR("write_byte: ALE and CLE pins are high simultaneously, ignore write\n"); |
1222 | return; | 1222 | return; |
1223 | } | 1223 | } |
1224 | 1224 | ||
1225 | if (ns->lines.cle == 1) { | 1225 | if (ns->lines.cle == 1) { |
1226 | /* | 1226 | /* |
1227 | * The byte written is a command. | 1227 | * The byte written is a command. |
@@ -1233,7 +1233,7 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | |||
1233 | return; | 1233 | return; |
1234 | } | 1234 | } |
1235 | 1235 | ||
1236 | /* | 1236 | /* |
1237 | * Chip might still be in STATE_DATAOUT | 1237 | * Chip might still be in STATE_DATAOUT |
1238 | * (if OPT_AUTOINCR feature is supported), STATE_DATAOUT_STATUS or | 1238 | * (if OPT_AUTOINCR feature is supported), STATE_DATAOUT_STATUS or |
1239 | * STATE_DATAOUT_STATUS_M state. If so, switch state. | 1239 | * STATE_DATAOUT_STATUS_M state. If so, switch state. |
@@ -1254,13 +1254,13 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | |||
1254 | "ignore previous states\n", (uint)byte, get_state_name(ns->nxstate)); | 1254 | "ignore previous states\n", (uint)byte, get_state_name(ns->nxstate)); |
1255 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | 1255 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); |
1256 | } | 1256 | } |
1257 | 1257 | ||
1258 | /* Check that the command byte is correct */ | 1258 | /* Check that the command byte is correct */ |
1259 | if (check_command(byte)) { | 1259 | if (check_command(byte)) { |
1260 | NS_ERR("write_byte: unknown command %#x\n", (uint)byte); | 1260 | NS_ERR("write_byte: unknown command %#x\n", (uint)byte); |
1261 | return; | 1261 | return; |
1262 | } | 1262 | } |
1263 | 1263 | ||
1264 | NS_DBG("command byte corresponding to %s state accepted\n", | 1264 | NS_DBG("command byte corresponding to %s state accepted\n", |
1265 | get_state_name(get_state_by_command(byte))); | 1265 | get_state_name(get_state_by_command(byte))); |
1266 | ns->regs.command = byte; | 1266 | ns->regs.command = byte; |
@@ -1277,12 +1277,12 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | |||
1277 | 1277 | ||
1278 | if (find_operation(ns, 1) < 0) | 1278 | if (find_operation(ns, 1) < 0) |
1279 | return; | 1279 | return; |
1280 | 1280 | ||
1281 | if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) { | 1281 | if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) { |
1282 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | 1282 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); |
1283 | return; | 1283 | return; |
1284 | } | 1284 | } |
1285 | 1285 | ||
1286 | ns->regs.count = 0; | 1286 | ns->regs.count = 0; |
1287 | switch (NS_STATE(ns->nxstate)) { | 1287 | switch (NS_STATE(ns->nxstate)) { |
1288 | case STATE_ADDR_PAGE: | 1288 | case STATE_ADDR_PAGE: |
@@ -1306,7 +1306,7 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | |||
1306 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | 1306 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); |
1307 | return; | 1307 | return; |
1308 | } | 1308 | } |
1309 | 1309 | ||
1310 | /* Check if this is expected byte */ | 1310 | /* Check if this is expected byte */ |
1311 | if (ns->regs.count == ns->regs.num) { | 1311 | if (ns->regs.count == ns->regs.num) { |
1312 | NS_ERR("write_byte: no more address bytes expected\n"); | 1312 | NS_ERR("write_byte: no more address bytes expected\n"); |
@@ -1325,12 +1325,12 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | |||
1325 | NS_DBG("address (%#x, %#x) is accepted\n", ns->regs.row, ns->regs.column); | 1325 | NS_DBG("address (%#x, %#x) is accepted\n", ns->regs.row, ns->regs.column); |
1326 | switch_state(ns); | 1326 | switch_state(ns); |
1327 | } | 1327 | } |
1328 | 1328 | ||
1329 | } else { | 1329 | } else { |
1330 | /* | 1330 | /* |
1331 | * The byte written is an input data. | 1331 | * The byte written is an input data. |
1332 | */ | 1332 | */ |
1333 | 1333 | ||
1334 | /* Check that chip is expecting data input */ | 1334 | /* Check that chip is expecting data input */ |
1335 | if (!(ns->state & STATE_DATAIN_MASK)) { | 1335 | if (!(ns->state & STATE_DATAIN_MASK)) { |
1336 | NS_ERR("write_byte: data input (%#x) isn't expected, state is %s, " | 1336 | NS_ERR("write_byte: data input (%#x) isn't expected, state is %s, " |
@@ -1372,7 +1372,7 @@ ns_nand_read_word(struct mtd_info *mtd) | |||
1372 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; | 1372 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; |
1373 | 1373 | ||
1374 | NS_DBG("read_word\n"); | 1374 | NS_DBG("read_word\n"); |
1375 | 1375 | ||
1376 | return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8); | 1376 | return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8); |
1377 | } | 1377 | } |
1378 | 1378 | ||
@@ -1380,14 +1380,14 @@ static void | |||
1380 | ns_nand_write_word(struct mtd_info *mtd, uint16_t word) | 1380 | ns_nand_write_word(struct mtd_info *mtd, uint16_t word) |
1381 | { | 1381 | { |
1382 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; | 1382 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; |
1383 | 1383 | ||
1384 | NS_DBG("write_word\n"); | 1384 | NS_DBG("write_word\n"); |
1385 | 1385 | ||
1386 | chip->write_byte(mtd, word & 0xFF); | 1386 | chip->write_byte(mtd, word & 0xFF); |
1387 | chip->write_byte(mtd, word >> 8); | 1387 | chip->write_byte(mtd, word >> 8); |
1388 | } | 1388 | } |
1389 | 1389 | ||
1390 | static void | 1390 | static void |
1391 | ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | 1391 | ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) |
1392 | { | 1392 | { |
1393 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | 1393 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; |
@@ -1409,13 +1409,13 @@ ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | |||
1409 | 1409 | ||
1410 | memcpy(ns->buf.byte + ns->regs.count, buf, len); | 1410 | memcpy(ns->buf.byte + ns->regs.count, buf, len); |
1411 | ns->regs.count += len; | 1411 | ns->regs.count += len; |
1412 | 1412 | ||
1413 | if (ns->regs.count == ns->regs.num) { | 1413 | if (ns->regs.count == ns->regs.num) { |
1414 | NS_DBG("write_buf: %d bytes were written\n", ns->regs.count); | 1414 | NS_DBG("write_buf: %d bytes were written\n", ns->regs.count); |
1415 | } | 1415 | } |
1416 | } | 1416 | } |
1417 | 1417 | ||
1418 | static void | 1418 | static void |
1419 | ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | 1419 | ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) |
1420 | { | 1420 | { |
1421 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | 1421 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; |
@@ -1453,7 +1453,7 @@ ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | |||
1453 | 1453 | ||
1454 | memcpy(buf, ns->buf.byte + ns->regs.count, len); | 1454 | memcpy(buf, ns->buf.byte + ns->regs.count, len); |
1455 | ns->regs.count += len; | 1455 | ns->regs.count += len; |
1456 | 1456 | ||
1457 | if (ns->regs.count == ns->regs.num) { | 1457 | if (ns->regs.count == ns->regs.num) { |
1458 | if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) { | 1458 | if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) { |
1459 | ns->regs.count = 0; | 1459 | ns->regs.count = 0; |
@@ -1465,11 +1465,11 @@ ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | |||
1465 | else if (NS_STATE(ns->nxstate) == STATE_READY) | 1465 | else if (NS_STATE(ns->nxstate) == STATE_READY) |
1466 | switch_state(ns); | 1466 | switch_state(ns); |
1467 | } | 1467 | } |
1468 | 1468 | ||
1469 | return; | 1469 | return; |
1470 | } | 1470 | } |
1471 | 1471 | ||
1472 | static int | 1472 | static int |
1473 | ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) | 1473 | ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) |
1474 | { | 1474 | { |
1475 | ns_nand_read_buf(mtd, (u_char *)&ns_verify_buf[0], len); | 1475 | ns_nand_read_buf(mtd, (u_char *)&ns_verify_buf[0], len); |
@@ -1496,7 +1496,7 @@ int __init ns_init_module(void) | |||
1496 | NS_ERR("wrong bus width (%d), use only 8 or 16\n", bus_width); | 1496 | NS_ERR("wrong bus width (%d), use only 8 or 16\n", bus_width); |
1497 | return -EINVAL; | 1497 | return -EINVAL; |
1498 | } | 1498 | } |
1499 | 1499 | ||
1500 | /* Allocate and initialize mtd_info, nand_chip and nandsim structures */ | 1500 | /* Allocate and initialize mtd_info, nand_chip and nandsim structures */ |
1501 | nsmtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip) | 1501 | nsmtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip) |
1502 | + sizeof(struct nandsim), GFP_KERNEL); | 1502 | + sizeof(struct nandsim), GFP_KERNEL); |
@@ -1509,7 +1509,7 @@ int __init ns_init_module(void) | |||
1509 | chip = (struct nand_chip *)(nsmtd + 1); | 1509 | chip = (struct nand_chip *)(nsmtd + 1); |
1510 | nsmtd->priv = (void *)chip; | 1510 | nsmtd->priv = (void *)chip; |
1511 | nand = (struct nandsim *)(chip + 1); | 1511 | nand = (struct nandsim *)(chip + 1); |
1512 | chip->priv = (void *)nand; | 1512 | chip->priv = (void *)nand; |
1513 | 1513 | ||
1514 | /* | 1514 | /* |
1515 | * Register simulator's callbacks. | 1515 | * Register simulator's callbacks. |
@@ -1526,9 +1526,9 @@ int __init ns_init_module(void) | |||
1526 | chip->eccmode = NAND_ECC_SOFT; | 1526 | chip->eccmode = NAND_ECC_SOFT; |
1527 | chip->options |= NAND_SKIP_BBTSCAN; | 1527 | chip->options |= NAND_SKIP_BBTSCAN; |
1528 | 1528 | ||
1529 | /* | 1529 | /* |
1530 | * Perform minimum nandsim structure initialization to handle | 1530 | * Perform minimum nandsim structure initialization to handle |
1531 | * the initial ID read command correctly | 1531 | * the initial ID read command correctly |
1532 | */ | 1532 | */ |
1533 | if (third_id_byte != 0xFF || fourth_id_byte != 0xFF) | 1533 | if (third_id_byte != 0xFF || fourth_id_byte != 0xFF) |
1534 | nand->geom.idbytes = 4; | 1534 | nand->geom.idbytes = 4; |
@@ -1557,7 +1557,7 @@ int __init ns_init_module(void) | |||
1557 | NS_ERR("scan_bbt: can't initialize the nandsim structure\n"); | 1557 | NS_ERR("scan_bbt: can't initialize the nandsim structure\n"); |
1558 | goto error; | 1558 | goto error; |
1559 | } | 1559 | } |
1560 | 1560 | ||
1561 | if ((retval = nand_default_bbt(nsmtd)) != 0) { | 1561 | if ((retval = nand_default_bbt(nsmtd)) != 0) { |
1562 | free_nandsim(nand); | 1562 | free_nandsim(nand); |
1563 | goto error; | 1563 | goto error; |
diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c index e510a83d7bdb..91a95f34a6ee 100644 --- a/drivers/mtd/nand/ppchameleonevb.c +++ b/drivers/mtd/nand/ppchameleonevb.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Derived from drivers/mtd/nand/edb7312.c | 6 | * Derived from drivers/mtd/nand/edb7312.c |
7 | * | 7 | * |
8 | * | 8 | * |
9 | * $Id: ppchameleonevb.c,v 1.6 2004/11/05 16:07:16 kalev Exp $ | 9 | * $Id: ppchameleonevb.c,v 1.7 2005/11/07 11:14:31 gleixner Exp $ |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2 as | 12 | * it under the terms of the GNU General Public License version 2 as |
@@ -338,7 +338,7 @@ nand_evb_init: | |||
338 | out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFFFFFFF0); | 338 | out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFFFFFFF0); |
339 | out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0x3FFFFFFF); | 339 | out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0x3FFFFFFF); |
340 | /* enable output driver */ | 340 | /* enable output driver */ |
341 | out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN | | 341 | out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN | |
342 | NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN); | 342 | NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN); |
343 | #ifdef USE_READY_BUSY_PIN | 343 | #ifdef USE_READY_BUSY_PIN |
344 | /* three-state select */ | 344 | /* three-state select */ |
@@ -402,7 +402,7 @@ static void __exit ppchameleonevb_cleanup (void) | |||
402 | /* Release resources, unregister device(s) */ | 402 | /* Release resources, unregister device(s) */ |
403 | nand_release (ppchameleon_mtd); | 403 | nand_release (ppchameleon_mtd); |
404 | nand_release (ppchameleonevb_mtd); | 404 | nand_release (ppchameleonevb_mtd); |
405 | 405 | ||
406 | /* Release iomaps */ | 406 | /* Release iomaps */ |
407 | this = (struct nand_chip *) &ppchameleon_mtd[1]; | 407 | this = (struct nand_chip *) &ppchameleon_mtd[1]; |
408 | iounmap((void *) this->IO_ADDR_R; | 408 | iounmap((void *) this->IO_ADDR_R; |
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c index 031051cbde76..3a5841c9d950 100644 --- a/drivers/mtd/nand/rtc_from4.c +++ b/drivers/mtd/nand/rtc_from4.c | |||
@@ -2,11 +2,11 @@ | |||
2 | * drivers/mtd/nand/rtc_from4.c | 2 | * drivers/mtd/nand/rtc_from4.c |
3 | * | 3 | * |
4 | * Copyright (C) 2004 Red Hat, Inc. | 4 | * Copyright (C) 2004 Red Hat, Inc. |
5 | * | 5 | * |
6 | * Derived from drivers/mtd/nand/spia.c | 6 | * Derived from drivers/mtd/nand/spia.c |
7 | * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) | 7 | * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) |
8 | * | 8 | * |
9 | * $Id: rtc_from4.c,v 1.9 2005/01/24 20:40:11 dmarlin Exp $ | 9 | * $Id: rtc_from4.c,v 1.10 2005/11/07 11:14:31 gleixner Exp $ |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2 as | 12 | * it under the terms of the GNU General Public License version 2 as |
@@ -14,8 +14,8 @@ | |||
14 | * | 14 | * |
15 | * Overview: | 15 | * Overview: |
16 | * This is a device driver for the AG-AND flash device found on the | 16 | * This is a device driver for the AG-AND flash device found on the |
17 | * Renesas Technology Corp. Flash ROM 4-slot interface board (FROM_BOARD4), | 17 | * Renesas Technology Corp. Flash ROM 4-slot interface board (FROM_BOARD4), |
18 | * which utilizes the Renesas HN29V1G91T-30 part. | 18 | * which utilizes the Renesas HN29V1G91T-30 part. |
19 | * This chip is a 1 GBibit (128MiB x 8 bits) AG-AND flash device. | 19 | * This chip is a 1 GBibit (128MiB x 8 bits) AG-AND flash device. |
20 | */ | 20 | */ |
21 | 21 | ||
@@ -105,9 +105,9 @@ const static struct mtd_partition partition_info[] = { | |||
105 | }; | 105 | }; |
106 | #define NUM_PARTITIONS 1 | 106 | #define NUM_PARTITIONS 1 |
107 | 107 | ||
108 | /* | 108 | /* |
109 | * hardware specific flash bbt decriptors | 109 | * hardware specific flash bbt decriptors |
110 | * Note: this is to allow debugging by disabling | 110 | * Note: this is to allow debugging by disabling |
111 | * NAND_BBT_CREATE and/or NAND_BBT_WRITE | 111 | * NAND_BBT_CREATE and/or NAND_BBT_WRITE |
112 | * | 112 | * |
113 | */ | 113 | */ |
@@ -141,7 +141,7 @@ static struct nand_bbt_descr rtc_from4_bbt_mirror_descr = { | |||
141 | /* the Reed Solomon control structure */ | 141 | /* the Reed Solomon control structure */ |
142 | static struct rs_control *rs_decoder; | 142 | static struct rs_control *rs_decoder; |
143 | 143 | ||
144 | /* | 144 | /* |
145 | * hardware specific Out Of Band information | 145 | * hardware specific Out Of Band information |
146 | */ | 146 | */ |
147 | static struct nand_oobinfo rtc_from4_nand_oobinfo = { | 147 | static struct nand_oobinfo rtc_from4_nand_oobinfo = { |
@@ -200,38 +200,38 @@ static uint8_t revbits[256] = { | |||
200 | 200 | ||
201 | 201 | ||
202 | 202 | ||
203 | /* | 203 | /* |
204 | * rtc_from4_hwcontrol - hardware specific access to control-lines | 204 | * rtc_from4_hwcontrol - hardware specific access to control-lines |
205 | * @mtd: MTD device structure | 205 | * @mtd: MTD device structure |
206 | * @cmd: hardware control command | 206 | * @cmd: hardware control command |
207 | * | 207 | * |
208 | * Address lines (A5 and A4) are used to control Command and Address Latch | 208 | * Address lines (A5 and A4) are used to control Command and Address Latch |
209 | * Enable on this board, so set the read/write address appropriately. | 209 | * Enable on this board, so set the read/write address appropriately. |
210 | * | 210 | * |
211 | * Chip Enable is also controlled by the Chip Select (CS5) and | 211 | * Chip Enable is also controlled by the Chip Select (CS5) and |
212 | * Address lines (A24-A22), so no action is required here. | 212 | * Address lines (A24-A22), so no action is required here. |
213 | * | 213 | * |
214 | */ | 214 | */ |
215 | static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd) | 215 | static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd) |
216 | { | 216 | { |
217 | struct nand_chip* this = (struct nand_chip *) (mtd->priv); | 217 | struct nand_chip* this = (struct nand_chip *) (mtd->priv); |
218 | 218 | ||
219 | switch(cmd) { | 219 | switch(cmd) { |
220 | 220 | ||
221 | case NAND_CTL_SETCLE: | 221 | case NAND_CTL_SETCLE: |
222 | this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_CLE); | 222 | this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_CLE); |
223 | break; | 223 | break; |
224 | case NAND_CTL_CLRCLE: | 224 | case NAND_CTL_CLRCLE: |
225 | this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_CLE); | 225 | this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_CLE); |
226 | break; | 226 | break; |
227 | 227 | ||
228 | case NAND_CTL_SETALE: | 228 | case NAND_CTL_SETALE: |
229 | this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_ALE); | 229 | this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_ALE); |
230 | break; | 230 | break; |
231 | case NAND_CTL_CLRALE: | 231 | case NAND_CTL_CLRALE: |
232 | this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_ALE); | 232 | this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_ALE); |
233 | break; | 233 | break; |
234 | 234 | ||
235 | case NAND_CTL_SETNCE: | 235 | case NAND_CTL_SETNCE: |
236 | break; | 236 | break; |
237 | case NAND_CTL_CLRNCE: | 237 | case NAND_CTL_CLRNCE: |
@@ -296,7 +296,7 @@ static int rtc_from4_nand_device_ready(struct mtd_info *mtd) | |||
296 | * @mtd: MTD device structure | 296 | * @mtd: MTD device structure |
297 | * @chip: Chip to select (0 == slot 3, 1 == slot 4) | 297 | * @chip: Chip to select (0 == slot 3, 1 == slot 4) |
298 | * | 298 | * |
299 | * If there was a sudden loss of power during an erase operation, a | 299 | * If there was a sudden loss of power during an erase operation, a |
300 | * "device recovery" operation must be performed when power is restored | 300 | * "device recovery" operation must be performed when power is restored |
301 | * to ensure correct operation. This routine performs the required steps | 301 | * to ensure correct operation. This routine performs the required steps |
302 | * for the requested chip. | 302 | * for the requested chip. |
@@ -312,7 +312,7 @@ static void deplete(struct mtd_info *mtd, int chip) | |||
312 | while (!this->dev_ready(mtd)); | 312 | while (!this->dev_ready(mtd)); |
313 | 313 | ||
314 | this->select_chip(mtd, chip); | 314 | this->select_chip(mtd, chip); |
315 | 315 | ||
316 | /* Send the commands for device recovery, phase 1 */ | 316 | /* Send the commands for device recovery, phase 1 */ |
317 | this->cmdfunc (mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0000); | 317 | this->cmdfunc (mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0000); |
318 | this->cmdfunc (mtd, NAND_CMD_DEPLETE2, -1, -1); | 318 | this->cmdfunc (mtd, NAND_CMD_DEPLETE2, -1, -1); |
@@ -330,7 +330,7 @@ static void deplete(struct mtd_info *mtd, int chip) | |||
330 | * @mtd: MTD device structure | 330 | * @mtd: MTD device structure |
331 | * @mode: I/O mode; read or write | 331 | * @mode: I/O mode; read or write |
332 | * | 332 | * |
333 | * enable hardware ECC for data read or write | 333 | * enable hardware ECC for data read or write |
334 | * | 334 | * |
335 | */ | 335 | */ |
336 | static void rtc_from4_enable_hwecc(struct mtd_info *mtd, int mode) | 336 | static void rtc_from4_enable_hwecc(struct mtd_info *mtd, int mode) |
@@ -340,7 +340,7 @@ static void rtc_from4_enable_hwecc(struct mtd_info *mtd, int mode) | |||
340 | 340 | ||
341 | switch (mode) { | 341 | switch (mode) { |
342 | case NAND_ECC_READ : | 342 | case NAND_ECC_READ : |
343 | status = RTC_FROM4_RS_ECC_CTL_CLR | 343 | status = RTC_FROM4_RS_ECC_CTL_CLR |
344 | | RTC_FROM4_RS_ECC_CTL_FD_E; | 344 | | RTC_FROM4_RS_ECC_CTL_FD_E; |
345 | 345 | ||
346 | *rs_ecc_ctl = status; | 346 | *rs_ecc_ctl = status; |
@@ -353,8 +353,8 @@ static void rtc_from4_enable_hwecc(struct mtd_info *mtd, int mode) | |||
353 | break; | 353 | break; |
354 | 354 | ||
355 | case NAND_ECC_WRITE : | 355 | case NAND_ECC_WRITE : |
356 | status = RTC_FROM4_RS_ECC_CTL_CLR | 356 | status = RTC_FROM4_RS_ECC_CTL_CLR |
357 | | RTC_FROM4_RS_ECC_CTL_GEN | 357 | | RTC_FROM4_RS_ECC_CTL_GEN |
358 | | RTC_FROM4_RS_ECC_CTL_FD_E; | 358 | | RTC_FROM4_RS_ECC_CTL_FD_E; |
359 | 359 | ||
360 | *rs_ecc_ctl = status; | 360 | *rs_ecc_ctl = status; |
@@ -411,7 +411,7 @@ static void rtc_from4_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_c | |||
411 | static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_char *ecc1, u_char *ecc2) | 411 | static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_char *ecc1, u_char *ecc2) |
412 | { | 412 | { |
413 | int i, j, res; | 413 | int i, j, res; |
414 | unsigned short status; | 414 | unsigned short status; |
415 | uint16_t par[6], syn[6]; | 415 | uint16_t par[6], syn[6]; |
416 | uint8_t ecc[8]; | 416 | uint8_t ecc[8]; |
417 | volatile unsigned short *rs_ecc; | 417 | volatile unsigned short *rs_ecc; |
@@ -430,7 +430,7 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha | |||
430 | } | 430 | } |
431 | 431 | ||
432 | /* convert into 6 10bit syndrome fields */ | 432 | /* convert into 6 10bit syndrome fields */ |
433 | par[5] = rs_decoder->index_of[(((uint16_t)ecc[0] >> 0) & 0x0ff) | | 433 | par[5] = rs_decoder->index_of[(((uint16_t)ecc[0] >> 0) & 0x0ff) | |
434 | (((uint16_t)ecc[1] << 8) & 0x300)]; | 434 | (((uint16_t)ecc[1] << 8) & 0x300)]; |
435 | par[4] = rs_decoder->index_of[(((uint16_t)ecc[1] >> 2) & 0x03f) | | 435 | par[4] = rs_decoder->index_of[(((uint16_t)ecc[1] >> 2) & 0x03f) | |
436 | (((uint16_t)ecc[2] << 6) & 0x3c0)]; | 436 | (((uint16_t)ecc[2] << 6) & 0x3c0)]; |
@@ -456,7 +456,7 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha | |||
456 | /* Let the library code do its magic.*/ | 456 | /* Let the library code do its magic.*/ |
457 | res = decode_rs8(rs_decoder, (uint8_t *)buf, par, 512, syn, 0, NULL, 0xff, NULL); | 457 | res = decode_rs8(rs_decoder, (uint8_t *)buf, par, 512, syn, 0, NULL, 0xff, NULL); |
458 | if (res > 0) { | 458 | if (res > 0) { |
459 | DEBUG (MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: " | 459 | DEBUG (MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: " |
460 | "ECC corrected %d errors on read\n", res); | 460 | "ECC corrected %d errors on read\n", res); |
461 | } | 461 | } |
462 | return res; | 462 | return res; |
@@ -470,9 +470,9 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha | |||
470 | * @state: state or the operation | 470 | * @state: state or the operation |
471 | * @status: status code returned from read status | 471 | * @status: status code returned from read status |
472 | * @page: startpage inside the chip, must be called with (page & this->pagemask) | 472 | * @page: startpage inside the chip, must be called with (page & this->pagemask) |
473 | * | 473 | * |
474 | * Perform additional error status checks on erase and write failures | 474 | * Perform additional error status checks on erase and write failures |
475 | * to determine if errors are correctable. For this device, correctable | 475 | * to determine if errors are correctable. For this device, correctable |
476 | * 1-bit errors on erase and write are considered acceptable. | 476 | * 1-bit errors on erase and write are considered acceptable. |
477 | * | 477 | * |
478 | * note: see pages 34..37 of data sheet for details. | 478 | * note: see pages 34..37 of data sheet for details. |
@@ -633,7 +633,7 @@ int __init rtc_from4_init (void) | |||
633 | 633 | ||
634 | #ifdef RTC_FROM4_HWECC | 634 | #ifdef RTC_FROM4_HWECC |
635 | /* We could create the decoder on demand, if memory is a concern. | 635 | /* We could create the decoder on demand, if memory is a concern. |
636 | * This way we have it handy, if an error happens | 636 | * This way we have it handy, if an error happens |
637 | * | 637 | * |
638 | * Symbolsize is 10 (bits) | 638 | * Symbolsize is 10 (bits) |
639 | * Primitve polynomial is x^10+x^3+1 | 639 | * Primitve polynomial is x^10+x^3+1 |
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 2df5e47d1f5c..97e9b7892d29 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c | |||
@@ -17,8 +17,9 @@ | |||
17 | * 02-May-2005 BJD Reduced hwcontrol decode | 17 | * 02-May-2005 BJD Reduced hwcontrol decode |
18 | * 20-Jun-2005 BJD Updated s3c2440 support, fixed timing bug | 18 | * 20-Jun-2005 BJD Updated s3c2440 support, fixed timing bug |
19 | * 08-Jul-2005 BJD Fix OOPS when no platform data supplied | 19 | * 08-Jul-2005 BJD Fix OOPS when no platform data supplied |
20 | * 20-Oct-2005 BJD Fix timing calculation bug | ||
20 | * | 21 | * |
21 | * $Id: s3c2410.c,v 1.14 2005/07/06 20:05:06 bjd Exp $ | 22 | * $Id: s3c2410.c,v 1.20 2005/11/07 11:14:31 gleixner Exp $ |
22 | * | 23 | * |
23 | * This program is free software; you can redistribute it and/or modify | 24 | * This program is free software; you can redistribute it and/or modify |
24 | * it under the terms of the GNU General Public License as published by | 25 | * it under the terms of the GNU General Public License as published by |
@@ -136,13 +137,13 @@ static struct s3c2410_platform_nand *to_nand_plat(struct device *dev) | |||
136 | 137 | ||
137 | /* timing calculations */ | 138 | /* timing calculations */ |
138 | 139 | ||
139 | #define NS_IN_KHZ 10000000 | 140 | #define NS_IN_KHZ 1000000 |
140 | 141 | ||
141 | static int s3c2410_nand_calc_rate(int wanted, unsigned long clk, int max) | 142 | static int s3c2410_nand_calc_rate(int wanted, unsigned long clk, int max) |
142 | { | 143 | { |
143 | int result; | 144 | int result; |
144 | 145 | ||
145 | result = (wanted * NS_IN_KHZ) / clk; | 146 | result = (wanted * clk) / NS_IN_KHZ; |
146 | result++; | 147 | result++; |
147 | 148 | ||
148 | pr_debug("result %d from %ld, %d\n", result, clk, wanted); | 149 | pr_debug("result %d from %ld, %d\n", result, clk, wanted); |
@@ -159,20 +160,22 @@ static int s3c2410_nand_calc_rate(int wanted, unsigned long clk, int max) | |||
159 | return result; | 160 | return result; |
160 | } | 161 | } |
161 | 162 | ||
162 | #define to_ns(ticks,clk) (((clk) * (ticks)) / NS_IN_KHZ) | 163 | #define to_ns(ticks,clk) (((ticks) * NS_IN_KHZ) / (unsigned int)(clk)) |
163 | 164 | ||
164 | /* controller setup */ | 165 | /* controller setup */ |
165 | 166 | ||
166 | static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, | 167 | static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, |
167 | struct device *dev) | 168 | struct device *dev) |
168 | { | 169 | { |
169 | struct s3c2410_platform_nand *plat = to_nand_plat(dev); | 170 | struct s3c2410_platform_nand *plat = to_nand_plat(dev); |
170 | unsigned int tacls, twrph0, twrph1; | ||
171 | unsigned long clkrate = clk_get_rate(info->clk); | 171 | unsigned long clkrate = clk_get_rate(info->clk); |
172 | int tacls, twrph0, twrph1; | ||
172 | unsigned long cfg; | 173 | unsigned long cfg; |
173 | 174 | ||
174 | /* calculate the timing information for the controller */ | 175 | /* calculate the timing information for the controller */ |
175 | 176 | ||
177 | clkrate /= 1000; /* turn clock into kHz for ease of use */ | ||
178 | |||
176 | if (plat != NULL) { | 179 | if (plat != NULL) { |
177 | tacls = s3c2410_nand_calc_rate(plat->tacls, clkrate, 4); | 180 | tacls = s3c2410_nand_calc_rate(plat->tacls, clkrate, 4); |
178 | twrph0 = s3c2410_nand_calc_rate(plat->twrph0, clkrate, 8); | 181 | twrph0 = s3c2410_nand_calc_rate(plat->twrph0, clkrate, 8); |
@@ -183,16 +186,16 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, | |||
183 | twrph0 = 8; | 186 | twrph0 = 8; |
184 | twrph1 = 8; | 187 | twrph1 = 8; |
185 | } | 188 | } |
186 | 189 | ||
187 | if (tacls < 0 || twrph0 < 0 || twrph1 < 0) { | 190 | if (tacls < 0 || twrph0 < 0 || twrph1 < 0) { |
188 | printk(KERN_ERR PFX "cannot get timings suitable for board\n"); | 191 | printk(KERN_ERR PFX "cannot get timings suitable for board\n"); |
189 | return -EINVAL; | 192 | return -EINVAL; |
190 | } | 193 | } |
191 | 194 | ||
192 | printk(KERN_INFO PFX "timing: Tacls %ldns, Twrph0 %ldns, Twrph1 %ldns\n", | 195 | printk(KERN_INFO PFX "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n", |
193 | to_ns(tacls, clkrate), | 196 | tacls, to_ns(tacls, clkrate), |
194 | to_ns(twrph0, clkrate), | 197 | twrph0, to_ns(twrph0, clkrate), |
195 | to_ns(twrph1, clkrate)); | 198 | twrph1, to_ns(twrph1, clkrate)); |
196 | 199 | ||
197 | if (!info->is_s3c2440) { | 200 | if (!info->is_s3c2440) { |
198 | cfg = S3C2410_NFCONF_EN; | 201 | cfg = S3C2410_NFCONF_EN; |
@@ -216,7 +219,7 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, | |||
216 | static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip) | 219 | static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip) |
217 | { | 220 | { |
218 | struct s3c2410_nand_info *info; | 221 | struct s3c2410_nand_info *info; |
219 | struct s3c2410_nand_mtd *nmtd; | 222 | struct s3c2410_nand_mtd *nmtd; |
220 | struct nand_chip *this = mtd->priv; | 223 | struct nand_chip *this = mtd->priv; |
221 | void __iomem *reg; | 224 | void __iomem *reg; |
222 | unsigned long cur; | 225 | unsigned long cur; |
@@ -249,7 +252,7 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip) | |||
249 | writel(cur, reg); | 252 | writel(cur, reg); |
250 | } | 253 | } |
251 | 254 | ||
252 | /* command and control functions | 255 | /* command and control functions |
253 | * | 256 | * |
254 | * Note, these all use tglx's method of changing the IO_ADDR_W field | 257 | * Note, these all use tglx's method of changing the IO_ADDR_W field |
255 | * to make the code simpler, and use the nand layer's code to issue the | 258 | * to make the code simpler, and use the nand layer's code to issue the |
@@ -321,7 +324,7 @@ static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd) | |||
321 | static int s3c2410_nand_devready(struct mtd_info *mtd) | 324 | static int s3c2410_nand_devready(struct mtd_info *mtd) |
322 | { | 325 | { |
323 | struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); | 326 | struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); |
324 | 327 | ||
325 | if (info->is_s3c2440) | 328 | if (info->is_s3c2440) |
326 | return readb(info->regs + S3C2440_NFSTAT) & S3C2440_NFSTAT_READY; | 329 | return readb(info->regs + S3C2440_NFSTAT) & S3C2440_NFSTAT_READY; |
327 | return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY; | 330 | return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY; |
@@ -342,7 +345,7 @@ static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, | |||
342 | 345 | ||
343 | if (read_ecc[0] == calc_ecc[0] && | 346 | if (read_ecc[0] == calc_ecc[0] && |
344 | read_ecc[1] == calc_ecc[1] && | 347 | read_ecc[1] == calc_ecc[1] && |
345 | read_ecc[2] == calc_ecc[2]) | 348 | read_ecc[2] == calc_ecc[2]) |
346 | return 0; | 349 | return 0; |
347 | 350 | ||
348 | /* we curently have no method for correcting the error */ | 351 | /* we curently have no method for correcting the error */ |
@@ -433,14 +436,14 @@ static int s3c2410_nand_remove(struct device *dev) | |||
433 | 436 | ||
434 | dev_set_drvdata(dev, NULL); | 437 | dev_set_drvdata(dev, NULL); |
435 | 438 | ||
436 | if (info == NULL) | 439 | if (info == NULL) |
437 | return 0; | 440 | return 0; |
438 | 441 | ||
439 | /* first thing we need to do is release all our mtds | 442 | /* first thing we need to do is release all our mtds |
440 | * and their partitions, then go through freeing the | 443 | * and their partitions, then go through freeing the |
441 | * resources used | 444 | * resources used |
442 | */ | 445 | */ |
443 | 446 | ||
444 | if (info->mtds != NULL) { | 447 | if (info->mtds != NULL) { |
445 | struct s3c2410_nand_mtd *ptr = info->mtds; | 448 | struct s3c2410_nand_mtd *ptr = info->mtds; |
446 | int mtdno; | 449 | int mtdno; |
@@ -504,7 +507,7 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, | |||
504 | 507 | ||
505 | /* s3c2410_nand_init_chip | 508 | /* s3c2410_nand_init_chip |
506 | * | 509 | * |
507 | * init a single instance of an chip | 510 | * init a single instance of an chip |
508 | */ | 511 | */ |
509 | 512 | ||
510 | static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, | 513 | static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, |
@@ -576,7 +579,7 @@ static int s3c24xx_nand_probe(struct device *dev, int is_s3c2440) | |||
576 | 579 | ||
577 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 580 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
578 | if (info == NULL) { | 581 | if (info == NULL) { |
579 | printk(KERN_ERR PFX "no memory for flash info\n"); | 582 | dev_err(dev, "no memory for flash info\n"); |
580 | err = -ENOMEM; | 583 | err = -ENOMEM; |
581 | goto exit_error; | 584 | goto exit_error; |
582 | } | 585 | } |
@@ -591,7 +594,7 @@ static int s3c24xx_nand_probe(struct device *dev, int is_s3c2440) | |||
591 | 594 | ||
592 | info->clk = clk_get(dev, "nand"); | 595 | info->clk = clk_get(dev, "nand"); |
593 | if (IS_ERR(info->clk)) { | 596 | if (IS_ERR(info->clk)) { |
594 | printk(KERN_ERR PFX "failed to get clock"); | 597 | dev_err(dev, "failed to get clock"); |
595 | err = -ENOENT; | 598 | err = -ENOENT; |
596 | goto exit_error; | 599 | goto exit_error; |
597 | } | 600 | } |
@@ -608,7 +611,7 @@ static int s3c24xx_nand_probe(struct device *dev, int is_s3c2440) | |||
608 | info->area = request_mem_region(res->start, size, pdev->name); | 611 | info->area = request_mem_region(res->start, size, pdev->name); |
609 | 612 | ||
610 | if (info->area == NULL) { | 613 | if (info->area == NULL) { |
611 | printk(KERN_ERR PFX "cannot reserve register region\n"); | 614 | dev_err(dev, "cannot reserve register region\n"); |
612 | err = -ENOENT; | 615 | err = -ENOENT; |
613 | goto exit_error; | 616 | goto exit_error; |
614 | } | 617 | } |
@@ -619,12 +622,12 @@ static int s3c24xx_nand_probe(struct device *dev, int is_s3c2440) | |||
619 | info->is_s3c2440 = is_s3c2440; | 622 | info->is_s3c2440 = is_s3c2440; |
620 | 623 | ||
621 | if (info->regs == NULL) { | 624 | if (info->regs == NULL) { |
622 | printk(KERN_ERR PFX "cannot reserve register region\n"); | 625 | dev_err(dev, "cannot reserve register region\n"); |
623 | err = -EIO; | 626 | err = -EIO; |
624 | goto exit_error; | 627 | goto exit_error; |
625 | } | 628 | } |
626 | 629 | ||
627 | printk(KERN_INFO PFX "mapped registers at %p\n", info->regs); | 630 | dev_dbg(dev, "mapped registers at %p\n", info->regs); |
628 | 631 | ||
629 | /* initialise the hardware */ | 632 | /* initialise the hardware */ |
630 | 633 | ||
@@ -642,7 +645,7 @@ static int s3c24xx_nand_probe(struct device *dev, int is_s3c2440) | |||
642 | size = nr_sets * sizeof(*info->mtds); | 645 | size = nr_sets * sizeof(*info->mtds); |
643 | info->mtds = kmalloc(size, GFP_KERNEL); | 646 | info->mtds = kmalloc(size, GFP_KERNEL); |
644 | if (info->mtds == NULL) { | 647 | if (info->mtds == NULL) { |
645 | printk(KERN_ERR PFX "failed to allocate mtd storage\n"); | 648 | dev_err(dev, "failed to allocate mtd storage\n"); |
646 | err = -ENOMEM; | 649 | err = -ENOMEM; |
647 | goto exit_error; | 650 | goto exit_error; |
648 | } | 651 | } |
@@ -656,7 +659,7 @@ static int s3c24xx_nand_probe(struct device *dev, int is_s3c2440) | |||
656 | for (setno = 0; setno < nr_sets; setno++, nmtd++) { | 659 | for (setno = 0; setno < nr_sets; setno++, nmtd++) { |
657 | pr_debug("initialising set %d (%p, info %p)\n", | 660 | pr_debug("initialising set %d (%p, info %p)\n", |
658 | setno, nmtd, info); | 661 | setno, nmtd, info); |
659 | 662 | ||
660 | s3c2410_nand_init_chip(info, nmtd, sets); | 663 | s3c2410_nand_init_chip(info, nmtd, sets); |
661 | 664 | ||
662 | nmtd->scan_res = nand_scan(&nmtd->mtd, | 665 | nmtd->scan_res = nand_scan(&nmtd->mtd, |
@@ -669,7 +672,7 @@ static int s3c24xx_nand_probe(struct device *dev, int is_s3c2440) | |||
669 | if (sets != NULL) | 672 | if (sets != NULL) |
670 | sets++; | 673 | sets++; |
671 | } | 674 | } |
672 | 675 | ||
673 | pr_debug("initialised ok\n"); | 676 | pr_debug("initialised ok\n"); |
674 | return 0; | 677 | return 0; |
675 | 678 | ||
@@ -695,6 +698,7 @@ static int s3c2440_nand_probe(struct device *dev) | |||
695 | 698 | ||
696 | static struct device_driver s3c2410_nand_driver = { | 699 | static struct device_driver s3c2410_nand_driver = { |
697 | .name = "s3c2410-nand", | 700 | .name = "s3c2410-nand", |
701 | .owner = THIS_MODULE, | ||
698 | .bus = &platform_bus_type, | 702 | .bus = &platform_bus_type, |
699 | .probe = s3c2410_nand_probe, | 703 | .probe = s3c2410_nand_probe, |
700 | .remove = s3c2410_nand_remove, | 704 | .remove = s3c2410_nand_remove, |
@@ -702,6 +706,7 @@ static struct device_driver s3c2410_nand_driver = { | |||
702 | 706 | ||
703 | static struct device_driver s3c2440_nand_driver = { | 707 | static struct device_driver s3c2440_nand_driver = { |
704 | .name = "s3c2440-nand", | 708 | .name = "s3c2440-nand", |
709 | .owner = THIS_MODULE, | ||
705 | .bus = &platform_bus_type, | 710 | .bus = &platform_bus_type, |
706 | .probe = s3c2440_nand_probe, | 711 | .probe = s3c2440_nand_probe, |
707 | .remove = s3c2410_nand_remove, | 712 | .remove = s3c2410_nand_remove, |
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 88b5b5b40b43..1924a4f137c7 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2004 Richard Purdie | 4 | * Copyright (C) 2004 Richard Purdie |
5 | * | 5 | * |
6 | * $Id: sharpsl.c,v 1.4 2005/01/23 11:09:19 rpurdie Exp $ | 6 | * $Id: sharpsl.c,v 1.7 2005/11/07 11:14:31 gleixner Exp $ |
7 | * | 7 | * |
8 | * Based on Sharp's NAND driver sharp_sl.c | 8 | * Based on Sharp's NAND driver sharp_sl.c |
9 | * | 9 | * |
@@ -76,14 +76,14 @@ static struct mtd_partition sharpsl_nand_default_partition_info[] = { | |||
76 | }, | 76 | }, |
77 | }; | 77 | }; |
78 | 78 | ||
79 | /* | 79 | /* |
80 | * hardware specific access to control-lines | 80 | * hardware specific access to control-lines |
81 | */ | 81 | */ |
82 | static void | 82 | static void |
83 | sharpsl_nand_hwcontrol(struct mtd_info* mtd, int cmd) | 83 | sharpsl_nand_hwcontrol(struct mtd_info* mtd, int cmd) |
84 | { | 84 | { |
85 | switch (cmd) { | 85 | switch (cmd) { |
86 | case NAND_CTL_SETCLE: | 86 | case NAND_CTL_SETCLE: |
87 | writeb(readb(FLASHCTL) | FLCLE, FLASHCTL); | 87 | writeb(readb(FLASHCTL) | FLCLE, FLASHCTL); |
88 | break; | 88 | break; |
89 | case NAND_CTL_CLRCLE: | 89 | case NAND_CTL_CLRCLE: |
@@ -97,10 +97,10 @@ sharpsl_nand_hwcontrol(struct mtd_info* mtd, int cmd) | |||
97 | writeb(readb(FLASHCTL) & ~FLALE, FLASHCTL); | 97 | writeb(readb(FLASHCTL) & ~FLALE, FLASHCTL); |
98 | break; | 98 | break; |
99 | 99 | ||
100 | case NAND_CTL_SETNCE: | 100 | case NAND_CTL_SETNCE: |
101 | writeb(readb(FLASHCTL) & ~(FLCE0|FLCE1), FLASHCTL); | 101 | writeb(readb(FLASHCTL) & ~(FLCE0|FLCE1), FLASHCTL); |
102 | break; | 102 | break; |
103 | case NAND_CTL_CLRNCE: | 103 | case NAND_CTL_CLRNCE: |
104 | writeb(readb(FLASHCTL) | (FLCE0|FLCE1), FLASHCTL); | 104 | writeb(readb(FLASHCTL) | (FLCE0|FLCE1), FLASHCTL); |
105 | break; | 105 | break; |
106 | } | 106 | } |
@@ -115,6 +115,23 @@ static struct nand_bbt_descr sharpsl_bbt = { | |||
115 | .pattern = scan_ff_pattern | 115 | .pattern = scan_ff_pattern |
116 | }; | 116 | }; |
117 | 117 | ||
118 | static struct nand_bbt_descr sharpsl_akita_bbt = { | ||
119 | .options = 0, | ||
120 | .offs = 4, | ||
121 | .len = 1, | ||
122 | .pattern = scan_ff_pattern | ||
123 | }; | ||
124 | |||
125 | static struct nand_oobinfo akita_oobinfo = { | ||
126 | .useecc = MTD_NANDECC_AUTOPLACE, | ||
127 | .eccbytes = 24, | ||
128 | .eccpos = { | ||
129 | 0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11, | ||
130 | 0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23, | ||
131 | 0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37}, | ||
132 | .oobfree = { {0x08, 0x09} } | ||
133 | }; | ||
134 | |||
118 | static int | 135 | static int |
119 | sharpsl_nand_dev_ready(struct mtd_info* mtd) | 136 | sharpsl_nand_dev_ready(struct mtd_info* mtd) |
120 | { | 137 | { |
@@ -160,7 +177,7 @@ sharpsl_nand_init(void) | |||
160 | printk ("Unable to allocate SharpSL NAND MTD device structure.\n"); | 177 | printk ("Unable to allocate SharpSL NAND MTD device structure.\n"); |
161 | return -ENOMEM; | 178 | return -ENOMEM; |
162 | } | 179 | } |
163 | 180 | ||
164 | /* map physical adress */ | 181 | /* map physical adress */ |
165 | sharpsl_io_base = ioremap(sharpsl_phys_base, 0x1000); | 182 | sharpsl_io_base = ioremap(sharpsl_phys_base, 0x1000); |
166 | if(!sharpsl_io_base){ | 183 | if(!sharpsl_io_base){ |
@@ -168,7 +185,7 @@ sharpsl_nand_init(void) | |||
168 | kfree(sharpsl_mtd); | 185 | kfree(sharpsl_mtd); |
169 | return -EIO; | 186 | return -EIO; |
170 | } | 187 | } |
171 | 188 | ||
172 | /* Get pointer to private data */ | 189 | /* Get pointer to private data */ |
173 | this = (struct nand_chip *) (&sharpsl_mtd[1]); | 190 | this = (struct nand_chip *) (&sharpsl_mtd[1]); |
174 | 191 | ||
@@ -194,10 +211,14 @@ sharpsl_nand_init(void) | |||
194 | this->chip_delay = 15; | 211 | this->chip_delay = 15; |
195 | /* set eccmode using hardware ECC */ | 212 | /* set eccmode using hardware ECC */ |
196 | this->eccmode = NAND_ECC_HW3_256; | 213 | this->eccmode = NAND_ECC_HW3_256; |
214 | this->badblock_pattern = &sharpsl_bbt; | ||
215 | if (machine_is_akita() || machine_is_borzoi()) { | ||
216 | this->badblock_pattern = &sharpsl_akita_bbt; | ||
217 | this->autooob = &akita_oobinfo; | ||
218 | } | ||
197 | this->enable_hwecc = sharpsl_nand_enable_hwecc; | 219 | this->enable_hwecc = sharpsl_nand_enable_hwecc; |
198 | this->calculate_ecc = sharpsl_nand_calculate_ecc; | 220 | this->calculate_ecc = sharpsl_nand_calculate_ecc; |
199 | this->correct_data = nand_correct_data; | 221 | this->correct_data = nand_correct_data; |
200 | this->badblock_pattern = &sharpsl_bbt; | ||
201 | 222 | ||
202 | /* Scan to find existence of the device */ | 223 | /* Scan to find existence of the device */ |
203 | err=nand_scan(sharpsl_mtd,1); | 224 | err=nand_scan(sharpsl_mtd,1); |
@@ -211,7 +232,7 @@ sharpsl_nand_init(void) | |||
211 | sharpsl_mtd->name = "sharpsl-nand"; | 232 | sharpsl_mtd->name = "sharpsl-nand"; |
212 | nr_partitions = parse_mtd_partitions(sharpsl_mtd, part_probes, | 233 | nr_partitions = parse_mtd_partitions(sharpsl_mtd, part_probes, |
213 | &sharpsl_partition_info, 0); | 234 | &sharpsl_partition_info, 0); |
214 | 235 | ||
215 | if (nr_partitions <= 0) { | 236 | if (nr_partitions <= 0) { |
216 | nr_partitions = DEFAULT_NUM_PARTITIONS; | 237 | nr_partitions = DEFAULT_NUM_PARTITIONS; |
217 | sharpsl_partition_info = sharpsl_nand_default_partition_info; | 238 | sharpsl_partition_info = sharpsl_nand_default_partition_info; |
@@ -230,7 +251,7 @@ sharpsl_nand_init(void) | |||
230 | } | 251 | } |
231 | } | 252 | } |
232 | 253 | ||
233 | if (machine_is_husky() || machine_is_borzoi()) { | 254 | if (machine_is_husky() || machine_is_borzoi() || machine_is_akita()) { |
234 | /* Need to use small eraseblock size for backward compatibility */ | 255 | /* Need to use small eraseblock size for backward compatibility */ |
235 | sharpsl_mtd->flags |= MTD_NO_VIRTBLOCKS; | 256 | sharpsl_mtd->flags |= MTD_NO_VIRTBLOCKS; |
236 | } | 257 | } |
diff --git a/drivers/mtd/nand/spia.c b/drivers/mtd/nand/spia.c index b777c412b758..32541cbb0103 100644 --- a/drivers/mtd/nand/spia.c +++ b/drivers/mtd/nand/spia.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * to controllines (due to change in nand.c) | 8 | * to controllines (due to change in nand.c) |
9 | * page_cache added | 9 | * page_cache added |
10 | * | 10 | * |
11 | * $Id: spia.c,v 1.24 2004/11/04 12:53:10 gleixner Exp $ | 11 | * $Id: spia.c,v 1.25 2005/11/07 11:14:31 gleixner Exp $ |
12 | * | 12 | * |
13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
14 | * it under the terms of the GNU General Public License version 2 as | 14 | * it under the terms of the GNU General Public License version 2 as |
@@ -82,7 +82,7 @@ const static struct mtd_partition partition_info[] = { | |||
82 | #define NUM_PARTITIONS 2 | 82 | #define NUM_PARTITIONS 2 |
83 | 83 | ||
84 | 84 | ||
85 | /* | 85 | /* |
86 | * hardware specific access to control-lines | 86 | * hardware specific access to control-lines |
87 | */ | 87 | */ |
88 | static void spia_hwcontrol(struct mtd_info *mtd, int cmd){ | 88 | static void spia_hwcontrol(struct mtd_info *mtd, int cmd){ |
@@ -137,7 +137,7 @@ int __init spia_init (void) | |||
137 | /* Set address of hardware control function */ | 137 | /* Set address of hardware control function */ |
138 | this->hwcontrol = spia_hwcontrol; | 138 | this->hwcontrol = spia_hwcontrol; |
139 | /* 15 us command delay time */ | 139 | /* 15 us command delay time */ |
140 | this->chip_delay = 15; | 140 | this->chip_delay = 15; |
141 | 141 | ||
142 | /* Scan to find existence of the device */ | 142 | /* Scan to find existence of the device */ |
143 | if (nand_scan (spia_mtd, 1)) { | 143 | if (nand_scan (spia_mtd, 1)) { |
diff --git a/drivers/mtd/nand/toto.c b/drivers/mtd/nand/toto.c index 52c808fb5fa9..7609c43cb3ec 100644 --- a/drivers/mtd/nand/toto.c +++ b/drivers/mtd/nand/toto.c | |||
@@ -15,7 +15,7 @@ | |||
15 | * This is a device driver for the NAND flash device found on the | 15 | * This is a device driver for the NAND flash device found on the |
16 | * TI fido board. It supports 32MiB and 64MiB cards | 16 | * TI fido board. It supports 32MiB and 64MiB cards |
17 | * | 17 | * |
18 | * $Id: toto.c,v 1.4 2004/10/05 13:50:20 gleixner Exp $ | 18 | * $Id: toto.c,v 1.5 2005/11/07 11:14:31 gleixner Exp $ |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
@@ -57,7 +57,7 @@ static unsigned long toto_io_base = OMAP_FLASH_1_BASE; | |||
57 | #endif | 57 | #endif |
58 | #define T_NAND_CTL_SETNCE(iob) gpiosetout(NAND_NCE, 0) | 58 | #define T_NAND_CTL_SETNCE(iob) gpiosetout(NAND_NCE, 0) |
59 | #define T_NAND_CTL_CLRNCE(iob) gpiosetout(NAND_NCE, NAND_NCE) | 59 | #define T_NAND_CTL_CLRNCE(iob) gpiosetout(NAND_NCE, NAND_NCE) |
60 | 60 | ||
61 | /* | 61 | /* |
62 | * Define partitions for flash devices | 62 | * Define partitions for flash devices |
63 | */ | 63 | */ |
@@ -91,7 +91,7 @@ static struct mtd_partition partition_info32M[] = { | |||
91 | 91 | ||
92 | #define NUM_PARTITIONS32M 3 | 92 | #define NUM_PARTITIONS32M 3 |
93 | #define NUM_PARTITIONS64M 4 | 93 | #define NUM_PARTITIONS64M 4 |
94 | /* | 94 | /* |
95 | * hardware specific access to control-lines | 95 | * hardware specific access to control-lines |
96 | */ | 96 | */ |
97 | 97 | ||
@@ -146,7 +146,7 @@ int __init toto_init (void) | |||
146 | this->hwcontrol = toto_hwcontrol; | 146 | this->hwcontrol = toto_hwcontrol; |
147 | this->dev_ready = NULL; | 147 | this->dev_ready = NULL; |
148 | /* 25 us command delay time */ | 148 | /* 25 us command delay time */ |
149 | this->chip_delay = 30; | 149 | this->chip_delay = 30; |
150 | this->eccmode = NAND_ECC_SOFT; | 150 | this->eccmode = NAND_ECC_SOFT; |
151 | 151 | ||
152 | /* Scan to find existance of the device */ | 152 | /* Scan to find existance of the device */ |
@@ -157,10 +157,10 @@ int __init toto_init (void) | |||
157 | 157 | ||
158 | /* Register the partitions */ | 158 | /* Register the partitions */ |
159 | switch(toto_mtd->size){ | 159 | switch(toto_mtd->size){ |
160 | case SZ_64M: add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M); break; | 160 | case SZ_64M: add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M); break; |
161 | case SZ_32M: add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M); break; | 161 | case SZ_32M: add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M); break; |
162 | default: { | 162 | default: { |
163 | printk (KERN_WARNING "Unsupported Nand device\n"); | 163 | printk (KERN_WARNING "Unsupported Nand device\n"); |
164 | err = -ENXIO; | 164 | err = -ENXIO; |
165 | goto out_buf; | 165 | goto out_buf; |
166 | } | 166 | } |
@@ -170,9 +170,9 @@ int __init toto_init (void) | |||
170 | archflashwp(0,0); /* open up flash for writing */ | 170 | archflashwp(0,0); /* open up flash for writing */ |
171 | 171 | ||
172 | goto out; | 172 | goto out; |
173 | 173 | ||
174 | out_buf: | 174 | out_buf: |
175 | kfree (this->data_buf); | 175 | kfree (this->data_buf); |
176 | out_mtd: | 176 | out_mtd: |
177 | kfree (toto_mtd); | 177 | kfree (toto_mtd); |
178 | out: | 178 | out: |
@@ -194,7 +194,7 @@ static void __exit toto_cleanup (void) | |||
194 | 194 | ||
195 | /* stop flash writes */ | 195 | /* stop flash writes */ |
196 | archflashwp(0,1); | 196 | archflashwp(0,1); |
197 | 197 | ||
198 | /* release gpios to system */ | 198 | /* release gpios to system */ |
199 | gpiorelease(NAND_MASK); | 199 | gpiorelease(NAND_MASK); |
200 | } | 200 | } |