diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-22 19:56:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-22 19:56:22 -0400 |
commit | ac1b7c378ef26fba6694d5f118fe7fc16fee2fe2 (patch) | |
tree | 3f72979545bb070eb2c3e903cbf31dc4aef3ffc9 /drivers/mtd/nand | |
parent | 9e268beb92ee3a853b3946e84b10358207e2085f (diff) | |
parent | c90173f0907486fe4010c2a8cef534e2473db43f (diff) |
Merge git://git.infradead.org/mtd-2.6
* git://git.infradead.org/mtd-2.6: (63 commits)
mtd: OneNAND: Allow setting of boundary information when built as module
jffs2: leaking jffs2_summary in function jffs2_scan_medium
mtd: nand: Fix memory leak on txx9ndfmc probe failure.
mtd: orion_nand: use burst reads with double word accesses
mtd/nand: s3c6400 support for s3c2410 driver
[MTD] [NAND] S3C2410: Use DIV_ROUND_UP
[MTD] [NAND] S3C2410: Deal with unaligned lengths in S3C2440 buffer read/write
[MTD] [NAND] S3C2410: Allow the machine code to get the BBT table from NAND
[MTD] [NAND] S3C2410: Added a kerneldoc for s3c2410_nand_set
mtd: physmap_of: Add multiple regions and concatenation support
mtd: nand: max_retries off by one in mxc_nand
mtd: nand: s3c2410_nand_setrate(): use correct macros for 2412/2440
mtd: onenand: add bbt_wait & unlock_all as replaceable for some platform
mtd: Flex-OneNAND support
mtd: nand: add OMAP2/OMAP3 NAND driver
mtd: maps: Blackfin async: fix memory leaks in probe/remove funcs
mtd: uclinux: mark local stuff static
mtd: uclinux: do not allow to be built as a module
mtd: uclinux: allow systems to override map addr/size
mtd: blackfin NFC: fix hang when using NAND on BF527-EZKITs
...
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r-- | drivers/mtd/nand/Kconfig | 24 | ||||
-rw-r--r-- | drivers/mtd/nand/Makefile | 1 | ||||
-rw-r--r-- | drivers/mtd/nand/atmel_nand.c | 11 | ||||
-rw-r--r-- | drivers/mtd/nand/bf5xx_nand.c | 17 | ||||
-rw-r--r-- | drivers/mtd/nand/davinci_nand.c | 342 | ||||
-rw-r--r-- | drivers/mtd/nand/mxc_nand.c | 66 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 3 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_ecc.c | 4 | ||||
-rw-r--r-- | drivers/mtd/nand/omap2.c | 776 | ||||
-rw-r--r-- | drivers/mtd/nand/orion_nand.c | 23 | ||||
-rw-r--r-- | drivers/mtd/nand/plat_nand.c | 19 | ||||
-rw-r--r-- | drivers/mtd/nand/s3c2410.c | 268 | ||||
-rw-r--r-- | drivers/mtd/nand/txx9ndfmc.c | 16 |
13 files changed, 1406 insertions, 164 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index f3276897859e..ce96c091f01b 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -74,6 +74,12 @@ config MTD_NAND_AMS_DELTA | |||
74 | help | 74 | help |
75 | Support for NAND flash on Amstrad E3 (Delta). | 75 | Support for NAND flash on Amstrad E3 (Delta). |
76 | 76 | ||
77 | config MTD_NAND_OMAP2 | ||
78 | tristate "NAND Flash device on OMAP2 and OMAP3" | ||
79 | depends on ARM && MTD_NAND && (ARCH_OMAP2 || ARCH_OMAP3) | ||
80 | help | ||
81 | Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms. | ||
82 | |||
77 | config MTD_NAND_TS7250 | 83 | config MTD_NAND_TS7250 |
78 | tristate "NAND Flash device on TS-7250 board" | 84 | tristate "NAND Flash device on TS-7250 board" |
79 | depends on MACH_TS72XX | 85 | depends on MACH_TS72XX |
@@ -139,27 +145,27 @@ config MTD_NAND_PPCHAMELEONEVB | |||
139 | This enables the NAND flash driver on the PPChameleon EVB Board. | 145 | This enables the NAND flash driver on the PPChameleon EVB Board. |
140 | 146 | ||
141 | config MTD_NAND_S3C2410 | 147 | config MTD_NAND_S3C2410 |
142 | tristate "NAND Flash support for S3C2410/S3C2440 SoC" | 148 | tristate "NAND Flash support for Samsung S3C SoCs" |
143 | depends on ARCH_S3C2410 | 149 | depends on ARCH_S3C2410 || ARCH_S3C64XX |
144 | help | 150 | help |
145 | This enables the NAND flash controller on the S3C2410 and S3C2440 | 151 | This enables the NAND flash controller on the S3C24xx and S3C64xx |
146 | SoCs | 152 | SoCs |
147 | 153 | ||
148 | No board specific support is done by this driver, each board | 154 | No board specific support is done by this driver, each board |
149 | must advertise a platform_device for the driver to attach. | 155 | must advertise a platform_device for the driver to attach. |
150 | 156 | ||
151 | config MTD_NAND_S3C2410_DEBUG | 157 | config MTD_NAND_S3C2410_DEBUG |
152 | bool "S3C2410 NAND driver debug" | 158 | bool "Samsung S3C NAND driver debug" |
153 | depends on MTD_NAND_S3C2410 | 159 | depends on MTD_NAND_S3C2410 |
154 | help | 160 | help |
155 | Enable debugging of the S3C2410 NAND driver | 161 | Enable debugging of the S3C NAND driver |
156 | 162 | ||
157 | config MTD_NAND_S3C2410_HWECC | 163 | config MTD_NAND_S3C2410_HWECC |
158 | bool "S3C2410 NAND Hardware ECC" | 164 | bool "Samsung S3C NAND Hardware ECC" |
159 | depends on MTD_NAND_S3C2410 | 165 | depends on MTD_NAND_S3C2410 |
160 | help | 166 | help |
161 | Enable the use of the S3C2410's internal ECC generator when | 167 | Enable the use of the controller's internal ECC generator when |
162 | using NAND. Early versions of the chip have had problems with | 168 | using NAND. Early versions of the chips have had problems with |
163 | incorrect ECC generation, and if using these, the default of | 169 | incorrect ECC generation, and if using these, the default of |
164 | software ECC is preferable. | 170 | software ECC is preferable. |
165 | 171 | ||
@@ -171,7 +177,7 @@ config MTD_NAND_NDFC | |||
171 | NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs | 177 | NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs |
172 | 178 | ||
173 | config MTD_NAND_S3C2410_CLKSTOP | 179 | config MTD_NAND_S3C2410_CLKSTOP |
174 | bool "S3C2410 NAND IDLE clock stop" | 180 | bool "Samsung S3C NAND IDLE clock stop" |
175 | depends on MTD_NAND_S3C2410 | 181 | depends on MTD_NAND_S3C2410 |
176 | default n | 182 | default n |
177 | help | 183 | help |
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index d33860ac42c3..f3a786b3cff3 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile | |||
@@ -25,6 +25,7 @@ obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o | |||
25 | obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o | 25 | obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o |
26 | obj-$(CONFIG_MTD_NAND_ATMEL) += atmel_nand.o | 26 | obj-$(CONFIG_MTD_NAND_ATMEL) += atmel_nand.o |
27 | obj-$(CONFIG_MTD_NAND_GPIO) += gpio.o | 27 | obj-$(CONFIG_MTD_NAND_GPIO) += gpio.o |
28 | obj-$(CONFIG_MTD_NAND_OMAP2) += omap2.o | ||
28 | obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o | 29 | obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o |
29 | obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o | 30 | obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o |
30 | obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o | 31 | obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o |
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 47a33cec3793..2802992b39da 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
@@ -24,6 +24,7 @@ | |||
24 | 24 | ||
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/moduleparam.h> | ||
27 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
28 | #include <linux/mtd/mtd.h> | 29 | #include <linux/mtd/mtd.h> |
29 | #include <linux/mtd/nand.h> | 30 | #include <linux/mtd/nand.h> |
@@ -47,6 +48,9 @@ | |||
47 | #define no_ecc 0 | 48 | #define no_ecc 0 |
48 | #endif | 49 | #endif |
49 | 50 | ||
51 | static int on_flash_bbt = 0; | ||
52 | module_param(on_flash_bbt, int, 0); | ||
53 | |||
50 | /* Register access macros */ | 54 | /* Register access macros */ |
51 | #define ecc_readl(add, reg) \ | 55 | #define ecc_readl(add, reg) \ |
52 | __raw_readl(add + ATMEL_ECC_##reg) | 56 | __raw_readl(add + ATMEL_ECC_##reg) |
@@ -459,12 +463,17 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
459 | 463 | ||
460 | if (host->board->det_pin) { | 464 | if (host->board->det_pin) { |
461 | if (gpio_get_value(host->board->det_pin)) { | 465 | if (gpio_get_value(host->board->det_pin)) { |
462 | printk("No SmartMedia card inserted.\n"); | 466 | printk(KERN_INFO "No SmartMedia card inserted.\n"); |
463 | res = ENXIO; | 467 | res = ENXIO; |
464 | goto err_no_card; | 468 | goto err_no_card; |
465 | } | 469 | } |
466 | } | 470 | } |
467 | 471 | ||
472 | if (on_flash_bbt) { | ||
473 | printk(KERN_INFO "atmel_nand: Use On Flash BBT\n"); | ||
474 | nand_chip->options |= NAND_USE_FLASH_BBT; | ||
475 | } | ||
476 | |||
468 | /* first scan to find the device and get the page size */ | 477 | /* first scan to find the device and get the page size */ |
469 | if (nand_scan_ident(mtd, 1)) { | 478 | if (nand_scan_ident(mtd, 1)) { |
470 | res = -ENXIO; | 479 | res = -ENXIO; |
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index 4c2a67ca801e..8506e7e606fd 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c | |||
@@ -458,7 +458,7 @@ static irqreturn_t bf5xx_nand_dma_irq(int irq, void *dev_id) | |||
458 | return IRQ_HANDLED; | 458 | return IRQ_HANDLED; |
459 | } | 459 | } |
460 | 460 | ||
461 | static int bf5xx_nand_dma_rw(struct mtd_info *mtd, | 461 | static void bf5xx_nand_dma_rw(struct mtd_info *mtd, |
462 | uint8_t *buf, int is_read) | 462 | uint8_t *buf, int is_read) |
463 | { | 463 | { |
464 | struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); | 464 | struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); |
@@ -496,11 +496,20 @@ static int bf5xx_nand_dma_rw(struct mtd_info *mtd, | |||
496 | /* setup DMA register with Blackfin DMA API */ | 496 | /* setup DMA register with Blackfin DMA API */ |
497 | set_dma_config(CH_NFC, 0x0); | 497 | set_dma_config(CH_NFC, 0x0); |
498 | set_dma_start_addr(CH_NFC, (unsigned long) buf); | 498 | set_dma_start_addr(CH_NFC, (unsigned long) buf); |
499 | |||
500 | /* The DMAs have different size on BF52x and BF54x */ | ||
501 | #ifdef CONFIG_BF52x | ||
502 | set_dma_x_count(CH_NFC, (page_size >> 1)); | ||
503 | set_dma_x_modify(CH_NFC, 2); | ||
504 | val = DI_EN | WDSIZE_16; | ||
505 | #endif | ||
506 | |||
507 | #ifdef CONFIG_BF54x | ||
499 | set_dma_x_count(CH_NFC, (page_size >> 2)); | 508 | set_dma_x_count(CH_NFC, (page_size >> 2)); |
500 | set_dma_x_modify(CH_NFC, 4); | 509 | set_dma_x_modify(CH_NFC, 4); |
501 | |||
502 | /* setup write or read operation */ | ||
503 | val = DI_EN | WDSIZE_32; | 510 | val = DI_EN | WDSIZE_32; |
511 | #endif | ||
512 | /* setup write or read operation */ | ||
504 | if (is_read) | 513 | if (is_read) |
505 | val |= WNR; | 514 | val |= WNR; |
506 | set_dma_config(CH_NFC, val); | 515 | set_dma_config(CH_NFC, val); |
@@ -512,8 +521,6 @@ static int bf5xx_nand_dma_rw(struct mtd_info *mtd, | |||
512 | else | 521 | else |
513 | bfin_write_NFC_PGCTL(0x2); | 522 | bfin_write_NFC_PGCTL(0x2); |
514 | wait_for_completion(&info->dma_completion); | 523 | wait_for_completion(&info->dma_completion); |
515 | |||
516 | return 0; | ||
517 | } | 524 | } |
518 | 525 | ||
519 | static void bf5xx_nand_dma_read_buf(struct mtd_info *mtd, | 526 | static void bf5xx_nand_dma_read_buf(struct mtd_info *mtd, |
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 02700f769b8a..0fad6487e6f4 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c | |||
@@ -44,7 +44,7 @@ | |||
44 | * and some flavors of secondary chipselect (e.g. based on A12) as used | 44 | * and some flavors of secondary chipselect (e.g. based on A12) as used |
45 | * with multichip packages. | 45 | * with multichip packages. |
46 | * | 46 | * |
47 | * The 1-bit ECC hardware is supported, but not yet the newer 4-bit ECC | 47 | * The 1-bit ECC hardware is supported, as well as the newer 4-bit ECC |
48 | * available on chips like the DM355 and OMAP-L137 and needed with the | 48 | * available on chips like the DM355 and OMAP-L137 and needed with the |
49 | * more error-prone MLC NAND chips. | 49 | * more error-prone MLC NAND chips. |
50 | * | 50 | * |
@@ -54,11 +54,14 @@ | |||
54 | struct davinci_nand_info { | 54 | struct davinci_nand_info { |
55 | struct mtd_info mtd; | 55 | struct mtd_info mtd; |
56 | struct nand_chip chip; | 56 | struct nand_chip chip; |
57 | struct nand_ecclayout ecclayout; | ||
57 | 58 | ||
58 | struct device *dev; | 59 | struct device *dev; |
59 | struct clk *clk; | 60 | struct clk *clk; |
60 | bool partitioned; | 61 | bool partitioned; |
61 | 62 | ||
63 | bool is_readmode; | ||
64 | |||
62 | void __iomem *base; | 65 | void __iomem *base; |
63 | void __iomem *vaddr; | 66 | void __iomem *vaddr; |
64 | 67 | ||
@@ -73,6 +76,7 @@ struct davinci_nand_info { | |||
73 | }; | 76 | }; |
74 | 77 | ||
75 | static DEFINE_SPINLOCK(davinci_nand_lock); | 78 | static DEFINE_SPINLOCK(davinci_nand_lock); |
79 | static bool ecc4_busy; | ||
76 | 80 | ||
77 | #define to_davinci_nand(m) container_of(m, struct davinci_nand_info, mtd) | 81 | #define to_davinci_nand(m) container_of(m, struct davinci_nand_info, mtd) |
78 | 82 | ||
@@ -218,6 +222,192 @@ static int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat, | |||
218 | /*----------------------------------------------------------------------*/ | 222 | /*----------------------------------------------------------------------*/ |
219 | 223 | ||
220 | /* | 224 | /* |
225 | * 4-bit hardware ECC ... context maintained over entire AEMIF | ||
226 | * | ||
227 | * This is a syndrome engine, but we avoid NAND_ECC_HW_SYNDROME | ||
228 | * since that forces use of a problematic "infix OOB" layout. | ||
229 | * Among other things, it trashes manufacturer bad block markers. | ||
230 | * Also, and specific to this hardware, it ECC-protects the "prepad" | ||
231 | * in the OOB ... while having ECC protection for parts of OOB would | ||
232 | * seem useful, the current MTD stack sometimes wants to update the | ||
233 | * OOB without recomputing ECC. | ||
234 | */ | ||
235 | |||
236 | static void nand_davinci_hwctl_4bit(struct mtd_info *mtd, int mode) | ||
237 | { | ||
238 | struct davinci_nand_info *info = to_davinci_nand(mtd); | ||
239 | unsigned long flags; | ||
240 | u32 val; | ||
241 | |||
242 | spin_lock_irqsave(&davinci_nand_lock, flags); | ||
243 | |||
244 | /* Start 4-bit ECC calculation for read/write */ | ||
245 | val = davinci_nand_readl(info, NANDFCR_OFFSET); | ||
246 | val &= ~(0x03 << 4); | ||
247 | val |= (info->core_chipsel << 4) | BIT(12); | ||
248 | davinci_nand_writel(info, NANDFCR_OFFSET, val); | ||
249 | |||
250 | info->is_readmode = (mode == NAND_ECC_READ); | ||
251 | |||
252 | spin_unlock_irqrestore(&davinci_nand_lock, flags); | ||
253 | } | ||
254 | |||
255 | /* Read raw ECC code after writing to NAND. */ | ||
256 | static void | ||
257 | nand_davinci_readecc_4bit(struct davinci_nand_info *info, u32 code[4]) | ||
258 | { | ||
259 | const u32 mask = 0x03ff03ff; | ||
260 | |||
261 | code[0] = davinci_nand_readl(info, NAND_4BIT_ECC1_OFFSET) & mask; | ||
262 | code[1] = davinci_nand_readl(info, NAND_4BIT_ECC2_OFFSET) & mask; | ||
263 | code[2] = davinci_nand_readl(info, NAND_4BIT_ECC3_OFFSET) & mask; | ||
264 | code[3] = davinci_nand_readl(info, NAND_4BIT_ECC4_OFFSET) & mask; | ||
265 | } | ||
266 | |||
267 | /* Terminate read ECC; or return ECC (as bytes) of data written to NAND. */ | ||
268 | static int nand_davinci_calculate_4bit(struct mtd_info *mtd, | ||
269 | const u_char *dat, u_char *ecc_code) | ||
270 | { | ||
271 | struct davinci_nand_info *info = to_davinci_nand(mtd); | ||
272 | u32 raw_ecc[4], *p; | ||
273 | unsigned i; | ||
274 | |||
275 | /* After a read, terminate ECC calculation by a dummy read | ||
276 | * of some 4-bit ECC register. ECC covers everything that | ||
277 | * was read; correct() just uses the hardware state, so | ||
278 | * ecc_code is not needed. | ||
279 | */ | ||
280 | if (info->is_readmode) { | ||
281 | davinci_nand_readl(info, NAND_4BIT_ECC1_OFFSET); | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | /* Pack eight raw 10-bit ecc values into ten bytes, making | ||
286 | * two passes which each convert four values (in upper and | ||
287 | * lower halves of two 32-bit words) into five bytes. The | ||
288 | * ROM boot loader uses this same packing scheme. | ||
289 | */ | ||
290 | nand_davinci_readecc_4bit(info, raw_ecc); | ||
291 | for (i = 0, p = raw_ecc; i < 2; i++, p += 2) { | ||
292 | *ecc_code++ = p[0] & 0xff; | ||
293 | *ecc_code++ = ((p[0] >> 8) & 0x03) | ((p[0] >> 14) & 0xfc); | ||
294 | *ecc_code++ = ((p[0] >> 22) & 0x0f) | ((p[1] << 4) & 0xf0); | ||
295 | *ecc_code++ = ((p[1] >> 4) & 0x3f) | ((p[1] >> 10) & 0xc0); | ||
296 | *ecc_code++ = (p[1] >> 18) & 0xff; | ||
297 | } | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | /* Correct up to 4 bits in data we just read, using state left in the | ||
303 | * hardware plus the ecc_code computed when it was first written. | ||
304 | */ | ||
305 | static int nand_davinci_correct_4bit(struct mtd_info *mtd, | ||
306 | u_char *data, u_char *ecc_code, u_char *null) | ||
307 | { | ||
308 | int i; | ||
309 | struct davinci_nand_info *info = to_davinci_nand(mtd); | ||
310 | unsigned short ecc10[8]; | ||
311 | unsigned short *ecc16; | ||
312 | u32 syndrome[4]; | ||
313 | unsigned num_errors, corrected; | ||
314 | |||
315 | /* All bytes 0xff? It's an erased page; ignore its ECC. */ | ||
316 | for (i = 0; i < 10; i++) { | ||
317 | if (ecc_code[i] != 0xff) | ||
318 | goto compare; | ||
319 | } | ||
320 | return 0; | ||
321 | |||
322 | compare: | ||
323 | /* Unpack ten bytes into eight 10 bit values. We know we're | ||
324 | * little-endian, and use type punning for less shifting/masking. | ||
325 | */ | ||
326 | if (WARN_ON(0x01 & (unsigned) ecc_code)) | ||
327 | return -EINVAL; | ||
328 | ecc16 = (unsigned short *)ecc_code; | ||
329 | |||
330 | ecc10[0] = (ecc16[0] >> 0) & 0x3ff; | ||
331 | ecc10[1] = ((ecc16[0] >> 10) & 0x3f) | ((ecc16[1] << 6) & 0x3c0); | ||
332 | ecc10[2] = (ecc16[1] >> 4) & 0x3ff; | ||
333 | ecc10[3] = ((ecc16[1] >> 14) & 0x3) | ((ecc16[2] << 2) & 0x3fc); | ||
334 | ecc10[4] = (ecc16[2] >> 8) | ((ecc16[3] << 8) & 0x300); | ||
335 | ecc10[5] = (ecc16[3] >> 2) & 0x3ff; | ||
336 | ecc10[6] = ((ecc16[3] >> 12) & 0xf) | ((ecc16[4] << 4) & 0x3f0); | ||
337 | ecc10[7] = (ecc16[4] >> 6) & 0x3ff; | ||
338 | |||
339 | /* Tell ECC controller about the expected ECC codes. */ | ||
340 | for (i = 7; i >= 0; i--) | ||
341 | davinci_nand_writel(info, NAND_4BIT_ECC_LOAD_OFFSET, ecc10[i]); | ||
342 | |||
343 | /* Allow time for syndrome calculation ... then read it. | ||
344 | * A syndrome of all zeroes 0 means no detected errors. | ||
345 | */ | ||
346 | davinci_nand_readl(info, NANDFSR_OFFSET); | ||
347 | nand_davinci_readecc_4bit(info, syndrome); | ||
348 | if (!(syndrome[0] | syndrome[1] | syndrome[2] | syndrome[3])) | ||
349 | return 0; | ||
350 | |||
351 | /* Start address calculation, and wait for it to complete. | ||
352 | * We _could_ start reading more data while this is working, | ||
353 | * to speed up the overall page read. | ||
354 | */ | ||
355 | davinci_nand_writel(info, NANDFCR_OFFSET, | ||
356 | davinci_nand_readl(info, NANDFCR_OFFSET) | BIT(13)); | ||
357 | for (;;) { | ||
358 | u32 fsr = davinci_nand_readl(info, NANDFSR_OFFSET); | ||
359 | |||
360 | switch ((fsr >> 8) & 0x0f) { | ||
361 | case 0: /* no error, should not happen */ | ||
362 | return 0; | ||
363 | case 1: /* five or more errors detected */ | ||
364 | return -EIO; | ||
365 | case 2: /* error addresses computed */ | ||
366 | case 3: | ||
367 | num_errors = 1 + ((fsr >> 16) & 0x03); | ||
368 | goto correct; | ||
369 | default: /* still working on it */ | ||
370 | cpu_relax(); | ||
371 | continue; | ||
372 | } | ||
373 | } | ||
374 | |||
375 | correct: | ||
376 | /* correct each error */ | ||
377 | for (i = 0, corrected = 0; i < num_errors; i++) { | ||
378 | int error_address, error_value; | ||
379 | |||
380 | if (i > 1) { | ||
381 | error_address = davinci_nand_readl(info, | ||
382 | NAND_ERR_ADD2_OFFSET); | ||
383 | error_value = davinci_nand_readl(info, | ||
384 | NAND_ERR_ERRVAL2_OFFSET); | ||
385 | } else { | ||
386 | error_address = davinci_nand_readl(info, | ||
387 | NAND_ERR_ADD1_OFFSET); | ||
388 | error_value = davinci_nand_readl(info, | ||
389 | NAND_ERR_ERRVAL1_OFFSET); | ||
390 | } | ||
391 | |||
392 | if (i & 1) { | ||
393 | error_address >>= 16; | ||
394 | error_value >>= 16; | ||
395 | } | ||
396 | error_address &= 0x3ff; | ||
397 | error_address = (512 + 7) - error_address; | ||
398 | |||
399 | if (error_address < 512) { | ||
400 | data[error_address] ^= error_value; | ||
401 | corrected++; | ||
402 | } | ||
403 | } | ||
404 | |||
405 | return corrected; | ||
406 | } | ||
407 | |||
408 | /*----------------------------------------------------------------------*/ | ||
409 | |||
410 | /* | ||
221 | * NOTE: NAND boot requires ALE == EM_A[1], CLE == EM_A[2], so that's | 411 | * NOTE: NAND boot requires ALE == EM_A[1], CLE == EM_A[2], so that's |
222 | * how these chips are normally wired. This translates to both 8 and 16 | 412 | * how these chips are normally wired. This translates to both 8 and 16 |
223 | * bit busses using ALE == BIT(3) in byte addresses, and CLE == BIT(4). | 413 | * bit busses using ALE == BIT(3) in byte addresses, and CLE == BIT(4). |
@@ -294,6 +484,23 @@ static void __init nand_dm6446evm_flash_init(struct davinci_nand_info *info) | |||
294 | 484 | ||
295 | /*----------------------------------------------------------------------*/ | 485 | /*----------------------------------------------------------------------*/ |
296 | 486 | ||
487 | /* An ECC layout for using 4-bit ECC with small-page flash, storing | ||
488 | * ten ECC bytes plus the manufacturer's bad block marker byte, and | ||
489 | * and not overlapping the default BBT markers. | ||
490 | */ | ||
491 | static struct nand_ecclayout hwecc4_small __initconst = { | ||
492 | .eccbytes = 10, | ||
493 | .eccpos = { 0, 1, 2, 3, 4, | ||
494 | /* offset 5 holds the badblock marker */ | ||
495 | 6, 7, | ||
496 | 13, 14, 15, }, | ||
497 | .oobfree = { | ||
498 | {.offset = 8, .length = 5, }, | ||
499 | {.offset = 16, }, | ||
500 | }, | ||
501 | }; | ||
502 | |||
503 | |||
297 | static int __init nand_davinci_probe(struct platform_device *pdev) | 504 | static int __init nand_davinci_probe(struct platform_device *pdev) |
298 | { | 505 | { |
299 | struct davinci_nand_pdata *pdata = pdev->dev.platform_data; | 506 | struct davinci_nand_pdata *pdata = pdev->dev.platform_data; |
@@ -306,6 +513,10 @@ static int __init nand_davinci_probe(struct platform_device *pdev) | |||
306 | uint32_t val; | 513 | uint32_t val; |
307 | nand_ecc_modes_t ecc_mode; | 514 | nand_ecc_modes_t ecc_mode; |
308 | 515 | ||
516 | /* insist on board-specific configuration */ | ||
517 | if (!pdata) | ||
518 | return -ENODEV; | ||
519 | |||
309 | /* which external chipselect will we be managing? */ | 520 | /* which external chipselect will we be managing? */ |
310 | if (pdev->id < 0 || pdev->id > 3) | 521 | if (pdev->id < 0 || pdev->id > 3) |
311 | return -ENODEV; | 522 | return -ENODEV; |
@@ -351,7 +562,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev) | |||
351 | info->chip.select_chip = nand_davinci_select_chip; | 562 | info->chip.select_chip = nand_davinci_select_chip; |
352 | 563 | ||
353 | /* options such as NAND_USE_FLASH_BBT or 16-bit widths */ | 564 | /* options such as NAND_USE_FLASH_BBT or 16-bit widths */ |
354 | info->chip.options = pdata ? pdata->options : 0; | 565 | info->chip.options = pdata->options; |
355 | 566 | ||
356 | info->ioaddr = (uint32_t __force) vaddr; | 567 | info->ioaddr = (uint32_t __force) vaddr; |
357 | 568 | ||
@@ -360,14 +571,8 @@ static int __init nand_davinci_probe(struct platform_device *pdev) | |||
360 | info->mask_chipsel = pdata->mask_chipsel; | 571 | info->mask_chipsel = pdata->mask_chipsel; |
361 | 572 | ||
362 | /* use nandboot-capable ALE/CLE masks by default */ | 573 | /* use nandboot-capable ALE/CLE masks by default */ |
363 | if (pdata && pdata->mask_ale) | 574 | info->mask_ale = pdata->mask_cle ? : MASK_ALE; |
364 | info->mask_ale = pdata->mask_cle; | 575 | info->mask_cle = pdata->mask_cle ? : MASK_CLE; |
365 | else | ||
366 | info->mask_ale = MASK_ALE; | ||
367 | if (pdata && pdata->mask_cle) | ||
368 | info->mask_cle = pdata->mask_cle; | ||
369 | else | ||
370 | info->mask_cle = MASK_CLE; | ||
371 | 576 | ||
372 | /* Set address of hardware control function */ | 577 | /* Set address of hardware control function */ |
373 | info->chip.cmd_ctrl = nand_davinci_hwcontrol; | 578 | info->chip.cmd_ctrl = nand_davinci_hwcontrol; |
@@ -377,30 +582,44 @@ static int __init nand_davinci_probe(struct platform_device *pdev) | |||
377 | info->chip.read_buf = nand_davinci_read_buf; | 582 | info->chip.read_buf = nand_davinci_read_buf; |
378 | info->chip.write_buf = nand_davinci_write_buf; | 583 | info->chip.write_buf = nand_davinci_write_buf; |
379 | 584 | ||
380 | /* use board-specific ECC config; else, the best available */ | 585 | /* Use board-specific ECC config */ |
381 | if (pdata) | 586 | ecc_mode = pdata->ecc_mode; |
382 | ecc_mode = pdata->ecc_mode; | ||
383 | else | ||
384 | ecc_mode = NAND_ECC_HW; | ||
385 | 587 | ||
588 | ret = -EINVAL; | ||
386 | switch (ecc_mode) { | 589 | switch (ecc_mode) { |
387 | case NAND_ECC_NONE: | 590 | case NAND_ECC_NONE: |
388 | case NAND_ECC_SOFT: | 591 | case NAND_ECC_SOFT: |
592 | pdata->ecc_bits = 0; | ||
389 | break; | 593 | break; |
390 | case NAND_ECC_HW: | 594 | case NAND_ECC_HW: |
391 | info->chip.ecc.calculate = nand_davinci_calculate_1bit; | 595 | if (pdata->ecc_bits == 4) { |
392 | info->chip.ecc.correct = nand_davinci_correct_1bit; | 596 | /* No sanity checks: CPUs must support this, |
393 | info->chip.ecc.hwctl = nand_davinci_hwctl_1bit; | 597 | * and the chips may not use NAND_BUSWIDTH_16. |
598 | */ | ||
599 | |||
600 | /* No sharing 4-bit hardware between chipselects yet */ | ||
601 | spin_lock_irq(&davinci_nand_lock); | ||
602 | if (ecc4_busy) | ||
603 | ret = -EBUSY; | ||
604 | else | ||
605 | ecc4_busy = true; | ||
606 | spin_unlock_irq(&davinci_nand_lock); | ||
607 | |||
608 | if (ret == -EBUSY) | ||
609 | goto err_ecc; | ||
610 | |||
611 | info->chip.ecc.calculate = nand_davinci_calculate_4bit; | ||
612 | info->chip.ecc.correct = nand_davinci_correct_4bit; | ||
613 | info->chip.ecc.hwctl = nand_davinci_hwctl_4bit; | ||
614 | info->chip.ecc.bytes = 10; | ||
615 | } else { | ||
616 | info->chip.ecc.calculate = nand_davinci_calculate_1bit; | ||
617 | info->chip.ecc.correct = nand_davinci_correct_1bit; | ||
618 | info->chip.ecc.hwctl = nand_davinci_hwctl_1bit; | ||
619 | info->chip.ecc.bytes = 3; | ||
620 | } | ||
394 | info->chip.ecc.size = 512; | 621 | info->chip.ecc.size = 512; |
395 | info->chip.ecc.bytes = 3; | ||
396 | break; | 622 | break; |
397 | case NAND_ECC_HW_SYNDROME: | ||
398 | /* FIXME implement */ | ||
399 | info->chip.ecc.size = 512; | ||
400 | info->chip.ecc.bytes = 10; | ||
401 | |||
402 | dev_warn(&pdev->dev, "4-bit ECC nyet supported\n"); | ||
403 | /* FALL THROUGH */ | ||
404 | default: | 623 | default: |
405 | ret = -EINVAL; | 624 | ret = -EINVAL; |
406 | goto err_ecc; | 625 | goto err_ecc; |
@@ -441,12 +660,56 @@ static int __init nand_davinci_probe(struct platform_device *pdev) | |||
441 | spin_unlock_irq(&davinci_nand_lock); | 660 | spin_unlock_irq(&davinci_nand_lock); |
442 | 661 | ||
443 | /* Scan to find existence of the device(s) */ | 662 | /* Scan to find existence of the device(s) */ |
444 | ret = nand_scan(&info->mtd, pdata->mask_chipsel ? 2 : 1); | 663 | ret = nand_scan_ident(&info->mtd, pdata->mask_chipsel ? 2 : 1); |
445 | if (ret < 0) { | 664 | if (ret < 0) { |
446 | dev_dbg(&pdev->dev, "no NAND chip(s) found\n"); | 665 | dev_dbg(&pdev->dev, "no NAND chip(s) found\n"); |
447 | goto err_scan; | 666 | goto err_scan; |
448 | } | 667 | } |
449 | 668 | ||
669 | /* Update ECC layout if needed ... for 1-bit HW ECC, the default | ||
670 | * is OK, but it allocates 6 bytes when only 3 are needed (for | ||
671 | * each 512 bytes). For the 4-bit HW ECC, that default is not | ||
672 | * usable: 10 bytes are needed, not 6. | ||
673 | */ | ||
674 | if (pdata->ecc_bits == 4) { | ||
675 | int chunks = info->mtd.writesize / 512; | ||
676 | |||
677 | if (!chunks || info->mtd.oobsize < 16) { | ||
678 | dev_dbg(&pdev->dev, "too small\n"); | ||
679 | ret = -EINVAL; | ||
680 | goto err_scan; | ||
681 | } | ||
682 | |||
683 | /* For small page chips, preserve the manufacturer's | ||
684 | * badblock marking data ... and make sure a flash BBT | ||
685 | * table marker fits in the free bytes. | ||
686 | */ | ||
687 | if (chunks == 1) { | ||
688 | info->ecclayout = hwecc4_small; | ||
689 | info->ecclayout.oobfree[1].length = | ||
690 | info->mtd.oobsize - 16; | ||
691 | goto syndrome_done; | ||
692 | } | ||
693 | |||
694 | /* For large page chips we'll be wanting to use a | ||
695 | * not-yet-implemented mode that reads OOB data | ||
696 | * before reading the body of the page, to avoid | ||
697 | * the "infix OOB" model of NAND_ECC_HW_SYNDROME | ||
698 | * (and preserve manufacturer badblock markings). | ||
699 | */ | ||
700 | dev_warn(&pdev->dev, "no 4-bit ECC support yet " | ||
701 | "for large page NAND\n"); | ||
702 | ret = -EIO; | ||
703 | goto err_scan; | ||
704 | |||
705 | syndrome_done: | ||
706 | info->chip.ecc.layout = &info->ecclayout; | ||
707 | } | ||
708 | |||
709 | ret = nand_scan_tail(&info->mtd); | ||
710 | if (ret < 0) | ||
711 | goto err_scan; | ||
712 | |||
450 | if (mtd_has_partitions()) { | 713 | if (mtd_has_partitions()) { |
451 | struct mtd_partition *mtd_parts = NULL; | 714 | struct mtd_partition *mtd_parts = NULL; |
452 | int mtd_parts_nb = 0; | 715 | int mtd_parts_nb = 0; |
@@ -455,22 +718,11 @@ static int __init nand_davinci_probe(struct platform_device *pdev) | |||
455 | static const char *probes[] __initconst = | 718 | static const char *probes[] __initconst = |
456 | { "cmdlinepart", NULL }; | 719 | { "cmdlinepart", NULL }; |
457 | 720 | ||
458 | const char *master_name; | ||
459 | |||
460 | /* Set info->mtd.name = 0 temporarily */ | ||
461 | master_name = info->mtd.name; | ||
462 | info->mtd.name = (char *)0; | ||
463 | |||
464 | /* info->mtd.name == 0, means: don't bother checking | ||
465 | <mtd-id> */ | ||
466 | mtd_parts_nb = parse_mtd_partitions(&info->mtd, probes, | 721 | mtd_parts_nb = parse_mtd_partitions(&info->mtd, probes, |
467 | &mtd_parts, 0); | 722 | &mtd_parts, 0); |
468 | |||
469 | /* Restore info->mtd.name */ | ||
470 | info->mtd.name = master_name; | ||
471 | } | 723 | } |
472 | 724 | ||
473 | if (mtd_parts_nb <= 0 && pdata) { | 725 | if (mtd_parts_nb <= 0) { |
474 | mtd_parts = pdata->parts; | 726 | mtd_parts = pdata->parts; |
475 | mtd_parts_nb = pdata->nr_parts; | 727 | mtd_parts_nb = pdata->nr_parts; |
476 | } | 728 | } |
@@ -483,7 +735,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev) | |||
483 | info->partitioned = true; | 735 | info->partitioned = true; |
484 | } | 736 | } |
485 | 737 | ||
486 | } else if (pdata && pdata->nr_parts) { | 738 | } else if (pdata->nr_parts) { |
487 | dev_warn(&pdev->dev, "ignoring %d default partitions on %s\n", | 739 | dev_warn(&pdev->dev, "ignoring %d default partitions on %s\n", |
488 | pdata->nr_parts, info->mtd.name); | 740 | pdata->nr_parts, info->mtd.name); |
489 | } | 741 | } |
@@ -509,6 +761,11 @@ err_scan: | |||
509 | err_clk_enable: | 761 | err_clk_enable: |
510 | clk_put(info->clk); | 762 | clk_put(info->clk); |
511 | 763 | ||
764 | spin_lock_irq(&davinci_nand_lock); | ||
765 | if (ecc_mode == NAND_ECC_HW_SYNDROME) | ||
766 | ecc4_busy = false; | ||
767 | spin_unlock_irq(&davinci_nand_lock); | ||
768 | |||
512 | err_ecc: | 769 | err_ecc: |
513 | err_clk: | 770 | err_clk: |
514 | err_ioremap: | 771 | err_ioremap: |
@@ -532,6 +789,11 @@ static int __exit nand_davinci_remove(struct platform_device *pdev) | |||
532 | else | 789 | else |
533 | status = del_mtd_device(&info->mtd); | 790 | status = del_mtd_device(&info->mtd); |
534 | 791 | ||
792 | spin_lock_irq(&davinci_nand_lock); | ||
793 | if (info->chip.ecc.mode == NAND_ECC_HW_SYNDROME) | ||
794 | ecc4_busy = false; | ||
795 | spin_unlock_irq(&davinci_nand_lock); | ||
796 | |||
535 | iounmap(info->base); | 797 | iounmap(info->base); |
536 | iounmap(info->vaddr); | 798 | iounmap(info->vaddr); |
537 | 799 | ||
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 40c26080ecda..76beea40d2cf 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -138,7 +138,14 @@ static struct nand_ecclayout nand_hw_eccoob_8 = { | |||
138 | static struct nand_ecclayout nand_hw_eccoob_16 = { | 138 | static struct nand_ecclayout nand_hw_eccoob_16 = { |
139 | .eccbytes = 5, | 139 | .eccbytes = 5, |
140 | .eccpos = {6, 7, 8, 9, 10}, | 140 | .eccpos = {6, 7, 8, 9, 10}, |
141 | .oobfree = {{0, 6}, {12, 4}, } | 141 | .oobfree = {{0, 5}, {11, 5}, } |
142 | }; | ||
143 | |||
144 | static struct nand_ecclayout nand_hw_eccoob_64 = { | ||
145 | .eccbytes = 20, | ||
146 | .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26, | ||
147 | 38, 39, 40, 41, 42, 54, 55, 56, 57, 58}, | ||
148 | .oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, } | ||
142 | }; | 149 | }; |
143 | 150 | ||
144 | #ifdef CONFIG_MTD_PARTITIONS | 151 | #ifdef CONFIG_MTD_PARTITIONS |
@@ -192,7 +199,7 @@ static void wait_op_done(struct mxc_nand_host *host, int max_retries, | |||
192 | } | 199 | } |
193 | udelay(1); | 200 | udelay(1); |
194 | } | 201 | } |
195 | if (max_retries <= 0) | 202 | if (max_retries < 0) |
196 | DEBUG(MTD_DEBUG_LEVEL0, "%s(%d): INT not set\n", | 203 | DEBUG(MTD_DEBUG_LEVEL0, "%s(%d): INT not set\n", |
197 | __func__, param); | 204 | __func__, param); |
198 | } | 205 | } |
@@ -795,9 +802,13 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
795 | send_addr(host, (page_addr & 0xff), false); | 802 | send_addr(host, (page_addr & 0xff), false); |
796 | 803 | ||
797 | if (host->pagesize_2k) { | 804 | if (host->pagesize_2k) { |
798 | send_addr(host, (page_addr >> 8) & 0xFF, false); | 805 | if (mtd->size >= 0x10000000) { |
799 | if (mtd->size >= 0x40000000) | 806 | /* paddr_8 - paddr_15 */ |
807 | send_addr(host, (page_addr >> 8) & 0xff, false); | ||
800 | send_addr(host, (page_addr >> 16) & 0xff, true); | 808 | send_addr(host, (page_addr >> 16) & 0xff, true); |
809 | } else | ||
810 | /* paddr_8 - paddr_15 */ | ||
811 | send_addr(host, (page_addr >> 8) & 0xff, true); | ||
801 | } else { | 812 | } else { |
802 | /* One more address cycle for higher density devices */ | 813 | /* One more address cycle for higher density devices */ |
803 | if (mtd->size >= 0x4000000) { | 814 | if (mtd->size >= 0x4000000) { |
@@ -923,7 +934,6 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
923 | this->ecc.mode = NAND_ECC_HW; | 934 | this->ecc.mode = NAND_ECC_HW; |
924 | this->ecc.size = 512; | 935 | this->ecc.size = 512; |
925 | this->ecc.bytes = 3; | 936 | this->ecc.bytes = 3; |
926 | this->ecc.layout = &nand_hw_eccoob_8; | ||
927 | tmp = readw(host->regs + NFC_CONFIG1); | 937 | tmp = readw(host->regs + NFC_CONFIG1); |
928 | tmp |= NFC_ECC_EN; | 938 | tmp |= NFC_ECC_EN; |
929 | writew(tmp, host->regs + NFC_CONFIG1); | 939 | writew(tmp, host->regs + NFC_CONFIG1); |
@@ -957,12 +967,44 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
957 | this->ecc.layout = &nand_hw_eccoob_16; | 967 | this->ecc.layout = &nand_hw_eccoob_16; |
958 | } | 968 | } |
959 | 969 | ||
960 | host->pagesize_2k = 0; | 970 | /* first scan to find the device and get the page size */ |
971 | if (nand_scan_ident(mtd, 1)) { | ||
972 | err = -ENXIO; | ||
973 | goto escan; | ||
974 | } | ||
961 | 975 | ||
962 | /* Scan to find existence of the device */ | 976 | host->pagesize_2k = (mtd->writesize == 2048) ? 1 : 0; |
963 | if (nand_scan(mtd, 1)) { | 977 | |
964 | DEBUG(MTD_DEBUG_LEVEL0, | 978 | if (this->ecc.mode == NAND_ECC_HW) { |
965 | "MXC_ND: Unable to find any NAND device.\n"); | 979 | switch (mtd->oobsize) { |
980 | case 8: | ||
981 | this->ecc.layout = &nand_hw_eccoob_8; | ||
982 | break; | ||
983 | case 16: | ||
984 | this->ecc.layout = &nand_hw_eccoob_16; | ||
985 | break; | ||
986 | case 64: | ||
987 | this->ecc.layout = &nand_hw_eccoob_64; | ||
988 | break; | ||
989 | default: | ||
990 | /* page size not handled by HW ECC */ | ||
991 | /* switching back to soft ECC */ | ||
992 | this->ecc.size = 512; | ||
993 | this->ecc.bytes = 3; | ||
994 | this->ecc.layout = &nand_hw_eccoob_8; | ||
995 | this->ecc.mode = NAND_ECC_SOFT; | ||
996 | this->ecc.calculate = NULL; | ||
997 | this->ecc.correct = NULL; | ||
998 | this->ecc.hwctl = NULL; | ||
999 | tmp = readw(host->regs + NFC_CONFIG1); | ||
1000 | tmp &= ~NFC_ECC_EN; | ||
1001 | writew(tmp, host->regs + NFC_CONFIG1); | ||
1002 | break; | ||
1003 | } | ||
1004 | } | ||
1005 | |||
1006 | /* second phase scan */ | ||
1007 | if (nand_scan_tail(mtd)) { | ||
966 | err = -ENXIO; | 1008 | err = -ENXIO; |
967 | goto escan; | 1009 | goto escan; |
968 | } | 1010 | } |
@@ -985,7 +1027,7 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
985 | return 0; | 1027 | return 0; |
986 | 1028 | ||
987 | escan: | 1029 | escan: |
988 | free_irq(host->irq, NULL); | 1030 | free_irq(host->irq, host); |
989 | eirq: | 1031 | eirq: |
990 | iounmap(host->regs); | 1032 | iounmap(host->regs); |
991 | eres: | 1033 | eres: |
@@ -1005,7 +1047,7 @@ static int __devexit mxcnd_remove(struct platform_device *pdev) | |||
1005 | platform_set_drvdata(pdev, NULL); | 1047 | platform_set_drvdata(pdev, NULL); |
1006 | 1048 | ||
1007 | nand_release(&host->mtd); | 1049 | nand_release(&host->mtd); |
1008 | free_irq(host->irq, NULL); | 1050 | free_irq(host->irq, host); |
1009 | iounmap(host->regs); | 1051 | iounmap(host->regs); |
1010 | kfree(host); | 1052 | kfree(host); |
1011 | 1053 | ||
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 3d7ed432fa41..8c21b89d2d0c 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -2756,7 +2756,8 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
2756 | * the out of band area | 2756 | * the out of band area |
2757 | */ | 2757 | */ |
2758 | chip->ecc.layout->oobavail = 0; | 2758 | chip->ecc.layout->oobavail = 0; |
2759 | for (i = 0; chip->ecc.layout->oobfree[i].length; i++) | 2759 | for (i = 0; chip->ecc.layout->oobfree[i].length |
2760 | && i < ARRAY_SIZE(chip->ecc.layout->oobfree); i++) | ||
2760 | chip->ecc.layout->oobavail += | 2761 | chip->ecc.layout->oobavail += |
2761 | chip->ecc.layout->oobfree[i].length; | 2762 | chip->ecc.layout->oobfree[i].length; |
2762 | mtd->oobavail = chip->ecc.layout->oobavail; | 2763 | mtd->oobavail = chip->ecc.layout->oobavail; |
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c index 868147acce2c..c0cb87d6d16e 100644 --- a/drivers/mtd/nand/nand_ecc.c +++ b/drivers/mtd/nand/nand_ecc.c | |||
@@ -428,8 +428,8 @@ EXPORT_SYMBOL(nand_calculate_ecc); | |||
428 | int nand_correct_data(struct mtd_info *mtd, unsigned char *buf, | 428 | int nand_correct_data(struct mtd_info *mtd, unsigned char *buf, |
429 | unsigned char *read_ecc, unsigned char *calc_ecc) | 429 | unsigned char *read_ecc, unsigned char *calc_ecc) |
430 | { | 430 | { |
431 | unsigned char b0, b1, b2; | 431 | unsigned char b0, b1, b2, bit_addr; |
432 | unsigned char byte_addr, bit_addr; | 432 | unsigned int byte_addr; |
433 | /* 256 or 512 bytes/ecc */ | 433 | /* 256 or 512 bytes/ecc */ |
434 | const uint32_t eccsize_mult = | 434 | const uint32_t eccsize_mult = |
435 | (((struct nand_chip *)mtd->priv)->ecc.size) >> 8; | 435 | (((struct nand_chip *)mtd->priv)->ecc.size) >> 8; |
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c new file mode 100644 index 000000000000..0cd76f89f4b0 --- /dev/null +++ b/drivers/mtd/nand/omap2.c | |||
@@ -0,0 +1,776 @@ | |||
1 | /* | ||
2 | * Copyright © 2004 Texas Instruments, Jian Zhang <jzhang@ti.com> | ||
3 | * Copyright © 2004 Micron Technology Inc. | ||
4 | * Copyright © 2004 David Brownell | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/platform_device.h> | ||
12 | #include <linux/dma-mapping.h> | ||
13 | #include <linux/delay.h> | ||
14 | #include <linux/mtd/mtd.h> | ||
15 | #include <linux/mtd/nand.h> | ||
16 | #include <linux/mtd/partitions.h> | ||
17 | #include <linux/io.h> | ||
18 | |||
19 | #include <asm/dma.h> | ||
20 | |||
21 | #include <mach/gpmc.h> | ||
22 | #include <mach/nand.h> | ||
23 | |||
24 | #define GPMC_IRQ_STATUS 0x18 | ||
25 | #define GPMC_ECC_CONFIG 0x1F4 | ||
26 | #define GPMC_ECC_CONTROL 0x1F8 | ||
27 | #define GPMC_ECC_SIZE_CONFIG 0x1FC | ||
28 | #define GPMC_ECC1_RESULT 0x200 | ||
29 | |||
30 | #define DRIVER_NAME "omap2-nand" | ||
31 | |||
32 | /* size (4 KiB) for IO mapping */ | ||
33 | #define NAND_IO_SIZE SZ_4K | ||
34 | |||
35 | #define NAND_WP_OFF 0 | ||
36 | #define NAND_WP_BIT 0x00000010 | ||
37 | #define WR_RD_PIN_MONITORING 0x00600000 | ||
38 | |||
39 | #define GPMC_BUF_FULL 0x00000001 | ||
40 | #define GPMC_BUF_EMPTY 0x00000000 | ||
41 | |||
42 | #define NAND_Ecc_P1e (1 << 0) | ||
43 | #define NAND_Ecc_P2e (1 << 1) | ||
44 | #define NAND_Ecc_P4e (1 << 2) | ||
45 | #define NAND_Ecc_P8e (1 << 3) | ||
46 | #define NAND_Ecc_P16e (1 << 4) | ||
47 | #define NAND_Ecc_P32e (1 << 5) | ||
48 | #define NAND_Ecc_P64e (1 << 6) | ||
49 | #define NAND_Ecc_P128e (1 << 7) | ||
50 | #define NAND_Ecc_P256e (1 << 8) | ||
51 | #define NAND_Ecc_P512e (1 << 9) | ||
52 | #define NAND_Ecc_P1024e (1 << 10) | ||
53 | #define NAND_Ecc_P2048e (1 << 11) | ||
54 | |||
55 | #define NAND_Ecc_P1o (1 << 16) | ||
56 | #define NAND_Ecc_P2o (1 << 17) | ||
57 | #define NAND_Ecc_P4o (1 << 18) | ||
58 | #define NAND_Ecc_P8o (1 << 19) | ||
59 | #define NAND_Ecc_P16o (1 << 20) | ||
60 | #define NAND_Ecc_P32o (1 << 21) | ||
61 | #define NAND_Ecc_P64o (1 << 22) | ||
62 | #define NAND_Ecc_P128o (1 << 23) | ||
63 | #define NAND_Ecc_P256o (1 << 24) | ||
64 | #define NAND_Ecc_P512o (1 << 25) | ||
65 | #define NAND_Ecc_P1024o (1 << 26) | ||
66 | #define NAND_Ecc_P2048o (1 << 27) | ||
67 | |||
68 | #define TF(value) (value ? 1 : 0) | ||
69 | |||
70 | #define P2048e(a) (TF(a & NAND_Ecc_P2048e) << 0) | ||
71 | #define P2048o(a) (TF(a & NAND_Ecc_P2048o) << 1) | ||
72 | #define P1e(a) (TF(a & NAND_Ecc_P1e) << 2) | ||
73 | #define P1o(a) (TF(a & NAND_Ecc_P1o) << 3) | ||
74 | #define P2e(a) (TF(a & NAND_Ecc_P2e) << 4) | ||
75 | #define P2o(a) (TF(a & NAND_Ecc_P2o) << 5) | ||
76 | #define P4e(a) (TF(a & NAND_Ecc_P4e) << 6) | ||
77 | #define P4o(a) (TF(a & NAND_Ecc_P4o) << 7) | ||
78 | |||
79 | #define P8e(a) (TF(a & NAND_Ecc_P8e) << 0) | ||
80 | #define P8o(a) (TF(a & NAND_Ecc_P8o) << 1) | ||
81 | #define P16e(a) (TF(a & NAND_Ecc_P16e) << 2) | ||
82 | #define P16o(a) (TF(a & NAND_Ecc_P16o) << 3) | ||
83 | #define P32e(a) (TF(a & NAND_Ecc_P32e) << 4) | ||
84 | #define P32o(a) (TF(a & NAND_Ecc_P32o) << 5) | ||
85 | #define P64e(a) (TF(a & NAND_Ecc_P64e) << 6) | ||
86 | #define P64o(a) (TF(a & NAND_Ecc_P64o) << 7) | ||
87 | |||
88 | #define P128e(a) (TF(a & NAND_Ecc_P128e) << 0) | ||
89 | #define P128o(a) (TF(a & NAND_Ecc_P128o) << 1) | ||
90 | #define P256e(a) (TF(a & NAND_Ecc_P256e) << 2) | ||
91 | #define P256o(a) (TF(a & NAND_Ecc_P256o) << 3) | ||
92 | #define P512e(a) (TF(a & NAND_Ecc_P512e) << 4) | ||
93 | #define P512o(a) (TF(a & NAND_Ecc_P512o) << 5) | ||
94 | #define P1024e(a) (TF(a & NAND_Ecc_P1024e) << 6) | ||
95 | #define P1024o(a) (TF(a & NAND_Ecc_P1024o) << 7) | ||
96 | |||
97 | #define P8e_s(a) (TF(a & NAND_Ecc_P8e) << 0) | ||
98 | #define P8o_s(a) (TF(a & NAND_Ecc_P8o) << 1) | ||
99 | #define P16e_s(a) (TF(a & NAND_Ecc_P16e) << 2) | ||
100 | #define P16o_s(a) (TF(a & NAND_Ecc_P16o) << 3) | ||
101 | #define P1e_s(a) (TF(a & NAND_Ecc_P1e) << 4) | ||
102 | #define P1o_s(a) (TF(a & NAND_Ecc_P1o) << 5) | ||
103 | #define P2e_s(a) (TF(a & NAND_Ecc_P2e) << 6) | ||
104 | #define P2o_s(a) (TF(a & NAND_Ecc_P2o) << 7) | ||
105 | |||
106 | #define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0) | ||
107 | #define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1) | ||
108 | |||
109 | #ifdef CONFIG_MTD_PARTITIONS | ||
110 | static const char *part_probes[] = { "cmdlinepart", NULL }; | ||
111 | #endif | ||
112 | |||
113 | struct omap_nand_info { | ||
114 | struct nand_hw_control controller; | ||
115 | struct omap_nand_platform_data *pdata; | ||
116 | struct mtd_info mtd; | ||
117 | struct mtd_partition *parts; | ||
118 | struct nand_chip nand; | ||
119 | struct platform_device *pdev; | ||
120 | |||
121 | int gpmc_cs; | ||
122 | unsigned long phys_base; | ||
123 | void __iomem *gpmc_cs_baseaddr; | ||
124 | void __iomem *gpmc_baseaddr; | ||
125 | }; | ||
126 | |||
127 | /** | ||
128 | * omap_nand_wp - This function enable or disable the Write Protect feature | ||
129 | * @mtd: MTD device structure | ||
130 | * @mode: WP ON/OFF | ||
131 | */ | ||
132 | static void omap_nand_wp(struct mtd_info *mtd, int mode) | ||
133 | { | ||
134 | struct omap_nand_info *info = container_of(mtd, | ||
135 | struct omap_nand_info, mtd); | ||
136 | |||
137 | unsigned long config = __raw_readl(info->gpmc_baseaddr + GPMC_CONFIG); | ||
138 | |||
139 | if (mode) | ||
140 | config &= ~(NAND_WP_BIT); /* WP is ON */ | ||
141 | else | ||
142 | config |= (NAND_WP_BIT); /* WP is OFF */ | ||
143 | |||
144 | __raw_writel(config, (info->gpmc_baseaddr + GPMC_CONFIG)); | ||
145 | } | ||
146 | |||
147 | /** | ||
148 | * omap_hwcontrol - hardware specific access to control-lines | ||
149 | * @mtd: MTD device structure | ||
150 | * @cmd: command to device | ||
151 | * @ctrl: | ||
152 | * NAND_NCE: bit 0 -> don't care | ||
153 | * NAND_CLE: bit 1 -> Command Latch | ||
154 | * NAND_ALE: bit 2 -> Address Latch | ||
155 | * | ||
156 | * NOTE: boards may use different bits for these!! | ||
157 | */ | ||
158 | static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) | ||
159 | { | ||
160 | struct omap_nand_info *info = container_of(mtd, | ||
161 | struct omap_nand_info, mtd); | ||
162 | switch (ctrl) { | ||
163 | case NAND_CTRL_CHANGE | NAND_CTRL_CLE: | ||
164 | info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr + | ||
165 | GPMC_CS_NAND_COMMAND; | ||
166 | info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr + | ||
167 | GPMC_CS_NAND_DATA; | ||
168 | break; | ||
169 | |||
170 | case NAND_CTRL_CHANGE | NAND_CTRL_ALE: | ||
171 | info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr + | ||
172 | GPMC_CS_NAND_ADDRESS; | ||
173 | info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr + | ||
174 | GPMC_CS_NAND_DATA; | ||
175 | break; | ||
176 | |||
177 | case NAND_CTRL_CHANGE | NAND_NCE: | ||
178 | info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr + | ||
179 | GPMC_CS_NAND_DATA; | ||
180 | info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr + | ||
181 | GPMC_CS_NAND_DATA; | ||
182 | break; | ||
183 | } | ||
184 | |||
185 | if (cmd != NAND_CMD_NONE) | ||
186 | __raw_writeb(cmd, info->nand.IO_ADDR_W); | ||
187 | } | ||
188 | |||
189 | /** | ||
190 | * omap_read_buf16 - read data from NAND controller into buffer | ||
191 | * @mtd: MTD device structure | ||
192 | * @buf: buffer to store date | ||
193 | * @len: number of bytes to read | ||
194 | */ | ||
195 | static void omap_read_buf16(struct mtd_info *mtd, u_char *buf, int len) | ||
196 | { | ||
197 | struct nand_chip *nand = mtd->priv; | ||
198 | |||
199 | __raw_readsw(nand->IO_ADDR_R, buf, len / 2); | ||
200 | } | ||
201 | |||
202 | /** | ||
203 | * omap_write_buf16 - write buffer to NAND controller | ||
204 | * @mtd: MTD device structure | ||
205 | * @buf: data buffer | ||
206 | * @len: number of bytes to write | ||
207 | */ | ||
208 | static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len) | ||
209 | { | ||
210 | struct omap_nand_info *info = container_of(mtd, | ||
211 | struct omap_nand_info, mtd); | ||
212 | u16 *p = (u16 *) buf; | ||
213 | |||
214 | /* FIXME try bursts of writesw() or DMA ... */ | ||
215 | len >>= 1; | ||
216 | |||
217 | while (len--) { | ||
218 | writew(*p++, info->nand.IO_ADDR_W); | ||
219 | |||
220 | while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr + | ||
221 | GPMC_STATUS) & GPMC_BUF_FULL)) | ||
222 | ; | ||
223 | } | ||
224 | } | ||
225 | /** | ||
226 | * omap_verify_buf - Verify chip data against buffer | ||
227 | * @mtd: MTD device structure | ||
228 | * @buf: buffer containing the data to compare | ||
229 | * @len: number of bytes to compare | ||
230 | */ | ||
231 | static int omap_verify_buf(struct mtd_info *mtd, const u_char * buf, int len) | ||
232 | { | ||
233 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | ||
234 | mtd); | ||
235 | u16 *p = (u16 *) buf; | ||
236 | |||
237 | len >>= 1; | ||
238 | while (len--) { | ||
239 | if (*p++ != cpu_to_le16(readw(info->nand.IO_ADDR_R))) | ||
240 | return -EFAULT; | ||
241 | } | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | #ifdef CONFIG_MTD_NAND_OMAP_HWECC | ||
247 | /** | ||
248 | * omap_hwecc_init - Initialize the HW ECC for NAND flash in GPMC controller | ||
249 | * @mtd: MTD device structure | ||
250 | */ | ||
251 | static void omap_hwecc_init(struct mtd_info *mtd) | ||
252 | { | ||
253 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | ||
254 | mtd); | ||
255 | struct nand_chip *chip = mtd->priv; | ||
256 | unsigned long val = 0x0; | ||
257 | |||
258 | /* Read from ECC Control Register */ | ||
259 | val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONTROL); | ||
260 | /* Clear all ECC | Enable Reg1 */ | ||
261 | val = ((0x00000001<<8) | 0x00000001); | ||
262 | __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONTROL); | ||
263 | |||
264 | /* Read from ECC Size Config Register */ | ||
265 | val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG); | ||
266 | /* ECCSIZE1=512 | Select eccResultsize[0-3] */ | ||
267 | val = ((((chip->ecc.size >> 1) - 1) << 22) | (0x0000000F)); | ||
268 | __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG); | ||
269 | } | ||
270 | |||
271 | /** | ||
272 | * gen_true_ecc - This function will generate true ECC value | ||
273 | * @ecc_buf: buffer to store ecc code | ||
274 | * | ||
275 | * This generated true ECC value can be used when correcting | ||
276 | * data read from NAND flash memory core | ||
277 | */ | ||
278 | static void gen_true_ecc(u8 *ecc_buf) | ||
279 | { | ||
280 | u32 tmp = ecc_buf[0] | (ecc_buf[1] << 16) | | ||
281 | ((ecc_buf[2] & 0xF0) << 20) | ((ecc_buf[2] & 0x0F) << 8); | ||
282 | |||
283 | ecc_buf[0] = ~(P64o(tmp) | P64e(tmp) | P32o(tmp) | P32e(tmp) | | ||
284 | P16o(tmp) | P16e(tmp) | P8o(tmp) | P8e(tmp)); | ||
285 | ecc_buf[1] = ~(P1024o(tmp) | P1024e(tmp) | P512o(tmp) | P512e(tmp) | | ||
286 | P256o(tmp) | P256e(tmp) | P128o(tmp) | P128e(tmp)); | ||
287 | ecc_buf[2] = ~(P4o(tmp) | P4e(tmp) | P2o(tmp) | P2e(tmp) | P1o(tmp) | | ||
288 | P1e(tmp) | P2048o(tmp) | P2048e(tmp)); | ||
289 | } | ||
290 | |||
291 | /** | ||
292 | * omap_compare_ecc - Detect (2 bits) and correct (1 bit) error in data | ||
293 | * @ecc_data1: ecc code from nand spare area | ||
294 | * @ecc_data2: ecc code from hardware register obtained from hardware ecc | ||
295 | * @page_data: page data | ||
296 | * | ||
297 | * This function compares two ECC's and indicates if there is an error. | ||
298 | * If the error can be corrected it will be corrected to the buffer. | ||
299 | */ | ||
300 | static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */ | ||
301 | u8 *ecc_data2, /* read from register */ | ||
302 | u8 *page_data) | ||
303 | { | ||
304 | uint i; | ||
305 | u8 tmp0_bit[8], tmp1_bit[8], tmp2_bit[8]; | ||
306 | u8 comp0_bit[8], comp1_bit[8], comp2_bit[8]; | ||
307 | u8 ecc_bit[24]; | ||
308 | u8 ecc_sum = 0; | ||
309 | u8 find_bit = 0; | ||
310 | uint find_byte = 0; | ||
311 | int isEccFF; | ||
312 | |||
313 | isEccFF = ((*(u32 *)ecc_data1 & 0xFFFFFF) == 0xFFFFFF); | ||
314 | |||
315 | gen_true_ecc(ecc_data1); | ||
316 | gen_true_ecc(ecc_data2); | ||
317 | |||
318 | for (i = 0; i <= 2; i++) { | ||
319 | *(ecc_data1 + i) = ~(*(ecc_data1 + i)); | ||
320 | *(ecc_data2 + i) = ~(*(ecc_data2 + i)); | ||
321 | } | ||
322 | |||
323 | for (i = 0; i < 8; i++) { | ||
324 | tmp0_bit[i] = *ecc_data1 % 2; | ||
325 | *ecc_data1 = *ecc_data1 / 2; | ||
326 | } | ||
327 | |||
328 | for (i = 0; i < 8; i++) { | ||
329 | tmp1_bit[i] = *(ecc_data1 + 1) % 2; | ||
330 | *(ecc_data1 + 1) = *(ecc_data1 + 1) / 2; | ||
331 | } | ||
332 | |||
333 | for (i = 0; i < 8; i++) { | ||
334 | tmp2_bit[i] = *(ecc_data1 + 2) % 2; | ||
335 | *(ecc_data1 + 2) = *(ecc_data1 + 2) / 2; | ||
336 | } | ||
337 | |||
338 | for (i = 0; i < 8; i++) { | ||
339 | comp0_bit[i] = *ecc_data2 % 2; | ||
340 | *ecc_data2 = *ecc_data2 / 2; | ||
341 | } | ||
342 | |||
343 | for (i = 0; i < 8; i++) { | ||
344 | comp1_bit[i] = *(ecc_data2 + 1) % 2; | ||
345 | *(ecc_data2 + 1) = *(ecc_data2 + 1) / 2; | ||
346 | } | ||
347 | |||
348 | for (i = 0; i < 8; i++) { | ||
349 | comp2_bit[i] = *(ecc_data2 + 2) % 2; | ||
350 | *(ecc_data2 + 2) = *(ecc_data2 + 2) / 2; | ||
351 | } | ||
352 | |||
353 | for (i = 0; i < 6; i++) | ||
354 | ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2]; | ||
355 | |||
356 | for (i = 0; i < 8; i++) | ||
357 | ecc_bit[i + 6] = tmp0_bit[i] ^ comp0_bit[i]; | ||
358 | |||
359 | for (i = 0; i < 8; i++) | ||
360 | ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i]; | ||
361 | |||
362 | ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0]; | ||
363 | ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1]; | ||
364 | |||
365 | for (i = 0; i < 24; i++) | ||
366 | ecc_sum += ecc_bit[i]; | ||
367 | |||
368 | switch (ecc_sum) { | ||
369 | case 0: | ||
370 | /* Not reached because this function is not called if | ||
371 | * ECC values are equal | ||
372 | */ | ||
373 | return 0; | ||
374 | |||
375 | case 1: | ||
376 | /* Uncorrectable error */ | ||
377 | DEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n"); | ||
378 | return -1; | ||
379 | |||
380 | case 11: | ||
381 | /* UN-Correctable error */ | ||
382 | DEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR B\n"); | ||
383 | return -1; | ||
384 | |||
385 | case 12: | ||
386 | /* Correctable error */ | ||
387 | find_byte = (ecc_bit[23] << 8) + | ||
388 | (ecc_bit[21] << 7) + | ||
389 | (ecc_bit[19] << 6) + | ||
390 | (ecc_bit[17] << 5) + | ||
391 | (ecc_bit[15] << 4) + | ||
392 | (ecc_bit[13] << 3) + | ||
393 | (ecc_bit[11] << 2) + | ||
394 | (ecc_bit[9] << 1) + | ||
395 | ecc_bit[7]; | ||
396 | |||
397 | find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1]; | ||
398 | |||
399 | DEBUG(MTD_DEBUG_LEVEL0, "Correcting single bit ECC error at " | ||
400 | "offset: %d, bit: %d\n", find_byte, find_bit); | ||
401 | |||
402 | page_data[find_byte] ^= (1 << find_bit); | ||
403 | |||
404 | return 0; | ||
405 | default: | ||
406 | if (isEccFF) { | ||
407 | if (ecc_data2[0] == 0 && | ||
408 | ecc_data2[1] == 0 && | ||
409 | ecc_data2[2] == 0) | ||
410 | return 0; | ||
411 | } | ||
412 | DEBUG(MTD_DEBUG_LEVEL0, "UNCORRECTED_ERROR default\n"); | ||
413 | return -1; | ||
414 | } | ||
415 | } | ||
416 | |||
417 | /** | ||
418 | * omap_correct_data - Compares the ECC read with HW generated ECC | ||
419 | * @mtd: MTD device structure | ||
420 | * @dat: page data | ||
421 | * @read_ecc: ecc read from nand flash | ||
422 | * @calc_ecc: ecc read from HW ECC registers | ||
423 | * | ||
424 | * Compares the ecc read from nand spare area with ECC registers values | ||
425 | * and if ECC's mismached, it will call 'omap_compare_ecc' for error detection | ||
426 | * and correction. | ||
427 | */ | ||
428 | static int omap_correct_data(struct mtd_info *mtd, u_char *dat, | ||
429 | u_char *read_ecc, u_char *calc_ecc) | ||
430 | { | ||
431 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | ||
432 | mtd); | ||
433 | int blockCnt = 0, i = 0, ret = 0; | ||
434 | |||
435 | /* Ex NAND_ECC_HW12_2048 */ | ||
436 | if ((info->nand.ecc.mode == NAND_ECC_HW) && | ||
437 | (info->nand.ecc.size == 2048)) | ||
438 | blockCnt = 4; | ||
439 | else | ||
440 | blockCnt = 1; | ||
441 | |||
442 | for (i = 0; i < blockCnt; i++) { | ||
443 | if (memcmp(read_ecc, calc_ecc, 3) != 0) { | ||
444 | ret = omap_compare_ecc(read_ecc, calc_ecc, dat); | ||
445 | if (ret < 0) | ||
446 | return ret; | ||
447 | } | ||
448 | read_ecc += 3; | ||
449 | calc_ecc += 3; | ||
450 | dat += 512; | ||
451 | } | ||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | /** | ||
456 | * omap_calcuate_ecc - Generate non-inverted ECC bytes. | ||
457 | * @mtd: MTD device structure | ||
458 | * @dat: The pointer to data on which ecc is computed | ||
459 | * @ecc_code: The ecc_code buffer | ||
460 | * | ||
461 | * Using noninverted ECC can be considered ugly since writing a blank | ||
462 | * page ie. padding will clear the ECC bytes. This is no problem as long | ||
463 | * nobody is trying to write data on the seemingly unused page. Reading | ||
464 | * an erased page will produce an ECC mismatch between generated and read | ||
465 | * ECC bytes that has to be dealt with separately. | ||
466 | */ | ||
467 | static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat, | ||
468 | u_char *ecc_code) | ||
469 | { | ||
470 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | ||
471 | mtd); | ||
472 | unsigned long val = 0x0; | ||
473 | unsigned long reg; | ||
474 | |||
475 | /* Start Reading from HW ECC1_Result = 0x200 */ | ||
476 | reg = (unsigned long)(info->gpmc_baseaddr + GPMC_ECC1_RESULT); | ||
477 | val = __raw_readl(reg); | ||
478 | *ecc_code++ = val; /* P128e, ..., P1e */ | ||
479 | *ecc_code++ = val >> 16; /* P128o, ..., P1o */ | ||
480 | /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */ | ||
481 | *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0); | ||
482 | reg += 4; | ||
483 | |||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | /** | ||
488 | * omap_enable_hwecc - This function enables the hardware ecc functionality | ||
489 | * @mtd: MTD device structure | ||
490 | * @mode: Read/Write mode | ||
491 | */ | ||
492 | static void omap_enable_hwecc(struct mtd_info *mtd, int mode) | ||
493 | { | ||
494 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | ||
495 | mtd); | ||
496 | struct nand_chip *chip = mtd->priv; | ||
497 | unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0; | ||
498 | unsigned long val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONFIG); | ||
499 | |||
500 | switch (mode) { | ||
501 | case NAND_ECC_READ: | ||
502 | __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL); | ||
503 | /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ | ||
504 | val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1); | ||
505 | break; | ||
506 | case NAND_ECC_READSYN: | ||
507 | __raw_writel(0x100, info->gpmc_baseaddr + GPMC_ECC_CONTROL); | ||
508 | /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ | ||
509 | val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1); | ||
510 | break; | ||
511 | case NAND_ECC_WRITE: | ||
512 | __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL); | ||
513 | /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ | ||
514 | val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1); | ||
515 | break; | ||
516 | default: | ||
517 | DEBUG(MTD_DEBUG_LEVEL0, "Error: Unrecognized Mode[%d]!\n", | ||
518 | mode); | ||
519 | break; | ||
520 | } | ||
521 | |||
522 | __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONFIG); | ||
523 | } | ||
524 | #endif | ||
525 | |||
526 | /** | ||
527 | * omap_wait - wait until the command is done | ||
528 | * @mtd: MTD device structure | ||
529 | * @chip: NAND Chip structure | ||
530 | * | ||
531 | * Wait function is called during Program and erase operations and | ||
532 | * the way it is called from MTD layer, we should wait till the NAND | ||
533 | * chip is ready after the programming/erase operation has completed. | ||
534 | * | ||
535 | * Erase can take up to 400ms and program up to 20ms according to | ||
536 | * general NAND and SmartMedia specs | ||
537 | */ | ||
538 | static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) | ||
539 | { | ||
540 | struct nand_chip *this = mtd->priv; | ||
541 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | ||
542 | mtd); | ||
543 | unsigned long timeo = jiffies; | ||
544 | int status, state = this->state; | ||
545 | |||
546 | if (state == FL_ERASING) | ||
547 | timeo += (HZ * 400) / 1000; | ||
548 | else | ||
549 | timeo += (HZ * 20) / 1000; | ||
550 | |||
551 | this->IO_ADDR_W = (void *) info->gpmc_cs_baseaddr + | ||
552 | GPMC_CS_NAND_COMMAND; | ||
553 | this->IO_ADDR_R = (void *) info->gpmc_cs_baseaddr + GPMC_CS_NAND_DATA; | ||
554 | |||
555 | __raw_writeb(NAND_CMD_STATUS & 0xFF, this->IO_ADDR_W); | ||
556 | |||
557 | while (time_before(jiffies, timeo)) { | ||
558 | status = __raw_readb(this->IO_ADDR_R); | ||
559 | if (!(status & 0x40)) | ||
560 | break; | ||
561 | } | ||
562 | return status; | ||
563 | } | ||
564 | |||
565 | /** | ||
566 | * omap_dev_ready - calls the platform specific dev_ready function | ||
567 | * @mtd: MTD device structure | ||
568 | */ | ||
569 | static int omap_dev_ready(struct mtd_info *mtd) | ||
570 | { | ||
571 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | ||
572 | mtd); | ||
573 | unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQ_STATUS); | ||
574 | |||
575 | if ((val & 0x100) == 0x100) { | ||
576 | /* Clear IRQ Interrupt */ | ||
577 | val |= 0x100; | ||
578 | val &= ~(0x0); | ||
579 | __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQ_STATUS); | ||
580 | } else { | ||
581 | unsigned int cnt = 0; | ||
582 | while (cnt++ < 0x1FF) { | ||
583 | if ((val & 0x100) == 0x100) | ||
584 | return 0; | ||
585 | val = __raw_readl(info->gpmc_baseaddr + | ||
586 | GPMC_IRQ_STATUS); | ||
587 | } | ||
588 | } | ||
589 | |||
590 | return 1; | ||
591 | } | ||
592 | |||
593 | static int __devinit omap_nand_probe(struct platform_device *pdev) | ||
594 | { | ||
595 | struct omap_nand_info *info; | ||
596 | struct omap_nand_platform_data *pdata; | ||
597 | int err; | ||
598 | unsigned long val; | ||
599 | |||
600 | |||
601 | pdata = pdev->dev.platform_data; | ||
602 | if (pdata == NULL) { | ||
603 | dev_err(&pdev->dev, "platform data missing\n"); | ||
604 | return -ENODEV; | ||
605 | } | ||
606 | |||
607 | info = kzalloc(sizeof(struct omap_nand_info), GFP_KERNEL); | ||
608 | if (!info) | ||
609 | return -ENOMEM; | ||
610 | |||
611 | platform_set_drvdata(pdev, info); | ||
612 | |||
613 | spin_lock_init(&info->controller.lock); | ||
614 | init_waitqueue_head(&info->controller.wq); | ||
615 | |||
616 | info->pdev = pdev; | ||
617 | |||
618 | info->gpmc_cs = pdata->cs; | ||
619 | info->gpmc_baseaddr = pdata->gpmc_baseaddr; | ||
620 | info->gpmc_cs_baseaddr = pdata->gpmc_cs_baseaddr; | ||
621 | |||
622 | info->mtd.priv = &info->nand; | ||
623 | info->mtd.name = dev_name(&pdev->dev); | ||
624 | info->mtd.owner = THIS_MODULE; | ||
625 | |||
626 | err = gpmc_cs_request(info->gpmc_cs, NAND_IO_SIZE, &info->phys_base); | ||
627 | if (err < 0) { | ||
628 | dev_err(&pdev->dev, "Cannot request GPMC CS\n"); | ||
629 | goto out_free_info; | ||
630 | } | ||
631 | |||
632 | /* Enable RD PIN Monitoring Reg */ | ||
633 | if (pdata->dev_ready) { | ||
634 | val = gpmc_cs_read_reg(info->gpmc_cs, GPMC_CS_CONFIG1); | ||
635 | val |= WR_RD_PIN_MONITORING; | ||
636 | gpmc_cs_write_reg(info->gpmc_cs, GPMC_CS_CONFIG1, val); | ||
637 | } | ||
638 | |||
639 | val = gpmc_cs_read_reg(info->gpmc_cs, GPMC_CS_CONFIG7); | ||
640 | val &= ~(0xf << 8); | ||
641 | val |= (0xc & 0xf) << 8; | ||
642 | gpmc_cs_write_reg(info->gpmc_cs, GPMC_CS_CONFIG7, val); | ||
643 | |||
644 | /* NAND write protect off */ | ||
645 | omap_nand_wp(&info->mtd, NAND_WP_OFF); | ||
646 | |||
647 | if (!request_mem_region(info->phys_base, NAND_IO_SIZE, | ||
648 | pdev->dev.driver->name)) { | ||
649 | err = -EBUSY; | ||
650 | goto out_free_cs; | ||
651 | } | ||
652 | |||
653 | info->nand.IO_ADDR_R = ioremap(info->phys_base, NAND_IO_SIZE); | ||
654 | if (!info->nand.IO_ADDR_R) { | ||
655 | err = -ENOMEM; | ||
656 | goto out_release_mem_region; | ||
657 | } | ||
658 | info->nand.controller = &info->controller; | ||
659 | |||
660 | info->nand.IO_ADDR_W = info->nand.IO_ADDR_R; | ||
661 | info->nand.cmd_ctrl = omap_hwcontrol; | ||
662 | |||
663 | /* REVISIT: only supports 16-bit NAND flash */ | ||
664 | |||
665 | info->nand.read_buf = omap_read_buf16; | ||
666 | info->nand.write_buf = omap_write_buf16; | ||
667 | info->nand.verify_buf = omap_verify_buf; | ||
668 | |||
669 | /* | ||
670 | * If RDY/BSY line is connected to OMAP then use the omap ready | ||
671 | * funcrtion and the generic nand_wait function which reads the status | ||
672 | * register after monitoring the RDY/BSY line.Otherwise use a standard | ||
673 | * chip delay which is slightly more than tR (AC Timing) of the NAND | ||
674 | * device and read status register until you get a failure or success | ||
675 | */ | ||
676 | if (pdata->dev_ready) { | ||
677 | info->nand.dev_ready = omap_dev_ready; | ||
678 | info->nand.chip_delay = 0; | ||
679 | } else { | ||
680 | info->nand.waitfunc = omap_wait; | ||
681 | info->nand.chip_delay = 50; | ||
682 | } | ||
683 | |||
684 | info->nand.options |= NAND_SKIP_BBTSCAN; | ||
685 | if ((gpmc_cs_read_reg(info->gpmc_cs, GPMC_CS_CONFIG1) & 0x3000) | ||
686 | == 0x1000) | ||
687 | info->nand.options |= NAND_BUSWIDTH_16; | ||
688 | |||
689 | #ifdef CONFIG_MTD_NAND_OMAP_HWECC | ||
690 | info->nand.ecc.bytes = 3; | ||
691 | info->nand.ecc.size = 512; | ||
692 | info->nand.ecc.calculate = omap_calculate_ecc; | ||
693 | info->nand.ecc.hwctl = omap_enable_hwecc; | ||
694 | info->nand.ecc.correct = omap_correct_data; | ||
695 | info->nand.ecc.mode = NAND_ECC_HW; | ||
696 | |||
697 | /* init HW ECC */ | ||
698 | omap_hwecc_init(&info->mtd); | ||
699 | #else | ||
700 | info->nand.ecc.mode = NAND_ECC_SOFT; | ||
701 | #endif | ||
702 | |||
703 | /* DIP switches on some boards change between 8 and 16 bit | ||
704 | * bus widths for flash. Try the other width if the first try fails. | ||
705 | */ | ||
706 | if (nand_scan(&info->mtd, 1)) { | ||
707 | info->nand.options ^= NAND_BUSWIDTH_16; | ||
708 | if (nand_scan(&info->mtd, 1)) { | ||
709 | err = -ENXIO; | ||
710 | goto out_release_mem_region; | ||
711 | } | ||
712 | } | ||
713 | |||
714 | #ifdef CONFIG_MTD_PARTITIONS | ||
715 | err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0); | ||
716 | if (err > 0) | ||
717 | add_mtd_partitions(&info->mtd, info->parts, err); | ||
718 | else if (pdata->parts) | ||
719 | add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts); | ||
720 | else | ||
721 | #endif | ||
722 | add_mtd_device(&info->mtd); | ||
723 | |||
724 | platform_set_drvdata(pdev, &info->mtd); | ||
725 | |||
726 | return 0; | ||
727 | |||
728 | out_release_mem_region: | ||
729 | release_mem_region(info->phys_base, NAND_IO_SIZE); | ||
730 | out_free_cs: | ||
731 | gpmc_cs_free(info->gpmc_cs); | ||
732 | out_free_info: | ||
733 | kfree(info); | ||
734 | |||
735 | return err; | ||
736 | } | ||
737 | |||
738 | static int omap_nand_remove(struct platform_device *pdev) | ||
739 | { | ||
740 | struct mtd_info *mtd = platform_get_drvdata(pdev); | ||
741 | struct omap_nand_info *info = mtd->priv; | ||
742 | |||
743 | platform_set_drvdata(pdev, NULL); | ||
744 | /* Release NAND device, its internal structures and partitions */ | ||
745 | nand_release(&info->mtd); | ||
746 | iounmap(info->nand.IO_ADDR_R); | ||
747 | kfree(&info->mtd); | ||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | static struct platform_driver omap_nand_driver = { | ||
752 | .probe = omap_nand_probe, | ||
753 | .remove = omap_nand_remove, | ||
754 | .driver = { | ||
755 | .name = DRIVER_NAME, | ||
756 | .owner = THIS_MODULE, | ||
757 | }, | ||
758 | }; | ||
759 | |||
760 | static int __init omap_nand_init(void) | ||
761 | { | ||
762 | printk(KERN_INFO "%s driver initializing\n", DRIVER_NAME); | ||
763 | return platform_driver_register(&omap_nand_driver); | ||
764 | } | ||
765 | |||
766 | static void __exit omap_nand_exit(void) | ||
767 | { | ||
768 | platform_driver_unregister(&omap_nand_driver); | ||
769 | } | ||
770 | |||
771 | module_init(omap_nand_init); | ||
772 | module_exit(omap_nand_exit); | ||
773 | |||
774 | MODULE_ALIAS(DRIVER_NAME); | ||
775 | MODULE_LICENSE("GPL"); | ||
776 | MODULE_DESCRIPTION("Glue layer for NAND flash on TI OMAP boards"); | ||
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index c2dfd3ea353d..7ad972229db4 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c | |||
@@ -47,6 +47,28 @@ static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl | |||
47 | writeb(cmd, nc->IO_ADDR_W + offs); | 47 | writeb(cmd, nc->IO_ADDR_W + offs); |
48 | } | 48 | } |
49 | 49 | ||
50 | static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | ||
51 | { | ||
52 | struct nand_chip *chip = mtd->priv; | ||
53 | void __iomem *io_base = chip->IO_ADDR_R; | ||
54 | uint64_t *buf64; | ||
55 | int i = 0; | ||
56 | |||
57 | while (len && (unsigned long)buf & 7) { | ||
58 | *buf++ = readb(io_base); | ||
59 | len--; | ||
60 | } | ||
61 | buf64 = (uint64_t *)buf; | ||
62 | while (i < len/8) { | ||
63 | uint64_t x; | ||
64 | asm ("ldrd\t%0, [%1]" : "=r" (x) : "r" (io_base)); | ||
65 | buf64[i++] = x; | ||
66 | } | ||
67 | i *= 8; | ||
68 | while (i < len) | ||
69 | buf[i++] = readb(io_base); | ||
70 | } | ||
71 | |||
50 | static int __init orion_nand_probe(struct platform_device *pdev) | 72 | static int __init orion_nand_probe(struct platform_device *pdev) |
51 | { | 73 | { |
52 | struct mtd_info *mtd; | 74 | struct mtd_info *mtd; |
@@ -83,6 +105,7 @@ static int __init orion_nand_probe(struct platform_device *pdev) | |||
83 | nc->priv = board; | 105 | nc->priv = board; |
84 | nc->IO_ADDR_R = nc->IO_ADDR_W = io_base; | 106 | nc->IO_ADDR_R = nc->IO_ADDR_W = io_base; |
85 | nc->cmd_ctrl = orion_nand_cmd_ctrl; | 107 | nc->cmd_ctrl = orion_nand_cmd_ctrl; |
108 | nc->read_buf = orion_nand_read_buf; | ||
86 | nc->ecc.mode = NAND_ECC_SOFT; | 109 | nc->ecc.mode = NAND_ECC_SOFT; |
87 | 110 | ||
88 | if (board->chip_delay) | 111 | if (board->chip_delay) |
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index 86e1d08eee00..4e16c6f5bdd5 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c | |||
@@ -61,6 +61,8 @@ static int __devinit plat_nand_probe(struct platform_device *pdev) | |||
61 | data->chip.cmd_ctrl = pdata->ctrl.cmd_ctrl; | 61 | data->chip.cmd_ctrl = pdata->ctrl.cmd_ctrl; |
62 | data->chip.dev_ready = pdata->ctrl.dev_ready; | 62 | data->chip.dev_ready = pdata->ctrl.dev_ready; |
63 | data->chip.select_chip = pdata->ctrl.select_chip; | 63 | data->chip.select_chip = pdata->ctrl.select_chip; |
64 | data->chip.write_buf = pdata->ctrl.write_buf; | ||
65 | data->chip.read_buf = pdata->ctrl.read_buf; | ||
64 | data->chip.chip_delay = pdata->chip.chip_delay; | 66 | data->chip.chip_delay = pdata->chip.chip_delay; |
65 | data->chip.options |= pdata->chip.options; | 67 | data->chip.options |= pdata->chip.options; |
66 | 68 | ||
@@ -70,6 +72,13 @@ static int __devinit plat_nand_probe(struct platform_device *pdev) | |||
70 | 72 | ||
71 | platform_set_drvdata(pdev, data); | 73 | platform_set_drvdata(pdev, data); |
72 | 74 | ||
75 | /* Handle any platform specific setup */ | ||
76 | if (pdata->ctrl.probe) { | ||
77 | res = pdata->ctrl.probe(pdev); | ||
78 | if (res) | ||
79 | goto out; | ||
80 | } | ||
81 | |||
73 | /* Scan to find existance of the device */ | 82 | /* Scan to find existance of the device */ |
74 | if (nand_scan(&data->mtd, 1)) { | 83 | if (nand_scan(&data->mtd, 1)) { |
75 | res = -ENXIO; | 84 | res = -ENXIO; |
@@ -86,6 +95,8 @@ static int __devinit plat_nand_probe(struct platform_device *pdev) | |||
86 | return 0; | 95 | return 0; |
87 | } | 96 | } |
88 | } | 97 | } |
98 | if (pdata->chip.set_parts) | ||
99 | pdata->chip.set_parts(data->mtd.size, &pdata->chip); | ||
89 | if (pdata->chip.partitions) { | 100 | if (pdata->chip.partitions) { |
90 | data->parts = pdata->chip.partitions; | 101 | data->parts = pdata->chip.partitions; |
91 | res = add_mtd_partitions(&data->mtd, data->parts, | 102 | res = add_mtd_partitions(&data->mtd, data->parts, |
@@ -99,6 +110,8 @@ static int __devinit plat_nand_probe(struct platform_device *pdev) | |||
99 | 110 | ||
100 | nand_release(&data->mtd); | 111 | nand_release(&data->mtd); |
101 | out: | 112 | out: |
113 | if (pdata->ctrl.remove) | ||
114 | pdata->ctrl.remove(pdev); | ||
102 | platform_set_drvdata(pdev, NULL); | 115 | platform_set_drvdata(pdev, NULL); |
103 | iounmap(data->io_base); | 116 | iounmap(data->io_base); |
104 | kfree(data); | 117 | kfree(data); |
@@ -111,15 +124,15 @@ out: | |||
111 | static int __devexit plat_nand_remove(struct platform_device *pdev) | 124 | static int __devexit plat_nand_remove(struct platform_device *pdev) |
112 | { | 125 | { |
113 | struct plat_nand_data *data = platform_get_drvdata(pdev); | 126 | struct plat_nand_data *data = platform_get_drvdata(pdev); |
114 | #ifdef CONFIG_MTD_PARTITIONS | ||
115 | struct platform_nand_data *pdata = pdev->dev.platform_data; | 127 | struct platform_nand_data *pdata = pdev->dev.platform_data; |
116 | #endif | ||
117 | 128 | ||
118 | nand_release(&data->mtd); | 129 | nand_release(&data->mtd); |
119 | #ifdef CONFIG_MTD_PARTITIONS | 130 | #ifdef CONFIG_MTD_PARTITIONS |
120 | if (data->parts && data->parts != pdata->chip.partitions) | 131 | if (data->parts && data->parts != pdata->chip.partitions) |
121 | kfree(data->parts); | 132 | kfree(data->parts); |
122 | #endif | 133 | #endif |
134 | if (pdata->ctrl.remove) | ||
135 | pdata->ctrl.remove(pdev); | ||
123 | iounmap(data->io_base); | 136 | iounmap(data->io_base); |
124 | kfree(data); | 137 | kfree(data); |
125 | 138 | ||
@@ -128,7 +141,7 @@ static int __devexit plat_nand_remove(struct platform_device *pdev) | |||
128 | 141 | ||
129 | static struct platform_driver plat_nand_driver = { | 142 | static struct platform_driver plat_nand_driver = { |
130 | .probe = plat_nand_probe, | 143 | .probe = plat_nand_probe, |
131 | .remove = plat_nand_remove, | 144 | .remove = __devexit_p(plat_nand_remove), |
132 | .driver = { | 145 | .driver = { |
133 | .name = "gen_nand", | 146 | .name = "gen_nand", |
134 | .owner = THIS_MODULE, | 147 | .owner = THIS_MODULE, |
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 8e375d5fe231..11dc7e69c4fb 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c | |||
@@ -74,6 +74,14 @@ static struct nand_ecclayout nand_hw_eccoob = { | |||
74 | 74 | ||
75 | struct s3c2410_nand_info; | 75 | struct s3c2410_nand_info; |
76 | 76 | ||
77 | /** | ||
78 | * struct s3c2410_nand_mtd - driver MTD structure | ||
79 | * @mtd: The MTD instance to pass to the MTD layer. | ||
80 | * @chip: The NAND chip information. | ||
81 | * @set: The platform information supplied for this set of NAND chips. | ||
82 | * @info: Link back to the hardware information. | ||
83 | * @scan_res: The result from calling nand_scan_ident(). | ||
84 | */ | ||
77 | struct s3c2410_nand_mtd { | 85 | struct s3c2410_nand_mtd { |
78 | struct mtd_info mtd; | 86 | struct mtd_info mtd; |
79 | struct nand_chip chip; | 87 | struct nand_chip chip; |
@@ -90,6 +98,21 @@ enum s3c_cpu_type { | |||
90 | 98 | ||
91 | /* overview of the s3c2410 nand state */ | 99 | /* overview of the s3c2410 nand state */ |
92 | 100 | ||
101 | /** | ||
102 | * struct s3c2410_nand_info - NAND controller state. | ||
103 | * @mtds: An array of MTD instances on this controoler. | ||
104 | * @platform: The platform data for this board. | ||
105 | * @device: The platform device we bound to. | ||
106 | * @area: The IO area resource that came from request_mem_region(). | ||
107 | * @clk: The clock resource for this controller. | ||
108 | * @regs: The area mapped for the hardware registers described by @area. | ||
109 | * @sel_reg: Pointer to the register controlling the NAND selection. | ||
110 | * @sel_bit: The bit in @sel_reg to select the NAND chip. | ||
111 | * @mtd_count: The number of MTDs created from this controller. | ||
112 | * @save_sel: The contents of @sel_reg to be saved over suspend. | ||
113 | * @clk_rate: The clock rate from @clk. | ||
114 | * @cpu_type: The exact type of this controller. | ||
115 | */ | ||
93 | struct s3c2410_nand_info { | 116 | struct s3c2410_nand_info { |
94 | /* mtd info */ | 117 | /* mtd info */ |
95 | struct nand_hw_control controller; | 118 | struct nand_hw_control controller; |
@@ -145,12 +168,19 @@ static inline int allow_clk_stop(struct s3c2410_nand_info *info) | |||
145 | 168 | ||
146 | #define NS_IN_KHZ 1000000 | 169 | #define NS_IN_KHZ 1000000 |
147 | 170 | ||
171 | /** | ||
172 | * s3c_nand_calc_rate - calculate timing data. | ||
173 | * @wanted: The cycle time in nanoseconds. | ||
174 | * @clk: The clock rate in kHz. | ||
175 | * @max: The maximum divider value. | ||
176 | * | ||
177 | * Calculate the timing value from the given parameters. | ||
178 | */ | ||
148 | static int s3c_nand_calc_rate(int wanted, unsigned long clk, int max) | 179 | static int s3c_nand_calc_rate(int wanted, unsigned long clk, int max) |
149 | { | 180 | { |
150 | int result; | 181 | int result; |
151 | 182 | ||
152 | result = (wanted * clk) / NS_IN_KHZ; | 183 | result = DIV_ROUND_UP((wanted * clk), NS_IN_KHZ); |
153 | result++; | ||
154 | 184 | ||
155 | pr_debug("result %d from %ld, %d\n", result, clk, wanted); | 185 | pr_debug("result %d from %ld, %d\n", result, clk, wanted); |
156 | 186 | ||
@@ -169,13 +199,21 @@ static int s3c_nand_calc_rate(int wanted, unsigned long clk, int max) | |||
169 | 199 | ||
170 | /* controller setup */ | 200 | /* controller setup */ |
171 | 201 | ||
202 | /** | ||
203 | * s3c2410_nand_setrate - setup controller timing information. | ||
204 | * @info: The controller instance. | ||
205 | * | ||
206 | * Given the information supplied by the platform, calculate and set | ||
207 | * the necessary timing registers in the hardware to generate the | ||
208 | * necessary timing cycles to the hardware. | ||
209 | */ | ||
172 | static int s3c2410_nand_setrate(struct s3c2410_nand_info *info) | 210 | static int s3c2410_nand_setrate(struct s3c2410_nand_info *info) |
173 | { | 211 | { |
174 | struct s3c2410_platform_nand *plat = info->platform; | 212 | struct s3c2410_platform_nand *plat = info->platform; |
175 | int tacls_max = (info->cpu_type == TYPE_S3C2412) ? 8 : 4; | 213 | int tacls_max = (info->cpu_type == TYPE_S3C2412) ? 8 : 4; |
176 | int tacls, twrph0, twrph1; | 214 | int tacls, twrph0, twrph1; |
177 | unsigned long clkrate = clk_get_rate(info->clk); | 215 | unsigned long clkrate = clk_get_rate(info->clk); |
178 | unsigned long set, cfg, mask; | 216 | unsigned long uninitialized_var(set), cfg, uninitialized_var(mask); |
179 | unsigned long flags; | 217 | unsigned long flags; |
180 | 218 | ||
181 | /* calculate the timing information for the controller */ | 219 | /* calculate the timing information for the controller */ |
@@ -215,9 +253,9 @@ static int s3c2410_nand_setrate(struct s3c2410_nand_info *info) | |||
215 | 253 | ||
216 | case TYPE_S3C2440: | 254 | case TYPE_S3C2440: |
217 | case TYPE_S3C2412: | 255 | case TYPE_S3C2412: |
218 | mask = (S3C2410_NFCONF_TACLS(tacls_max - 1) | | 256 | mask = (S3C2440_NFCONF_TACLS(tacls_max - 1) | |
219 | S3C2410_NFCONF_TWRPH0(7) | | 257 | S3C2440_NFCONF_TWRPH0(7) | |
220 | S3C2410_NFCONF_TWRPH1(7)); | 258 | S3C2440_NFCONF_TWRPH1(7)); |
221 | 259 | ||
222 | set = S3C2440_NFCONF_TACLS(tacls - 1); | 260 | set = S3C2440_NFCONF_TACLS(tacls - 1); |
223 | set |= S3C2440_NFCONF_TWRPH0(twrph0 - 1); | 261 | set |= S3C2440_NFCONF_TWRPH0(twrph0 - 1); |
@@ -225,14 +263,9 @@ static int s3c2410_nand_setrate(struct s3c2410_nand_info *info) | |||
225 | break; | 263 | break; |
226 | 264 | ||
227 | default: | 265 | default: |
228 | /* keep compiler happy */ | ||
229 | mask = 0; | ||
230 | set = 0; | ||
231 | BUG(); | 266 | BUG(); |
232 | } | 267 | } |
233 | 268 | ||
234 | dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg); | ||
235 | |||
236 | local_irq_save(flags); | 269 | local_irq_save(flags); |
237 | 270 | ||
238 | cfg = readl(info->regs + S3C2410_NFCONF); | 271 | cfg = readl(info->regs + S3C2410_NFCONF); |
@@ -242,9 +275,18 @@ static int s3c2410_nand_setrate(struct s3c2410_nand_info *info) | |||
242 | 275 | ||
243 | local_irq_restore(flags); | 276 | local_irq_restore(flags); |
244 | 277 | ||
278 | dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg); | ||
279 | |||
245 | return 0; | 280 | return 0; |
246 | } | 281 | } |
247 | 282 | ||
283 | /** | ||
284 | * s3c2410_nand_inithw - basic hardware initialisation | ||
285 | * @info: The hardware state. | ||
286 | * | ||
287 | * Do the basic initialisation of the hardware, using s3c2410_nand_setrate() | ||
288 | * to setup the hardware access speeds and set the controller to be enabled. | ||
289 | */ | ||
248 | static int s3c2410_nand_inithw(struct s3c2410_nand_info *info) | 290 | static int s3c2410_nand_inithw(struct s3c2410_nand_info *info) |
249 | { | 291 | { |
250 | int ret; | 292 | int ret; |
@@ -268,8 +310,19 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info) | |||
268 | return 0; | 310 | return 0; |
269 | } | 311 | } |
270 | 312 | ||
271 | /* select chip */ | 313 | /** |
272 | 314 | * s3c2410_nand_select_chip - select the given nand chip | |
315 | * @mtd: The MTD instance for this chip. | ||
316 | * @chip: The chip number. | ||
317 | * | ||
318 | * This is called by the MTD layer to either select a given chip for the | ||
319 | * @mtd instance, or to indicate that the access has finished and the | ||
320 | * chip can be de-selected. | ||
321 | * | ||
322 | * The routine ensures that the nFCE line is correctly setup, and any | ||
323 | * platform specific selection code is called to route nFCE to the specific | ||
324 | * chip. | ||
325 | */ | ||
273 | static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip) | 326 | static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip) |
274 | { | 327 | { |
275 | struct s3c2410_nand_info *info; | 328 | struct s3c2410_nand_info *info; |
@@ -530,7 +583,16 @@ static void s3c2410_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | |||
530 | static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | 583 | static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) |
531 | { | 584 | { |
532 | struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); | 585 | struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); |
533 | readsl(info->regs + S3C2440_NFDATA, buf, len / 4); | 586 | |
587 | readsl(info->regs + S3C2440_NFDATA, buf, len >> 2); | ||
588 | |||
589 | /* cleanup if we've got less than a word to do */ | ||
590 | if (len & 3) { | ||
591 | buf += len & ~3; | ||
592 | |||
593 | for (; len & 3; len--) | ||
594 | *buf++ = readb(info->regs + S3C2440_NFDATA); | ||
595 | } | ||
534 | } | 596 | } |
535 | 597 | ||
536 | static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | 598 | static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) |
@@ -542,7 +604,16 @@ static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int | |||
542 | static void s3c2440_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | 604 | static void s3c2440_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) |
543 | { | 605 | { |
544 | struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); | 606 | struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); |
545 | writesl(info->regs + S3C2440_NFDATA, buf, len / 4); | 607 | |
608 | writesl(info->regs + S3C2440_NFDATA, buf, len >> 2); | ||
609 | |||
610 | /* cleanup any fractional write */ | ||
611 | if (len & 3) { | ||
612 | buf += len & ~3; | ||
613 | |||
614 | for (; len & 3; len--, buf++) | ||
615 | writeb(*buf, info->regs + S3C2440_NFDATA); | ||
616 | } | ||
546 | } | 617 | } |
547 | 618 | ||
548 | /* cpufreq driver support */ | 619 | /* cpufreq driver support */ |
@@ -593,7 +664,7 @@ static inline void s3c2410_nand_cpufreq_deregister(struct s3c2410_nand_info *inf | |||
593 | 664 | ||
594 | /* device management functions */ | 665 | /* device management functions */ |
595 | 666 | ||
596 | static int s3c2410_nand_remove(struct platform_device *pdev) | 667 | static int s3c24xx_nand_remove(struct platform_device *pdev) |
597 | { | 668 | { |
598 | struct s3c2410_nand_info *info = to_nand_info(pdev); | 669 | struct s3c2410_nand_info *info = to_nand_info(pdev); |
599 | 670 | ||
@@ -645,17 +716,31 @@ static int s3c2410_nand_remove(struct platform_device *pdev) | |||
645 | } | 716 | } |
646 | 717 | ||
647 | #ifdef CONFIG_MTD_PARTITIONS | 718 | #ifdef CONFIG_MTD_PARTITIONS |
719 | const char *part_probes[] = { "cmdlinepart", NULL }; | ||
648 | static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, | 720 | static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, |
649 | struct s3c2410_nand_mtd *mtd, | 721 | struct s3c2410_nand_mtd *mtd, |
650 | struct s3c2410_nand_set *set) | 722 | struct s3c2410_nand_set *set) |
651 | { | 723 | { |
724 | struct mtd_partition *part_info; | ||
725 | int nr_part = 0; | ||
726 | |||
652 | if (set == NULL) | 727 | if (set == NULL) |
653 | return add_mtd_device(&mtd->mtd); | 728 | return add_mtd_device(&mtd->mtd); |
654 | 729 | ||
655 | if (set->nr_partitions > 0 && set->partitions != NULL) { | 730 | if (set->nr_partitions == 0) { |
656 | return add_mtd_partitions(&mtd->mtd, set->partitions, set->nr_partitions); | 731 | mtd->mtd.name = set->name; |
732 | nr_part = parse_mtd_partitions(&mtd->mtd, part_probes, | ||
733 | &part_info, 0); | ||
734 | } else { | ||
735 | if (set->nr_partitions > 0 && set->partitions != NULL) { | ||
736 | nr_part = set->nr_partitions; | ||
737 | part_info = set->partitions; | ||
738 | } | ||
657 | } | 739 | } |
658 | 740 | ||
741 | if (nr_part > 0 && part_info) | ||
742 | return add_mtd_partitions(&mtd->mtd, part_info, nr_part); | ||
743 | |||
659 | return add_mtd_device(&mtd->mtd); | 744 | return add_mtd_device(&mtd->mtd); |
660 | } | 745 | } |
661 | #else | 746 | #else |
@@ -667,11 +752,16 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, | |||
667 | } | 752 | } |
668 | #endif | 753 | #endif |
669 | 754 | ||
670 | /* s3c2410_nand_init_chip | 755 | /** |
756 | * s3c2410_nand_init_chip - initialise a single instance of an chip | ||
757 | * @info: The base NAND controller the chip is on. | ||
758 | * @nmtd: The new controller MTD instance to fill in. | ||
759 | * @set: The information passed from the board specific platform data. | ||
671 | * | 760 | * |
672 | * init a single instance of an chip | 761 | * Initialise the given @nmtd from the information in @info and @set. This |
673 | */ | 762 | * readies the structure for use with the MTD layer functions by ensuring |
674 | 763 | * all pointers are setup and the necessary control routines selected. | |
764 | */ | ||
675 | static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, | 765 | static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, |
676 | struct s3c2410_nand_mtd *nmtd, | 766 | struct s3c2410_nand_mtd *nmtd, |
677 | struct s3c2410_nand_set *set) | 767 | struct s3c2410_nand_set *set) |
@@ -757,14 +847,40 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, | |||
757 | 847 | ||
758 | if (set->disable_ecc) | 848 | if (set->disable_ecc) |
759 | chip->ecc.mode = NAND_ECC_NONE; | 849 | chip->ecc.mode = NAND_ECC_NONE; |
850 | |||
851 | switch (chip->ecc.mode) { | ||
852 | case NAND_ECC_NONE: | ||
853 | dev_info(info->device, "NAND ECC disabled\n"); | ||
854 | break; | ||
855 | case NAND_ECC_SOFT: | ||
856 | dev_info(info->device, "NAND soft ECC\n"); | ||
857 | break; | ||
858 | case NAND_ECC_HW: | ||
859 | dev_info(info->device, "NAND hardware ECC\n"); | ||
860 | break; | ||
861 | default: | ||
862 | dev_info(info->device, "NAND ECC UNKNOWN\n"); | ||
863 | break; | ||
864 | } | ||
865 | |||
866 | /* If you use u-boot BBT creation code, specifying this flag will | ||
867 | * let the kernel fish out the BBT from the NAND, and also skip the | ||
868 | * full NAND scan that can take 1/2s or so. Little things... */ | ||
869 | if (set->flash_bbt) | ||
870 | chip->options |= NAND_USE_FLASH_BBT | NAND_SKIP_BBTSCAN; | ||
760 | } | 871 | } |
761 | 872 | ||
762 | /* s3c2410_nand_update_chip | 873 | /** |
874 | * s3c2410_nand_update_chip - post probe update | ||
875 | * @info: The controller instance. | ||
876 | * @nmtd: The driver version of the MTD instance. | ||
763 | * | 877 | * |
764 | * post-probe chip update, to change any items, such as the | 878 | * This routine is called after the chip probe has succesfully completed |
765 | * layout for large page nand | 879 | * and the relevant per-chip information updated. This call ensure that |
766 | */ | 880 | * we update the internal state accordingly. |
767 | 881 | * | |
882 | * The internal state is currently limited to the ECC state information. | ||
883 | */ | ||
768 | static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info, | 884 | static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info, |
769 | struct s3c2410_nand_mtd *nmtd) | 885 | struct s3c2410_nand_mtd *nmtd) |
770 | { | 886 | { |
@@ -773,33 +889,33 @@ static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info, | |||
773 | dev_dbg(info->device, "chip %p => page shift %d\n", | 889 | dev_dbg(info->device, "chip %p => page shift %d\n", |
774 | chip, chip->page_shift); | 890 | chip, chip->page_shift); |
775 | 891 | ||
776 | if (hardware_ecc) { | 892 | if (chip->ecc.mode != NAND_ECC_HW) |
893 | return; | ||
894 | |||
777 | /* change the behaviour depending on wether we are using | 895 | /* change the behaviour depending on wether we are using |
778 | * the large or small page nand device */ | 896 | * the large or small page nand device */ |
779 | 897 | ||
780 | if (chip->page_shift > 10) { | 898 | if (chip->page_shift > 10) { |
781 | chip->ecc.size = 256; | 899 | chip->ecc.size = 256; |
782 | chip->ecc.bytes = 3; | 900 | chip->ecc.bytes = 3; |
783 | } else { | 901 | } else { |
784 | chip->ecc.size = 512; | 902 | chip->ecc.size = 512; |
785 | chip->ecc.bytes = 3; | 903 | chip->ecc.bytes = 3; |
786 | chip->ecc.layout = &nand_hw_eccoob; | 904 | chip->ecc.layout = &nand_hw_eccoob; |
787 | } | ||
788 | } | 905 | } |
789 | } | 906 | } |
790 | 907 | ||
791 | /* s3c2410_nand_probe | 908 | /* s3c24xx_nand_probe |
792 | * | 909 | * |
793 | * called by device layer when it finds a device matching | 910 | * called by device layer when it finds a device matching |
794 | * one our driver can handled. This code checks to see if | 911 | * one our driver can handled. This code checks to see if |
795 | * it can allocate all necessary resources then calls the | 912 | * it can allocate all necessary resources then calls the |
796 | * nand layer to look for devices | 913 | * nand layer to look for devices |
797 | */ | 914 | */ |
798 | 915 | static int s3c24xx_nand_probe(struct platform_device *pdev) | |
799 | static int s3c24xx_nand_probe(struct platform_device *pdev, | ||
800 | enum s3c_cpu_type cpu_type) | ||
801 | { | 916 | { |
802 | struct s3c2410_platform_nand *plat = to_nand_plat(pdev); | 917 | struct s3c2410_platform_nand *plat = to_nand_plat(pdev); |
918 | enum s3c_cpu_type cpu_type; | ||
803 | struct s3c2410_nand_info *info; | 919 | struct s3c2410_nand_info *info; |
804 | struct s3c2410_nand_mtd *nmtd; | 920 | struct s3c2410_nand_mtd *nmtd; |
805 | struct s3c2410_nand_set *sets; | 921 | struct s3c2410_nand_set *sets; |
@@ -809,6 +925,8 @@ static int s3c24xx_nand_probe(struct platform_device *pdev, | |||
809 | int nr_sets; | 925 | int nr_sets; |
810 | int setno; | 926 | int setno; |
811 | 927 | ||
928 | cpu_type = platform_get_device_id(pdev)->driver_data; | ||
929 | |||
812 | pr_debug("s3c2410_nand_probe(%p)\n", pdev); | 930 | pr_debug("s3c2410_nand_probe(%p)\n", pdev); |
813 | 931 | ||
814 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 932 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
@@ -922,7 +1040,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev, | |||
922 | return 0; | 1040 | return 0; |
923 | 1041 | ||
924 | exit_error: | 1042 | exit_error: |
925 | s3c2410_nand_remove(pdev); | 1043 | s3c24xx_nand_remove(pdev); |
926 | 1044 | ||
927 | if (err == 0) | 1045 | if (err == 0) |
928 | err = -EINVAL; | 1046 | err = -EINVAL; |
@@ -983,50 +1101,33 @@ static int s3c24xx_nand_resume(struct platform_device *dev) | |||
983 | 1101 | ||
984 | /* driver device registration */ | 1102 | /* driver device registration */ |
985 | 1103 | ||
986 | static int s3c2410_nand_probe(struct platform_device *dev) | 1104 | static struct platform_device_id s3c24xx_driver_ids[] = { |
987 | { | 1105 | { |
988 | return s3c24xx_nand_probe(dev, TYPE_S3C2410); | 1106 | .name = "s3c2410-nand", |
989 | } | 1107 | .driver_data = TYPE_S3C2410, |
990 | 1108 | }, { | |
991 | static int s3c2440_nand_probe(struct platform_device *dev) | 1109 | .name = "s3c2440-nand", |
992 | { | 1110 | .driver_data = TYPE_S3C2440, |
993 | return s3c24xx_nand_probe(dev, TYPE_S3C2440); | 1111 | }, { |
994 | } | 1112 | .name = "s3c2412-nand", |
995 | 1113 | .driver_data = TYPE_S3C2412, | |
996 | static int s3c2412_nand_probe(struct platform_device *dev) | 1114 | }, { |
997 | { | 1115 | .name = "s3c6400-nand", |
998 | return s3c24xx_nand_probe(dev, TYPE_S3C2412); | 1116 | .driver_data = TYPE_S3C2412, /* compatible with 2412 */ |
999 | } | ||
1000 | |||
1001 | static struct platform_driver s3c2410_nand_driver = { | ||
1002 | .probe = s3c2410_nand_probe, | ||
1003 | .remove = s3c2410_nand_remove, | ||
1004 | .suspend = s3c24xx_nand_suspend, | ||
1005 | .resume = s3c24xx_nand_resume, | ||
1006 | .driver = { | ||
1007 | .name = "s3c2410-nand", | ||
1008 | .owner = THIS_MODULE, | ||
1009 | }, | 1117 | }, |
1118 | { } | ||
1010 | }; | 1119 | }; |
1011 | 1120 | ||
1012 | static struct platform_driver s3c2440_nand_driver = { | 1121 | MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids); |
1013 | .probe = s3c2440_nand_probe, | ||
1014 | .remove = s3c2410_nand_remove, | ||
1015 | .suspend = s3c24xx_nand_suspend, | ||
1016 | .resume = s3c24xx_nand_resume, | ||
1017 | .driver = { | ||
1018 | .name = "s3c2440-nand", | ||
1019 | .owner = THIS_MODULE, | ||
1020 | }, | ||
1021 | }; | ||
1022 | 1122 | ||
1023 | static struct platform_driver s3c2412_nand_driver = { | 1123 | static struct platform_driver s3c24xx_nand_driver = { |
1024 | .probe = s3c2412_nand_probe, | 1124 | .probe = s3c24xx_nand_probe, |
1025 | .remove = s3c2410_nand_remove, | 1125 | .remove = s3c24xx_nand_remove, |
1026 | .suspend = s3c24xx_nand_suspend, | 1126 | .suspend = s3c24xx_nand_suspend, |
1027 | .resume = s3c24xx_nand_resume, | 1127 | .resume = s3c24xx_nand_resume, |
1128 | .id_table = s3c24xx_driver_ids, | ||
1028 | .driver = { | 1129 | .driver = { |
1029 | .name = "s3c2412-nand", | 1130 | .name = "s3c24xx-nand", |
1030 | .owner = THIS_MODULE, | 1131 | .owner = THIS_MODULE, |
1031 | }, | 1132 | }, |
1032 | }; | 1133 | }; |
@@ -1035,16 +1136,12 @@ static int __init s3c2410_nand_init(void) | |||
1035 | { | 1136 | { |
1036 | printk("S3C24XX NAND Driver, (c) 2004 Simtec Electronics\n"); | 1137 | printk("S3C24XX NAND Driver, (c) 2004 Simtec Electronics\n"); |
1037 | 1138 | ||
1038 | platform_driver_register(&s3c2412_nand_driver); | 1139 | return platform_driver_register(&s3c24xx_nand_driver); |
1039 | platform_driver_register(&s3c2440_nand_driver); | ||
1040 | return platform_driver_register(&s3c2410_nand_driver); | ||
1041 | } | 1140 | } |
1042 | 1141 | ||
1043 | static void __exit s3c2410_nand_exit(void) | 1142 | static void __exit s3c2410_nand_exit(void) |
1044 | { | 1143 | { |
1045 | platform_driver_unregister(&s3c2412_nand_driver); | 1144 | platform_driver_unregister(&s3c24xx_nand_driver); |
1046 | platform_driver_unregister(&s3c2440_nand_driver); | ||
1047 | platform_driver_unregister(&s3c2410_nand_driver); | ||
1048 | } | 1145 | } |
1049 | 1146 | ||
1050 | module_init(s3c2410_nand_init); | 1147 | module_init(s3c2410_nand_init); |
@@ -1053,6 +1150,3 @@ module_exit(s3c2410_nand_exit); | |||
1053 | MODULE_LICENSE("GPL"); | 1150 | MODULE_LICENSE("GPL"); |
1054 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | 1151 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); |
1055 | MODULE_DESCRIPTION("S3C24XX MTD NAND driver"); | 1152 | MODULE_DESCRIPTION("S3C24XX MTD NAND driver"); |
1056 | MODULE_ALIAS("platform:s3c2410-nand"); | ||
1057 | MODULE_ALIAS("platform:s3c2412-nand"); | ||
1058 | MODULE_ALIAS("platform:s3c2440-nand"); | ||
diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c index 812479264896..488088eff2ca 100644 --- a/drivers/mtd/nand/txx9ndfmc.c +++ b/drivers/mtd/nand/txx9ndfmc.c | |||
@@ -64,7 +64,7 @@ struct txx9ndfmc_priv { | |||
64 | struct nand_chip chip; | 64 | struct nand_chip chip; |
65 | struct mtd_info mtd; | 65 | struct mtd_info mtd; |
66 | int cs; | 66 | int cs; |
67 | char mtdname[BUS_ID_SIZE + 2]; | 67 | const char *mtdname; |
68 | }; | 68 | }; |
69 | 69 | ||
70 | #define MAX_TXX9NDFMC_DEV 4 | 70 | #define MAX_TXX9NDFMC_DEV 4 |
@@ -334,16 +334,23 @@ static int __init txx9ndfmc_probe(struct platform_device *dev) | |||
334 | 334 | ||
335 | if (plat->ch_mask != 1) { | 335 | if (plat->ch_mask != 1) { |
336 | txx9_priv->cs = i; | 336 | txx9_priv->cs = i; |
337 | sprintf(txx9_priv->mtdname, "%s.%u", | 337 | txx9_priv->mtdname = kasprintf(GFP_KERNEL, "%s.%u", |
338 | dev_name(&dev->dev), i); | 338 | dev_name(&dev->dev), i); |
339 | } else { | 339 | } else { |
340 | txx9_priv->cs = -1; | 340 | txx9_priv->cs = -1; |
341 | strcpy(txx9_priv->mtdname, dev_name(&dev->dev)); | 341 | txx9_priv->mtdname = kstrdup(dev_name(&dev->dev), |
342 | GFP_KERNEL); | ||
343 | } | ||
344 | if (!txx9_priv->mtdname) { | ||
345 | kfree(txx9_priv); | ||
346 | dev_err(&dev->dev, "Unable to allocate MTD name.\n"); | ||
347 | continue; | ||
342 | } | 348 | } |
343 | if (plat->wide_mask & (1 << i)) | 349 | if (plat->wide_mask & (1 << i)) |
344 | chip->options |= NAND_BUSWIDTH_16; | 350 | chip->options |= NAND_BUSWIDTH_16; |
345 | 351 | ||
346 | if (nand_scan(mtd, 1)) { | 352 | if (nand_scan(mtd, 1)) { |
353 | kfree(txx9_priv->mtdname); | ||
347 | kfree(txx9_priv); | 354 | kfree(txx9_priv); |
348 | continue; | 355 | continue; |
349 | } | 356 | } |
@@ -385,6 +392,7 @@ static int __exit txx9ndfmc_remove(struct platform_device *dev) | |||
385 | kfree(drvdata->parts[i]); | 392 | kfree(drvdata->parts[i]); |
386 | #endif | 393 | #endif |
387 | del_mtd_device(mtd); | 394 | del_mtd_device(mtd); |
395 | kfree(txx9_priv->mtdname); | ||
388 | kfree(txx9_priv); | 396 | kfree(txx9_priv); |
389 | } | 397 | } |
390 | return 0; | 398 | return 0; |