diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mtd/nand/Kconfig | 14 | ||||
-rw-r--r-- | drivers/mtd/nand/Makefile | 1 | ||||
-rw-r--r-- | drivers/mtd/nand/ams-delta.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/au1550nd.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/autcpu12.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/cs553x_nand.c | 12 | ||||
-rw-r--r-- | drivers/mtd/nand/diskonchip.c | 10 | ||||
-rw-r--r-- | drivers/mtd/nand/h1910.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 774 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_ecc.c | 222 | ||||
-rw-r--r-- | drivers/mtd/nand/nandsim.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/ndfc.c | 319 | ||||
-rw-r--r-- | drivers/mtd/nand/ppchameleonevb.c | 4 | ||||
-rw-r--r-- | drivers/mtd/nand/rtc_from4.c | 12 | ||||
-rw-r--r-- | drivers/mtd/nand/s3c2410.c | 16 | ||||
-rw-r--r-- | drivers/mtd/nand/sharpsl.c | 10 | ||||
-rw-r--r-- | drivers/mtd/nand/toto.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/ts7250.c | 2 |
18 files changed, 870 insertions, 538 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 2d0ebad55a49..c2cb87fc4cb8 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -23,6 +23,14 @@ config MTD_NAND_VERIFY_WRITE | |||
23 | device thinks the write was successful, a bit could have been | 23 | device thinks the write was successful, a bit could have been |
24 | flipped accidentaly due to device wear or something else. | 24 | flipped accidentaly due to device wear or something else. |
25 | 25 | ||
26 | config MTD_NAND_ECC_SMC | ||
27 | bool "NAND ECC Smart Media byte order" | ||
28 | depends on MTD_NAND | ||
29 | default n | ||
30 | help | ||
31 | Software ECC according to the Smart Media Specification. | ||
32 | The original Linux implementation had byte 0 and 1 swapped. | ||
33 | |||
26 | config MTD_NAND_AUTCPU12 | 34 | config MTD_NAND_AUTCPU12 |
27 | tristate "SmartMediaCard on autronix autcpu12 board" | 35 | tristate "SmartMediaCard on autronix autcpu12 board" |
28 | depends on MTD_NAND && ARCH_AUTCPU12 | 36 | depends on MTD_NAND && ARCH_AUTCPU12 |
@@ -121,6 +129,12 @@ config MTD_NAND_S3C2410_HWECC | |||
121 | currently not be able to switch to software, as there is no | 129 | currently not be able to switch to software, as there is no |
122 | implementation for ECC method used by the S3C2410 | 130 | implementation for ECC method used by the S3C2410 |
123 | 131 | ||
132 | config MTD_NAND_NDFC | ||
133 | tristate "NDFC NanD Flash Controller" | ||
134 | depends on MTD_NAND && 44x | ||
135 | help | ||
136 | NDFC Nand Flash Controllers are integrated in EP44x SoCs | ||
137 | |||
124 | config MTD_NAND_DISKONCHIP | 138 | config MTD_NAND_DISKONCHIP |
125 | tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)" | 139 | tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)" |
126 | depends on MTD_NAND && EXPERIMENTAL | 140 | depends on MTD_NAND && EXPERIMENTAL |
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 33475087dbff..f74759351c91 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile | |||
@@ -21,5 +21,6 @@ obj-$(CONFIG_MTD_NAND_SHARPSL) += sharpsl.o | |||
21 | obj-$(CONFIG_MTD_NAND_TS7250) += ts7250.o | 21 | obj-$(CONFIG_MTD_NAND_TS7250) += ts7250.o |
22 | obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o | 22 | obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o |
23 | obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o | 23 | obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o |
24 | obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o | ||
24 | 25 | ||
25 | nand-objs = nand_base.o nand_bbt.o | 26 | nand-objs = nand_base.o nand_bbt.o |
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index 5a349eb316f5..aeaf2dece095 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c | |||
@@ -192,7 +192,7 @@ static int __init ams_delta_init(void) | |||
192 | } | 192 | } |
193 | /* 25 us command delay time */ | 193 | /* 25 us command delay time */ |
194 | this->chip_delay = 30; | 194 | this->chip_delay = 30; |
195 | this->eccmode = NAND_ECC_SOFT; | 195 | this->ecc.mode = NAND_ECC_SOFT; |
196 | 196 | ||
197 | /* Set chip enabled, but */ | 197 | /* Set chip enabled, but */ |
198 | ams_delta_latch2_write(NAND_MASK, AMS_DELTA_LATCH2_NAND_NRE | | 198 | ams_delta_latch2_write(NAND_MASK, AMS_DELTA_LATCH2_NAND_NRE | |
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 4253b9309789..29dde7dcafa1 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c | |||
@@ -578,7 +578,7 @@ static int __init au1xxx_nand_init(void) | |||
578 | 578 | ||
579 | /* 30 us command delay time */ | 579 | /* 30 us command delay time */ |
580 | this->chip_delay = 30; | 580 | this->chip_delay = 30; |
581 | this->eccmode = NAND_ECC_SOFT; | 581 | this->ecc.mode = NAND_ECC_SOFT; |
582 | 582 | ||
583 | this->options = NAND_NO_AUTOINCR; | 583 | this->options = NAND_NO_AUTOINCR; |
584 | 584 | ||
diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c index 43b296040d7f..dbb1b6267ade 100644 --- a/drivers/mtd/nand/autcpu12.c +++ b/drivers/mtd/nand/autcpu12.c | |||
@@ -163,7 +163,7 @@ static int __init autcpu12_init(void) | |||
163 | this->dev_ready = autcpu12_device_ready; | 163 | this->dev_ready = autcpu12_device_ready; |
164 | /* 20 us command delay time */ | 164 | /* 20 us command delay time */ |
165 | this->chip_delay = 20; | 165 | this->chip_delay = 20; |
166 | this->eccmode = NAND_ECC_SOFT; | 166 | this->ecc.mode = NAND_ECC_SOFT; |
167 | 167 | ||
168 | /* Enable the following for a flash based bad block table */ | 168 | /* Enable the following for a flash based bad block table */ |
169 | /* | 169 | /* |
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c index bf251253ea1f..064f3feadf53 100644 --- a/drivers/mtd/nand/cs553x_nand.c +++ b/drivers/mtd/nand/cs553x_nand.c | |||
@@ -242,11 +242,13 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) | |||
242 | 242 | ||
243 | this->chip_delay = 0; | 243 | this->chip_delay = 0; |
244 | 244 | ||
245 | this->eccmode = NAND_ECC_HW3_256; | 245 | this->ecc.mode = NAND_ECC_HW; |
246 | this->enable_hwecc = cs_enable_hwecc; | 246 | this->ecc.size = 256; |
247 | this->calculate_ecc = cs_calculate_ecc; | 247 | this->ecc.bytes = 3; |
248 | this->correct_data = nand_correct_data; | 248 | this->ecc.hwctl = cs_enable_hwecc; |
249 | 249 | this->ecc.calculate = cs_calculate_ecc; | |
250 | this->ecc.correct = nand_correct_data; | ||
251 | |||
250 | /* Enable the following for a flash based bad block table */ | 252 | /* Enable the following for a flash based bad block table */ |
251 | this->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR; | 253 | this->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR; |
252 | 254 | ||
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index d160930276d6..b771608ef84e 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c | |||
@@ -1674,12 +1674,14 @@ static int __init doc_probe(unsigned long physadr) | |||
1674 | nand->dev_ready = doc200x_dev_ready; | 1674 | nand->dev_ready = doc200x_dev_ready; |
1675 | nand->waitfunc = doc200x_wait; | 1675 | nand->waitfunc = doc200x_wait; |
1676 | nand->block_bad = doc200x_block_bad; | 1676 | nand->block_bad = doc200x_block_bad; |
1677 | nand->enable_hwecc = doc200x_enable_hwecc; | 1677 | nand->ecc.hwctl = doc200x_enable_hwecc; |
1678 | nand->calculate_ecc = doc200x_calculate_ecc; | 1678 | nand->ecc.calculate = doc200x_calculate_ecc; |
1679 | nand->correct_data = doc200x_correct_data; | 1679 | nand->ecc.correct = doc200x_correct_data; |
1680 | 1680 | ||
1681 | nand->autooob = &doc200x_oobinfo; | 1681 | nand->autooob = &doc200x_oobinfo; |
1682 | nand->eccmode = NAND_ECC_HW6_512; | 1682 | nand->ecc.mode = NAND_ECC_HW_SYNDROME; |
1683 | nand->ecc.size = 512; | ||
1684 | nand->ecc.bytes = 6; | ||
1683 | nand->options = NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME; | 1685 | nand->options = NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME; |
1684 | 1686 | ||
1685 | doc->physadr = physadr; | 1687 | doc->physadr = physadr; |
diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c index 9848eb09b884..06e91fa11b34 100644 --- a/drivers/mtd/nand/h1910.c +++ b/drivers/mtd/nand/h1910.c | |||
@@ -149,7 +149,7 @@ static int __init h1910_init(void) | |||
149 | this->dev_ready = NULL; /* unknown whether that was correct or not so we will just do it like this */ | 149 | this->dev_ready = NULL; /* unknown whether that was correct or not so we will just do it like this */ |
150 | /* 15 us command delay time */ | 150 | /* 15 us command delay time */ |
151 | this->chip_delay = 50; | 151 | this->chip_delay = 50; |
152 | this->eccmode = NAND_ECC_SOFT; | 152 | this->ecc.mode = NAND_ECC_SOFT; |
153 | this->options = NAND_NO_AUTOINCR; | 153 | this->options = NAND_NO_AUTOINCR; |
154 | 154 | ||
155 | /* Scan to find existence of the device */ | 155 | /* Scan to find existence of the device */ |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index cd90a46bf56a..778535006c83 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -10,7 +10,7 @@ | |||
10 | * http://www.linux-mtd.infradead.org/tech/nand.html | 10 | * http://www.linux-mtd.infradead.org/tech/nand.html |
11 | * | 11 | * |
12 | * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) | 12 | * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) |
13 | * 2002 Thomas Gleixner (tglx@linutronix.de) | 13 | * 2002 Thomas Gleixner (tglx@linutronix.de) |
14 | * | 14 | * |
15 | * 02-08-2004 tglx: support for strange chips, which cannot auto increment | 15 | * 02-08-2004 tglx: support for strange chips, which cannot auto increment |
16 | * pages on read / read_oob | 16 | * pages on read / read_oob |
@@ -25,26 +25,30 @@ | |||
25 | * 05-19-2004 tglx: Basic support for Renesas AG-AND chips | 25 | * 05-19-2004 tglx: Basic support for Renesas AG-AND chips |
26 | * | 26 | * |
27 | * 09-24-2004 tglx: add support for hardware controllers (e.g. ECC) shared | 27 | * 09-24-2004 tglx: add support for hardware controllers (e.g. ECC) shared |
28 | * among multiple independend devices. Suggestions and initial patch | 28 | * among multiple independend devices. Suggestions and initial |
29 | * from Ben Dooks <ben-mtd@fluff.org> | 29 | * patch from Ben Dooks <ben-mtd@fluff.org> |
30 | * | 30 | * |
31 | * 12-05-2004 dmarlin: add workaround for Renesas AG-AND chips "disturb" issue. | 31 | * 12-05-2004 dmarlin: add workaround for Renesas AG-AND chips "disturb" |
32 | * Basically, any block not rewritten may lose data when surrounding blocks | 32 | * issue. Basically, any block not rewritten may lose data when |
33 | * are rewritten many times. JFFS2 ensures this doesn't happen for blocks | 33 | * surrounding blocks are rewritten many times. JFFS2 ensures |
34 | * it uses, but the Bad Block Table(s) may not be rewritten. To ensure they | 34 | * this doesn't happen for blocks it uses, but the Bad Block |
35 | * do not lose data, force them to be rewritten when some of the surrounding | 35 | * Table(s) may not be rewritten. To ensure they do not lose |
36 | * blocks are erased. Rather than tracking a specific nearby block (which | 36 | * data, force them to be rewritten when some of the surrounding |
37 | * could itself go bad), use a page address 'mask' to select several blocks | 37 | * blocks are erased. Rather than tracking a specific nearby |
38 | * in the same area, and rewrite the BBT when any of them are erased. | 38 | * block (which could itself go bad), use a page address 'mask' to |
39 | * | 39 | * select several blocks in the same area, and rewrite the BBT |
40 | * 01-03-2005 dmarlin: added support for the device recovery command sequence for Renesas | 40 | * when any of them are erased. |
41 | * AG-AND chips. If there was a sudden loss of power during an erase operation, | 41 | * |
42 | * a "device recovery" operation must be performed when power is restored | 42 | * 01-03-2005 dmarlin: added support for the device recovery command sequence |
43 | * to ensure correct operation. | 43 | * for Renesas AG-AND chips. If there was a sudden loss of power |
44 | * | 44 | * during an erase operation, a "device recovery" operation must |
45 | * 01-20-2005 dmarlin: added support for optional hardware specific callback routine to | 45 | * be performed when power is restored to ensure correct |
46 | * perform extra error status checks on erase and write failures. This required | 46 | * operation. |
47 | * adding a wrapper function for nand_read_ecc. | 47 | * |
48 | * 01-20-2005 dmarlin: added support for optional hardware specific callback | ||
49 | * routine to perform extra error status checks on erase and write | ||
50 | * failures. This required adding a wrapper function for | ||
51 | * nand_read_ecc. | ||
48 | * | 52 | * |
49 | * 08-20-2005 vwool: suspend/resume added | 53 | * 08-20-2005 vwool: suspend/resume added |
50 | * | 54 | * |
@@ -72,6 +76,7 @@ | |||
72 | #include <linux/module.h> | 76 | #include <linux/module.h> |
73 | #include <linux/delay.h> | 77 | #include <linux/delay.h> |
74 | #include <linux/errno.h> | 78 | #include <linux/errno.h> |
79 | #include <linux/err.h> | ||
75 | #include <linux/sched.h> | 80 | #include <linux/sched.h> |
76 | #include <linux/slab.h> | 81 | #include <linux/slab.h> |
77 | #include <linux/types.h> | 82 | #include <linux/types.h> |
@@ -114,7 +119,7 @@ static struct nand_oobinfo nand_oob_64 = { | |||
114 | }; | 119 | }; |
115 | 120 | ||
116 | /* This is used for padding purposes in nand_write_oob */ | 121 | /* This is used for padding purposes in nand_write_oob */ |
117 | static u_char ffchars[] = { | 122 | static uint8_t ffchars[] = { |
118 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 123 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
119 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 124 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
120 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 125 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
@@ -128,36 +133,47 @@ static u_char ffchars[] = { | |||
128 | /* | 133 | /* |
129 | * NAND low-level MTD interface functions | 134 | * NAND low-level MTD interface functions |
130 | */ | 135 | */ |
131 | static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len); | 136 | static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len); |
132 | static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len); | 137 | static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len); |
133 | static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len); | 138 | static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len); |
134 | 139 | ||
135 | static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); | 140 | static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, |
141 | size_t *retlen, uint8_t *buf); | ||
136 | static int nand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | 142 | static int nand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, |
137 | size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); | 143 | size_t *retlen, uint8_t *buf, uint8_t *eccbuf, |
138 | static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); | 144 | struct nand_oobinfo *oobsel); |
139 | static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); | 145 | static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len, |
146 | size_t *retlen, uint8_t *buf); | ||
147 | static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, | ||
148 | size_t *retlen, const uint8_t *buf); | ||
140 | static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | 149 | static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, |
141 | size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); | 150 | size_t *retlen, const uint8_t *buf, uint8_t *eccbuf, |
142 | static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); | 151 | struct nand_oobinfo *oobsel); |
143 | static int nand_writev(struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); | 152 | static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, |
153 | size_t *retlen, const uint8_t *buf); | ||
154 | static int nand_writev(struct mtd_info *mtd, const struct kvec *vecs, | ||
155 | unsigned long count, loff_t to, size_t *retlen); | ||
144 | static int nand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, | 156 | static int nand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, |
145 | unsigned long count, loff_t to, size_t *retlen, u_char *eccbuf, | 157 | unsigned long count, loff_t to, size_t *retlen, |
146 | struct nand_oobinfo *oobsel); | 158 | uint8_t *eccbuf, struct nand_oobinfo *oobsel); |
147 | static int nand_erase(struct mtd_info *mtd, struct erase_info *instr); | 159 | static int nand_erase(struct mtd_info *mtd, struct erase_info *instr); |
148 | static void nand_sync(struct mtd_info *mtd); | 160 | static void nand_sync(struct mtd_info *mtd); |
149 | 161 | ||
150 | /* Some internal functions */ | 162 | /* Some internal functions */ |
151 | static int nand_write_page(struct mtd_info *mtd, struct nand_chip *this, int page, u_char * oob_buf, | 163 | static int nand_write_page(struct mtd_info *mtd, struct nand_chip *this, |
164 | int page, uint8_t * oob_buf, | ||
152 | struct nand_oobinfo *oobsel, int mode); | 165 | struct nand_oobinfo *oobsel, int mode); |
153 | #ifdef CONFIG_MTD_NAND_VERIFY_WRITE | 166 | #ifdef CONFIG_MTD_NAND_VERIFY_WRITE |
154 | static int nand_verify_pages(struct mtd_info *mtd, struct nand_chip *this, int page, int numpages, | 167 | static int nand_verify_pages(struct mtd_info *mtd, struct nand_chip *this, |
155 | u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode); | 168 | int page, int numpages, uint8_t *oob_buf, |
169 | struct nand_oobinfo *oobsel, int chipnr, | ||
170 | int oobmode); | ||
156 | #else | 171 | #else |
157 | #define nand_verify_pages(...) (0) | 172 | #define nand_verify_pages(...) (0) |
158 | #endif | 173 | #endif |
159 | 174 | ||
160 | static int nand_get_device(struct nand_chip *this, struct mtd_info *mtd, int new_state); | 175 | static int nand_get_device(struct nand_chip *this, struct mtd_info *mtd, |
176 | int new_state); | ||
161 | 177 | ||
162 | /** | 178 | /** |
163 | * nand_release_device - [GENERIC] release chip | 179 | * nand_release_device - [GENERIC] release chip |
@@ -172,20 +188,12 @@ static void nand_release_device(struct mtd_info *mtd) | |||
172 | /* De-select the NAND device */ | 188 | /* De-select the NAND device */ |
173 | this->select_chip(mtd, -1); | 189 | this->select_chip(mtd, -1); |
174 | 190 | ||
175 | if (this->controller) { | 191 | /* Release the controller and the chip */ |
176 | /* Release the controller and the chip */ | 192 | spin_lock(&this->controller->lock); |
177 | spin_lock(&this->controller->lock); | 193 | this->controller->active = NULL; |
178 | this->controller->active = NULL; | 194 | this->state = FL_READY; |
179 | this->state = FL_READY; | 195 | wake_up(&this->controller->wq); |
180 | wake_up(&this->controller->wq); | 196 | spin_unlock(&this->controller->lock); |
181 | spin_unlock(&this->controller->lock); | ||
182 | } else { | ||
183 | /* Release the chip */ | ||
184 | spin_lock(&this->chip_lock); | ||
185 | this->state = FL_READY; | ||
186 | wake_up(&this->wq); | ||
187 | spin_unlock(&this->chip_lock); | ||
188 | } | ||
189 | } | 197 | } |
190 | 198 | ||
191 | /** | 199 | /** |
@@ -194,7 +202,7 @@ static void nand_release_device(struct mtd_info *mtd) | |||
194 | * | 202 | * |
195 | * Default read function for 8bit buswith | 203 | * Default read function for 8bit buswith |
196 | */ | 204 | */ |
197 | static u_char nand_read_byte(struct mtd_info *mtd) | 205 | static uint8_t nand_read_byte(struct mtd_info *mtd) |
198 | { | 206 | { |
199 | struct nand_chip *this = mtd->priv; | 207 | struct nand_chip *this = mtd->priv; |
200 | return readb(this->IO_ADDR_R); | 208 | return readb(this->IO_ADDR_R); |
@@ -207,7 +215,7 @@ static u_char nand_read_byte(struct mtd_info *mtd) | |||
207 | * | 215 | * |
208 | * Default write function for 8it buswith | 216 | * Default write function for 8it buswith |
209 | */ | 217 | */ |
210 | static void nand_write_byte(struct mtd_info *mtd, u_char byte) | 218 | static void nand_write_byte(struct mtd_info *mtd, uint8_t byte) |
211 | { | 219 | { |
212 | struct nand_chip *this = mtd->priv; | 220 | struct nand_chip *this = mtd->priv; |
213 | writeb(byte, this->IO_ADDR_W); | 221 | writeb(byte, this->IO_ADDR_W); |
@@ -220,10 +228,10 @@ static void nand_write_byte(struct mtd_info *mtd, u_char byte) | |||
220 | * Default read function for 16bit buswith with | 228 | * Default read function for 16bit buswith with |
221 | * endianess conversion | 229 | * endianess conversion |
222 | */ | 230 | */ |
223 | static u_char nand_read_byte16(struct mtd_info *mtd) | 231 | static uint8_t nand_read_byte16(struct mtd_info *mtd) |
224 | { | 232 | { |
225 | struct nand_chip *this = mtd->priv; | 233 | struct nand_chip *this = mtd->priv; |
226 | return (u_char) cpu_to_le16(readw(this->IO_ADDR_R)); | 234 | return (uint8_t) cpu_to_le16(readw(this->IO_ADDR_R)); |
227 | } | 235 | } |
228 | 236 | ||
229 | /** | 237 | /** |
@@ -234,7 +242,7 @@ static u_char nand_read_byte16(struct mtd_info *mtd) | |||
234 | * Default write function for 16bit buswith with | 242 | * Default write function for 16bit buswith with |
235 | * endianess conversion | 243 | * endianess conversion |
236 | */ | 244 | */ |
237 | static void nand_write_byte16(struct mtd_info *mtd, u_char byte) | 245 | static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte) |
238 | { | 246 | { |
239 | struct nand_chip *this = mtd->priv; | 247 | struct nand_chip *this = mtd->priv; |
240 | writew(le16_to_cpu((u16) byte), this->IO_ADDR_W); | 248 | writew(le16_to_cpu((u16) byte), this->IO_ADDR_W); |
@@ -298,7 +306,7 @@ static void nand_select_chip(struct mtd_info *mtd, int chip) | |||
298 | * | 306 | * |
299 | * Default write function for 8bit buswith | 307 | * Default write function for 8bit buswith |
300 | */ | 308 | */ |
301 | static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | 309 | static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) |
302 | { | 310 | { |
303 | int i; | 311 | int i; |
304 | struct nand_chip *this = mtd->priv; | 312 | struct nand_chip *this = mtd->priv; |
@@ -315,7 +323,7 @@ static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | |||
315 | * | 323 | * |
316 | * Default read function for 8bit buswith | 324 | * Default read function for 8bit buswith |
317 | */ | 325 | */ |
318 | static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | 326 | static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) |
319 | { | 327 | { |
320 | int i; | 328 | int i; |
321 | struct nand_chip *this = mtd->priv; | 329 | struct nand_chip *this = mtd->priv; |
@@ -332,7 +340,7 @@ static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | |||
332 | * | 340 | * |
333 | * Default verify function for 8bit buswith | 341 | * Default verify function for 8bit buswith |
334 | */ | 342 | */ |
335 | static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) | 343 | static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len) |
336 | { | 344 | { |
337 | int i; | 345 | int i; |
338 | struct nand_chip *this = mtd->priv; | 346 | struct nand_chip *this = mtd->priv; |
@@ -352,7 +360,7 @@ static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) | |||
352 | * | 360 | * |
353 | * Default write function for 16bit buswith | 361 | * Default write function for 16bit buswith |
354 | */ | 362 | */ |
355 | static void nand_write_buf16(struct mtd_info *mtd, const u_char *buf, int len) | 363 | static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) |
356 | { | 364 | { |
357 | int i; | 365 | int i; |
358 | struct nand_chip *this = mtd->priv; | 366 | struct nand_chip *this = mtd->priv; |
@@ -372,7 +380,7 @@ static void nand_write_buf16(struct mtd_info *mtd, const u_char *buf, int len) | |||
372 | * | 380 | * |
373 | * Default read function for 16bit buswith | 381 | * Default read function for 16bit buswith |
374 | */ | 382 | */ |
375 | static void nand_read_buf16(struct mtd_info *mtd, u_char *buf, int len) | 383 | static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) |
376 | { | 384 | { |
377 | int i; | 385 | int i; |
378 | struct nand_chip *this = mtd->priv; | 386 | struct nand_chip *this = mtd->priv; |
@@ -391,7 +399,7 @@ static void nand_read_buf16(struct mtd_info *mtd, u_char *buf, int len) | |||
391 | * | 399 | * |
392 | * Default verify function for 16bit buswith | 400 | * Default verify function for 16bit buswith |
393 | */ | 401 | */ |
394 | static int nand_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len) | 402 | static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) |
395 | { | 403 | { |
396 | int i; | 404 | int i; |
397 | struct nand_chip *this = mtd->priv; | 405 | struct nand_chip *this = mtd->priv; |
@@ -432,14 +440,16 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) | |||
432 | page = (int)ofs; | 440 | page = (int)ofs; |
433 | 441 | ||
434 | if (this->options & NAND_BUSWIDTH_16) { | 442 | if (this->options & NAND_BUSWIDTH_16) { |
435 | this->cmdfunc(mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE, page & this->pagemask); | 443 | this->cmdfunc(mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE, |
444 | page & this->pagemask); | ||
436 | bad = cpu_to_le16(this->read_word(mtd)); | 445 | bad = cpu_to_le16(this->read_word(mtd)); |
437 | if (this->badblockpos & 0x1) | 446 | if (this->badblockpos & 0x1) |
438 | bad >>= 8; | 447 | bad >>= 8; |
439 | if ((bad & 0xFF) != 0xff) | 448 | if ((bad & 0xFF) != 0xff) |
440 | res = 1; | 449 | res = 1; |
441 | } else { | 450 | } else { |
442 | this->cmdfunc(mtd, NAND_CMD_READOOB, this->badblockpos, page & this->pagemask); | 451 | this->cmdfunc(mtd, NAND_CMD_READOOB, this->badblockpos, |
452 | page & this->pagemask); | ||
443 | if (this->read_byte(mtd) != 0xff) | 453 | if (this->read_byte(mtd) != 0xff) |
444 | res = 1; | 454 | res = 1; |
445 | } | 455 | } |
@@ -463,7 +473,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) | |||
463 | static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | 473 | static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) |
464 | { | 474 | { |
465 | struct nand_chip *this = mtd->priv; | 475 | struct nand_chip *this = mtd->priv; |
466 | u_char buf[2] = { 0, 0 }; | 476 | uint8_t buf[2] = { 0, 0 }; |
467 | size_t retlen; | 477 | size_t retlen; |
468 | int block; | 478 | int block; |
469 | 479 | ||
@@ -506,7 +516,8 @@ static int nand_check_wp(struct mtd_info *mtd) | |||
506 | * Check, if the block is bad. Either by reading the bad block table or | 516 | * Check, if the block is bad. Either by reading the bad block table or |
507 | * calling of the scan function. | 517 | * calling of the scan function. |
508 | */ | 518 | */ |
509 | static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt) | 519 | static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, |
520 | int allowbbt) | ||
510 | { | 521 | { |
511 | struct nand_chip *this = mtd->priv; | 522 | struct nand_chip *this = mtd->priv; |
512 | 523 | ||
@@ -548,7 +559,8 @@ static void nand_wait_ready(struct mtd_info *mtd) | |||
548 | * Send command to NAND device. This function is used for small page | 559 | * Send command to NAND device. This function is used for small page |
549 | * devices (256/512 Bytes per page) | 560 | * devices (256/512 Bytes per page) |
550 | */ | 561 | */ |
551 | static void nand_command(struct mtd_info *mtd, unsigned command, int column, int page_addr) | 562 | static void nand_command(struct mtd_info *mtd, unsigned command, int column, |
563 | int page_addr) | ||
552 | { | 564 | { |
553 | register struct nand_chip *this = mtd->priv; | 565 | register struct nand_chip *this = mtd->priv; |
554 | 566 | ||
@@ -589,11 +601,11 @@ static void nand_command(struct mtd_info *mtd, unsigned command, int column, int | |||
589 | this->write_byte(mtd, column); | 601 | this->write_byte(mtd, column); |
590 | } | 602 | } |
591 | if (page_addr != -1) { | 603 | if (page_addr != -1) { |
592 | this->write_byte(mtd, (unsigned char)(page_addr & 0xff)); | 604 | this->write_byte(mtd, (uint8_t)(page_addr & 0xff)); |
593 | this->write_byte(mtd, (unsigned char)((page_addr >> 8) & 0xff)); | 605 | this->write_byte(mtd, (uint8_t)((page_addr >> 8) & 0xff)); |
594 | /* One more address cycle for devices > 32MiB */ | 606 | /* One more address cycle for devices > 32MiB */ |
595 | if (this->chipsize > (32 << 20)) | 607 | if (this->chipsize > (32 << 20)) |
596 | this->write_byte(mtd, (unsigned char)((page_addr >> 16) & 0x0f)); | 608 | this->write_byte(mtd, (uint8_t)((page_addr >> 16) & 0x0f)); |
597 | } | 609 | } |
598 | /* Latch in address */ | 610 | /* Latch in address */ |
599 | this->hwcontrol(mtd, NAND_CTL_CLRALE); | 611 | this->hwcontrol(mtd, NAND_CTL_CLRALE); |
@@ -681,11 +693,11 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned command, int column, | |||
681 | this->write_byte(mtd, column >> 8); | 693 | this->write_byte(mtd, column >> 8); |
682 | } | 694 | } |
683 | if (page_addr != -1) { | 695 | if (page_addr != -1) { |
684 | this->write_byte(mtd, (unsigned char)(page_addr & 0xff)); | 696 | this->write_byte(mtd, (uint8_t)(page_addr & 0xff)); |
685 | this->write_byte(mtd, (unsigned char)((page_addr >> 8) & 0xff)); | 697 | this->write_byte(mtd, (uint8_t)((page_addr >> 8) & 0xff)); |
686 | /* One more address cycle for devices > 128MiB */ | 698 | /* One more address cycle for devices > 128MiB */ |
687 | if (this->chipsize > (128 << 20)) | 699 | if (this->chipsize > (128 << 20)) |
688 | this->write_byte(mtd, (unsigned char)((page_addr >> 16) & 0xff)); | 700 | this->write_byte(mtd, (uint8_t)((page_addr >> 16) & 0xff)); |
689 | } | 701 | } |
690 | /* Latch in address */ | 702 | /* Latch in address */ |
691 | this->hwcontrol(mtd, NAND_CTL_CLRALE); | 703 | this->hwcontrol(mtd, NAND_CTL_CLRALE); |
@@ -763,27 +775,21 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned command, int column, | |||
763 | * | 775 | * |
764 | * Get the device and lock it for exclusive access | 776 | * Get the device and lock it for exclusive access |
765 | */ | 777 | */ |
766 | static int nand_get_device(struct nand_chip *this, struct mtd_info *mtd, int new_state) | 778 | static int |
779 | nand_get_device(struct nand_chip *this, struct mtd_info *mtd, int new_state) | ||
767 | { | 780 | { |
768 | struct nand_chip *active; | 781 | spinlock_t *lock = &this->controller->lock; |
769 | spinlock_t *lock; | 782 | wait_queue_head_t *wq = &this->controller->wq; |
770 | wait_queue_head_t *wq; | ||
771 | DECLARE_WAITQUEUE(wait, current); | 783 | DECLARE_WAITQUEUE(wait, current); |
772 | |||
773 | lock = (this->controller) ? &this->controller->lock : &this->chip_lock; | ||
774 | wq = (this->controller) ? &this->controller->wq : &this->wq; | ||
775 | retry: | 784 | retry: |
776 | active = this; | ||
777 | spin_lock(lock); | 785 | spin_lock(lock); |
778 | 786 | ||
779 | /* Hardware controller shared among independend devices */ | 787 | /* Hardware controller shared among independend devices */ |
780 | if (this->controller) { | 788 | /* Hardware controller shared among independend devices */ |
781 | if (this->controller->active) | 789 | if (!this->controller->active) |
782 | active = this->controller->active; | 790 | this->controller->active = this; |
783 | else | 791 | |
784 | this->controller->active = this; | 792 | if (this->controller->active == this && this->state == FL_READY) { |
785 | } | ||
786 | if (active == this && this->state == FL_READY) { | ||
787 | this->state = new_state; | 793 | this->state = new_state; |
788 | spin_unlock(lock); | 794 | spin_unlock(lock); |
789 | return 0; | 795 | return 0; |
@@ -869,13 +875,13 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) | |||
869 | * Cached programming is not supported yet. | 875 | * Cached programming is not supported yet. |
870 | */ | 876 | */ |
871 | static int nand_write_page(struct mtd_info *mtd, struct nand_chip *this, int page, | 877 | static int nand_write_page(struct mtd_info *mtd, struct nand_chip *this, int page, |
872 | u_char *oob_buf, struct nand_oobinfo *oobsel, int cached) | 878 | uint8_t *oob_buf, struct nand_oobinfo *oobsel, int cached) |
873 | { | 879 | { |
874 | int i, status; | 880 | int i, status; |
875 | u_char ecc_code[32]; | 881 | uint8_t ecc_code[32]; |
876 | int eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE; | 882 | int eccmode = oobsel->useecc ? this->ecc.mode : NAND_ECC_NONE; |
877 | int *oob_config = oobsel->eccpos; | 883 | int *oob_config = oobsel->eccpos; |
878 | int datidx = 0, eccidx = 0, eccsteps = this->eccsteps; | 884 | int datidx = 0, eccidx = 0, eccsteps = this->ecc.steps; |
879 | int eccbytes = 0; | 885 | int eccbytes = 0; |
880 | 886 | ||
881 | /* FIXME: Enable cached programming */ | 887 | /* FIXME: Enable cached programming */ |
@@ -895,20 +901,20 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *this, int pag | |||
895 | /* Software ecc 3/256, write all */ | 901 | /* Software ecc 3/256, write all */ |
896 | case NAND_ECC_SOFT: | 902 | case NAND_ECC_SOFT: |
897 | for (; eccsteps; eccsteps--) { | 903 | for (; eccsteps; eccsteps--) { |
898 | this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code); | 904 | this->ecc.calculate(mtd, &this->data_poi[datidx], ecc_code); |
899 | for (i = 0; i < 3; i++, eccidx++) | 905 | for (i = 0; i < 3; i++, eccidx++) |
900 | oob_buf[oob_config[eccidx]] = ecc_code[i]; | 906 | oob_buf[oob_config[eccidx]] = ecc_code[i]; |
901 | datidx += this->eccsize; | 907 | datidx += this->ecc.size; |
902 | } | 908 | } |
903 | this->write_buf(mtd, this->data_poi, mtd->writesize); | 909 | this->write_buf(mtd, this->data_poi, mtd->writesize); |
904 | break; | 910 | break; |
905 | default: | 911 | default: |
906 | eccbytes = this->eccbytes; | 912 | eccbytes = this->ecc.bytes; |
907 | for (; eccsteps; eccsteps--) { | 913 | for (; eccsteps; eccsteps--) { |
908 | /* enable hardware ecc logic for write */ | 914 | /* enable hardware ecc logic for write */ |
909 | this->enable_hwecc(mtd, NAND_ECC_WRITE); | 915 | this->ecc.hwctl(mtd, NAND_ECC_WRITE); |
910 | this->write_buf(mtd, &this->data_poi[datidx], this->eccsize); | 916 | this->write_buf(mtd, &this->data_poi[datidx], this->ecc.size); |
911 | this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code); | 917 | this->ecc.calculate(mtd, &this->data_poi[datidx], ecc_code); |
912 | for (i = 0; i < eccbytes; i++, eccidx++) | 918 | for (i = 0; i < eccbytes; i++, eccidx++) |
913 | oob_buf[oob_config[eccidx]] = ecc_code[i]; | 919 | oob_buf[oob_config[eccidx]] = ecc_code[i]; |
914 | /* If the hardware ecc provides syndromes then | 920 | /* If the hardware ecc provides syndromes then |
@@ -916,7 +922,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *this, int pag | |||
916 | * the data bytes (words) */ | 922 | * the data bytes (words) */ |
917 | if (this->options & NAND_HWECC_SYNDROME) | 923 | if (this->options & NAND_HWECC_SYNDROME) |
918 | this->write_buf(mtd, ecc_code, eccbytes); | 924 | this->write_buf(mtd, ecc_code, eccbytes); |
919 | datidx += this->eccsize; | 925 | datidx += this->ecc.size; |
920 | } | 926 | } |
921 | break; | 927 | break; |
922 | } | 928 | } |
@@ -957,7 +963,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *this, int pag | |||
957 | * nand_verify_pages - [GENERIC] verify the chip contents after a write | 963 | * nand_verify_pages - [GENERIC] verify the chip contents after a write |
958 | * @mtd: MTD device structure | 964 | * @mtd: MTD device structure |
959 | * @this: NAND chip structure | 965 | * @this: NAND chip structure |
960 | * @page: startpage inside the chip, must be called with (page & this->pagemask) | 966 | * @page: startpage inside the chip, must be called with (page & this->pagemask) |
961 | * @numpages: number of pages to verify | 967 | * @numpages: number of pages to verify |
962 | * @oob_buf: out of band data buffer | 968 | * @oob_buf: out of band data buffer |
963 | * @oobsel: out of band selecttion structre | 969 | * @oobsel: out of band selecttion structre |
@@ -973,12 +979,12 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *this, int pag | |||
973 | * it early in the page write stage. Better to write no data than invalid data. | 979 | * it early in the page write stage. Better to write no data than invalid data. |
974 | */ | 980 | */ |
975 | static int nand_verify_pages(struct mtd_info *mtd, struct nand_chip *this, int page, int numpages, | 981 | static int nand_verify_pages(struct mtd_info *mtd, struct nand_chip *this, int page, int numpages, |
976 | u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode) | 982 | uint8_t *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode) |
977 | { | 983 | { |
978 | int i, j, datidx = 0, oobofs = 0, res = -EIO; | 984 | int i, j, datidx = 0, oobofs = 0, res = -EIO; |
979 | int eccsteps = this->eccsteps; | 985 | int eccsteps = this->eccsteps; |
980 | int hweccbytes; | 986 | int hweccbytes; |
981 | u_char oobdata[64]; | 987 | uint8_t oobdata[64]; |
982 | 988 | ||
983 | hweccbytes = (this->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0; | 989 | hweccbytes = (this->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0; |
984 | 990 | ||
@@ -1073,7 +1079,7 @@ static int nand_verify_pages(struct mtd_info *mtd, struct nand_chip *this, int p | |||
1073 | * This function simply calls nand_do_read_ecc with oob buffer and oobsel = NULL | 1079 | * This function simply calls nand_do_read_ecc with oob buffer and oobsel = NULL |
1074 | * and flags = 0xff | 1080 | * and flags = 0xff |
1075 | */ | 1081 | */ |
1076 | static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) | 1082 | static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, uint8_t *buf) |
1077 | { | 1083 | { |
1078 | return nand_do_read_ecc(mtd, from, len, retlen, buf, NULL, &mtd->oobinfo, 0xff); | 1084 | return nand_do_read_ecc(mtd, from, len, retlen, buf, NULL, &mtd->oobinfo, 0xff); |
1079 | } | 1085 | } |
@@ -1091,7 +1097,7 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retl | |||
1091 | * This function simply calls nand_do_read_ecc with flags = 0xff | 1097 | * This function simply calls nand_do_read_ecc with flags = 0xff |
1092 | */ | 1098 | */ |
1093 | static int nand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | 1099 | static int nand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, |
1094 | size_t *retlen, u_char *buf, u_char *oob_buf, struct nand_oobinfo *oobsel) | 1100 | size_t *retlen, uint8_t *buf, uint8_t *oob_buf, struct nand_oobinfo *oobsel) |
1095 | { | 1101 | { |
1096 | /* use userspace supplied oobinfo, if zero */ | 1102 | /* use userspace supplied oobinfo, if zero */ |
1097 | if (oobsel == NULL) | 1103 | if (oobsel == NULL) |
@@ -1116,15 +1122,15 @@ static int nand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | |||
1116 | * NAND read with ECC | 1122 | * NAND read with ECC |
1117 | */ | 1123 | */ |
1118 | int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | 1124 | int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, |
1119 | size_t *retlen, u_char *buf, u_char *oob_buf, struct nand_oobinfo *oobsel, int flags) | 1125 | size_t *retlen, uint8_t *buf, uint8_t *oob_buf, struct nand_oobinfo *oobsel, int flags) |
1120 | { | 1126 | { |
1121 | 1127 | ||
1122 | int i, j, col, realpage, page, end, ecc, chipnr, sndcmd = 1; | 1128 | int i, j, col, realpage, page, end, ecc, chipnr, sndcmd = 1; |
1123 | int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0; | 1129 | int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0; |
1124 | struct nand_chip *this = mtd->priv; | 1130 | struct nand_chip *this = mtd->priv; |
1125 | u_char *data_poi, *oob_data = oob_buf; | 1131 | uint8_t *data_poi, *oob_data = oob_buf; |
1126 | u_char ecc_calc[32]; | 1132 | uint8_t ecc_calc[32]; |
1127 | u_char ecc_code[32]; | 1133 | uint8_t ecc_code[32]; |
1128 | int eccmode, eccsteps; | 1134 | int eccmode, eccsteps; |
1129 | int *oob_config, datidx; | 1135 | int *oob_config, datidx; |
1130 | int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1; | 1136 | int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1; |
@@ -1149,7 +1155,7 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | |||
1149 | if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) | 1155 | if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) |
1150 | oobsel = this->autooob; | 1156 | oobsel = this->autooob; |
1151 | 1157 | ||
1152 | eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE; | 1158 | eccmode = oobsel->useecc ? this->ecc.mode : NAND_ECC_NONE; |
1153 | oob_config = oobsel->eccpos; | 1159 | oob_config = oobsel->eccpos; |
1154 | 1160 | ||
1155 | /* Select the NAND device */ | 1161 | /* Select the NAND device */ |
@@ -1164,8 +1170,8 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | |||
1164 | col = from & (mtd->writesize - 1); | 1170 | col = from & (mtd->writesize - 1); |
1165 | 1171 | ||
1166 | end = mtd->writesize; | 1172 | end = mtd->writesize; |
1167 | ecc = this->eccsize; | 1173 | ecc = this->ecc.size; |
1168 | eccbytes = this->eccbytes; | 1174 | eccbytes = this->ecc.bytes; |
1169 | 1175 | ||
1170 | if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME)) | 1176 | if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME)) |
1171 | compareecc = 0; | 1177 | compareecc = 0; |
@@ -1210,7 +1216,7 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | |||
1210 | oobsel->useecc == MTD_NANDECC_AUTOPL_USR) | 1216 | oobsel->useecc == MTD_NANDECC_AUTOPL_USR) |
1211 | oob_data = &this->data_buf[end]; | 1217 | oob_data = &this->data_buf[end]; |
1212 | 1218 | ||
1213 | eccsteps = this->eccsteps; | 1219 | eccsteps = this->ecc.steps; |
1214 | 1220 | ||
1215 | switch (eccmode) { | 1221 | switch (eccmode) { |
1216 | case NAND_ECC_NONE:{ | 1222 | case NAND_ECC_NONE:{ |
@@ -1228,12 +1234,12 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | |||
1228 | case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */ | 1234 | case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */ |
1229 | this->read_buf(mtd, data_poi, end); | 1235 | this->read_buf(mtd, data_poi, end); |
1230 | for (i = 0, datidx = 0; eccsteps; eccsteps--, i += 3, datidx += ecc) | 1236 | for (i = 0, datidx = 0; eccsteps; eccsteps--, i += 3, datidx += ecc) |
1231 | this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]); | 1237 | this->ecc.calculate(mtd, &data_poi[datidx], &ecc_calc[i]); |
1232 | break; | 1238 | break; |
1233 | 1239 | ||
1234 | default: | 1240 | default: |
1235 | for (i = 0, datidx = 0; eccsteps; eccsteps--, i += eccbytes, datidx += ecc) { | 1241 | for (i = 0, datidx = 0; eccsteps; eccsteps--, i += eccbytes, datidx += ecc) { |
1236 | this->enable_hwecc(mtd, NAND_ECC_READ); | 1242 | this->ecc.hwctl(mtd, NAND_ECC_READ); |
1237 | this->read_buf(mtd, &data_poi[datidx], ecc); | 1243 | this->read_buf(mtd, &data_poi[datidx], ecc); |
1238 | 1244 | ||
1239 | /* HW ecc with syndrome calculation must read the | 1245 | /* HW ecc with syndrome calculation must read the |
@@ -1241,19 +1247,19 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | |||
1241 | if (!compareecc) { | 1247 | if (!compareecc) { |
1242 | /* Some hw ecc generators need to know when the | 1248 | /* Some hw ecc generators need to know when the |
1243 | * syndrome is read from flash */ | 1249 | * syndrome is read from flash */ |
1244 | this->enable_hwecc(mtd, NAND_ECC_READSYN); | 1250 | this->ecc.hwctl(mtd, NAND_ECC_READSYN); |
1245 | this->read_buf(mtd, &oob_data[i], eccbytes); | 1251 | this->read_buf(mtd, &oob_data[i], eccbytes); |
1246 | /* We calc error correction directly, it checks the hw | 1252 | /* We calc error correction directly, it checks the hw |
1247 | * generator for an error, reads back the syndrome and | 1253 | * generator for an error, reads back the syndrome and |
1248 | * does the error correction on the fly */ | 1254 | * does the error correction on the fly */ |
1249 | ecc_status = this->correct_data(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]); | 1255 | ecc_status = this->ecc.correct(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]); |
1250 | if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) { | 1256 | if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) { |
1251 | DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: " | 1257 | DEBUG(MTD_DEBUG_LEVEL0, "nand_read_ecc: " |
1252 | "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr); | 1258 | "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr); |
1253 | ecc_failed++; | 1259 | ecc_failed++; |
1254 | } | 1260 | } |
1255 | } else { | 1261 | } else { |
1256 | this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]); | 1262 | this->ecc.calculate(mtd, &data_poi[datidx], &ecc_calc[i]); |
1257 | } | 1263 | } |
1258 | } | 1264 | } |
1259 | break; | 1265 | break; |
@@ -1271,8 +1277,8 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | |||
1271 | ecc_code[j] = oob_data[oob_config[j]]; | 1277 | ecc_code[j] = oob_data[oob_config[j]]; |
1272 | 1278 | ||
1273 | /* correct data, if necessary */ | 1279 | /* correct data, if necessary */ |
1274 | for (i = 0, j = 0, datidx = 0; i < this->eccsteps; i++, datidx += ecc) { | 1280 | for (i = 0, j = 0, datidx = 0; i < this->ecc.steps; i++, datidx += ecc) { |
1275 | ecc_status = this->correct_data(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]); | 1281 | ecc_status = this->ecc.correct(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]); |
1276 | 1282 | ||
1277 | /* Get next chunk of ecc bytes */ | 1283 | /* Get next chunk of ecc bytes */ |
1278 | j += eccbytes; | 1284 | j += eccbytes; |
@@ -1309,7 +1315,7 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | |||
1309 | break; | 1315 | break; |
1310 | case MTD_NANDECC_PLACE: | 1316 | case MTD_NANDECC_PLACE: |
1311 | /* YAFFS1 legacy mode */ | 1317 | /* YAFFS1 legacy mode */ |
1312 | oob_data += this->eccsteps * sizeof(int); | 1318 | oob_data += this->ecc.steps * sizeof(int); |
1313 | default: | 1319 | default: |
1314 | oob_data += mtd->oobsize; | 1320 | oob_data += mtd->oobsize; |
1315 | } | 1321 | } |
@@ -1378,7 +1384,7 @@ int nand_do_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | |||
1378 | * | 1384 | * |
1379 | * NAND read out-of-band data from the spare area | 1385 | * NAND read out-of-band data from the spare area |
1380 | */ | 1386 | */ |
1381 | static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) | 1387 | static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, uint8_t *buf) |
1382 | { | 1388 | { |
1383 | int i, col, page, chipnr; | 1389 | int i, col, page, chipnr; |
1384 | struct nand_chip *this = mtd->priv; | 1390 | struct nand_chip *this = mtd->priv; |
@@ -1545,7 +1551,7 @@ int nand_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, s | |||
1545 | * forces the 0xff fill before using the buffer again. | 1551 | * forces the 0xff fill before using the buffer again. |
1546 | * | 1552 | * |
1547 | */ | 1553 | */ |
1548 | static u_char *nand_prepare_oobbuf(struct mtd_info *mtd, u_char *fsbuf, struct nand_oobinfo *oobsel, | 1554 | static uint8_t *nand_prepare_oobbuf(struct mtd_info *mtd, uint8_t *fsbuf, struct nand_oobinfo *oobsel, |
1549 | int autoplace, int numpages) | 1555 | int autoplace, int numpages) |
1550 | { | 1556 | { |
1551 | struct nand_chip *this = mtd->priv; | 1557 | struct nand_chip *this = mtd->priv; |
@@ -1594,7 +1600,7 @@ static u_char *nand_prepare_oobbuf(struct mtd_info *mtd, u_char *fsbuf, struct n | |||
1594 | * This function simply calls nand_write_ecc with oob buffer and oobsel = NULL | 1600 | * This function simply calls nand_write_ecc with oob buffer and oobsel = NULL |
1595 | * | 1601 | * |
1596 | */ | 1602 | */ |
1597 | static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) | 1603 | static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const uint8_t *buf) |
1598 | { | 1604 | { |
1599 | return (nand_write_ecc(mtd, to, len, retlen, buf, NULL, NULL)); | 1605 | return (nand_write_ecc(mtd, to, len, retlen, buf, NULL, NULL)); |
1600 | } | 1606 | } |
@@ -1612,13 +1618,13 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retle | |||
1612 | * NAND write with ECC | 1618 | * NAND write with ECC |
1613 | */ | 1619 | */ |
1614 | static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | 1620 | static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, |
1615 | size_t *retlen, const u_char *buf, u_char *eccbuf, | 1621 | size_t *retlen, const uint8_t *buf, uint8_t *eccbuf, |
1616 | struct nand_oobinfo *oobsel) | 1622 | struct nand_oobinfo *oobsel) |
1617 | { | 1623 | { |
1618 | int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr; | 1624 | int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr; |
1619 | int autoplace = 0, numpages, totalpages; | 1625 | int autoplace = 0, numpages, totalpages; |
1620 | struct nand_chip *this = mtd->priv; | 1626 | struct nand_chip *this = mtd->priv; |
1621 | u_char *oobbuf, *bufstart; | 1627 | uint8_t *oobbuf, *bufstart; |
1622 | int ppblock = (1 << (this->phys_erase_shift - this->page_shift)); | 1628 | int ppblock = (1 << (this->phys_erase_shift - this->page_shift)); |
1623 | 1629 | ||
1624 | DEBUG(MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len); | 1630 | DEBUG(MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len); |
@@ -1675,12 +1681,12 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | |||
1675 | /* Calc number of pages we can write in one go */ | 1681 | /* Calc number of pages we can write in one go */ |
1676 | numpages = min(ppblock - (startpage & (ppblock - 1)), totalpages); | 1682 | numpages = min(ppblock - (startpage & (ppblock - 1)), totalpages); |
1677 | oobbuf = nand_prepare_oobbuf(mtd, eccbuf, oobsel, autoplace, numpages); | 1683 | oobbuf = nand_prepare_oobbuf(mtd, eccbuf, oobsel, autoplace, numpages); |
1678 | bufstart = (u_char *) buf; | 1684 | bufstart = (uint8_t *) buf; |
1679 | 1685 | ||
1680 | /* Loop until all data is written */ | 1686 | /* Loop until all data is written */ |
1681 | while (written < len) { | 1687 | while (written < len) { |
1682 | 1688 | ||
1683 | this->data_poi = (u_char *) &buf[written]; | 1689 | this->data_poi = (uint8_t *) &buf[written]; |
1684 | /* Write one page. If this is the last page to write | 1690 | /* Write one page. If this is the last page to write |
1685 | * or the last page in this block, then use the | 1691 | * or the last page in this block, then use the |
1686 | * real pageprogram command, else select cached programming | 1692 | * real pageprogram command, else select cached programming |
@@ -1759,7 +1765,7 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | |||
1759 | * | 1765 | * |
1760 | * NAND write out-of-band | 1766 | * NAND write out-of-band |
1761 | */ | 1767 | */ |
1762 | static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) | 1768 | static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const uint8_t *buf) |
1763 | { | 1769 | { |
1764 | int column, page, status, ret = -EIO, chipnr; | 1770 | int column, page, status, ret = -EIO, chipnr; |
1765 | struct nand_chip *this = mtd->priv; | 1771 | struct nand_chip *this = mtd->priv; |
@@ -1879,13 +1885,13 @@ static int nand_writev(struct mtd_info *mtd, const struct kvec *vecs, unsigned l | |||
1879 | * NAND write with iovec with ecc | 1885 | * NAND write with iovec with ecc |
1880 | */ | 1886 | */ |
1881 | static int nand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, | 1887 | static int nand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, |
1882 | loff_t to, size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel) | 1888 | loff_t to, size_t *retlen, uint8_t *eccbuf, struct nand_oobinfo *oobsel) |
1883 | { | 1889 | { |
1884 | int i, page, len, total_len, ret = -EIO, written = 0, chipnr; | 1890 | int i, page, len, total_len, ret = -EIO, written = 0, chipnr; |
1885 | int oob, numpages, autoplace = 0, startpage; | 1891 | int oob, numpages, autoplace = 0, startpage; |
1886 | struct nand_chip *this = mtd->priv; | 1892 | struct nand_chip *this = mtd->priv; |
1887 | int ppblock = (1 << (this->phys_erase_shift - this->page_shift)); | 1893 | int ppblock = (1 << (this->phys_erase_shift - this->page_shift)); |
1888 | u_char *oobbuf, *bufstart; | 1894 | uint8_t *oobbuf, *bufstart; |
1889 | 1895 | ||
1890 | /* Preset written len for early exit */ | 1896 | /* Preset written len for early exit */ |
1891 | *retlen = 0; | 1897 | *retlen = 0; |
@@ -1954,7 +1960,7 @@ static int nand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, unsign | |||
1954 | /* Do not cross block boundaries */ | 1960 | /* Do not cross block boundaries */ |
1955 | numpages = min(ppblock - (startpage & (ppblock - 1)), numpages); | 1961 | numpages = min(ppblock - (startpage & (ppblock - 1)), numpages); |
1956 | oobbuf = nand_prepare_oobbuf(mtd, NULL, oobsel, autoplace, numpages); | 1962 | oobbuf = nand_prepare_oobbuf(mtd, NULL, oobsel, autoplace, numpages); |
1957 | bufstart = (u_char *) vecs->iov_base; | 1963 | bufstart = (uint8_t *) vecs->iov_base; |
1958 | bufstart += len; | 1964 | bufstart += len; |
1959 | this->data_poi = bufstart; | 1965 | this->data_poi = bufstart; |
1960 | oob = 0; | 1966 | oob = 0; |
@@ -1985,7 +1991,7 @@ static int nand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, unsign | |||
1985 | int cnt = 0; | 1991 | int cnt = 0; |
1986 | while (cnt < mtd->writesize) { | 1992 | while (cnt < mtd->writesize) { |
1987 | if (vecs->iov_base != NULL && vecs->iov_len) | 1993 | if (vecs->iov_base != NULL && vecs->iov_len) |
1988 | this->data_buf[cnt++] = ((u_char *) vecs->iov_base)[len++]; | 1994 | this->data_buf[cnt++] = ((uint8_t *) vecs->iov_base)[len++]; |
1989 | /* Check, if we have to switch to the next tuple */ | 1995 | /* Check, if we have to switch to the next tuple */ |
1990 | if (len >= (int)vecs->iov_len) { | 1996 | if (len >= (int)vecs->iov_len) { |
1991 | vecs++; | 1997 | vecs++; |
@@ -2308,46 +2314,70 @@ static void nand_resume(struct mtd_info *mtd) | |||
2308 | if (this->state == FL_PM_SUSPENDED) | 2314 | if (this->state == FL_PM_SUSPENDED) |
2309 | nand_release_device(mtd); | 2315 | nand_release_device(mtd); |
2310 | else | 2316 | else |
2311 | printk(KERN_ERR "resume() called for the chip which is not in suspended state\n"); | 2317 | printk(KERN_ERR "nand_resume() called for a chip which is not " |
2312 | 2318 | "in suspended state\n"); | |
2313 | } | 2319 | } |
2314 | 2320 | ||
2315 | /* module_text_address() isn't exported, and it's mostly a pointless | 2321 | /* |
2316 | test if this is a module _anyway_ -- they'd have to try _really_ hard | 2322 | * Free allocated data structures |
2317 | to call us from in-kernel code if the core NAND support is modular. */ | 2323 | */ |
2318 | #ifdef MODULE | 2324 | static void nand_free_kmem(struct nand_chip *this) |
2319 | #define caller_is_module() (1) | 2325 | { |
2320 | #else | 2326 | /* Buffer allocated by nand_scan ? */ |
2321 | #define caller_is_module() module_text_address((unsigned long)__builtin_return_address(0)) | 2327 | if (this->options & NAND_OOBBUF_ALLOC) |
2322 | #endif | 2328 | kfree(this->oob_buf); |
2329 | /* Buffer allocated by nand_scan ? */ | ||
2330 | if (this->options & NAND_DATABUF_ALLOC) | ||
2331 | kfree(this->data_buf); | ||
2332 | /* Controller allocated by nand_scan ? */ | ||
2333 | if (this->options & NAND_CONTROLLER_ALLOC) | ||
2334 | kfree(this->controller); | ||
2335 | } | ||
2323 | 2336 | ||
2324 | /** | 2337 | /* |
2325 | * nand_scan - [NAND Interface] Scan for the NAND device | 2338 | * Allocate buffers and data structures |
2326 | * @mtd: MTD device structure | ||
2327 | * @maxchips: Number of chips to scan for | ||
2328 | * | ||
2329 | * This fills out all the uninitialized function pointers | ||
2330 | * with the defaults. | ||
2331 | * The flash ID is read and the mtd/chip structures are | ||
2332 | * filled with the appropriate values. Buffers are allocated if | ||
2333 | * they are not provided by the board driver | ||
2334 | * The mtd->owner field must be set to the module of the caller | ||
2335 | * | ||
2336 | */ | 2339 | */ |
2337 | int nand_scan(struct mtd_info *mtd, int maxchips) | 2340 | static int nand_allocate_kmem(struct mtd_info *mtd, struct nand_chip *this) |
2338 | { | 2341 | { |
2339 | int i, nand_maf_id, nand_dev_id, busw, maf_id; | 2342 | size_t len; |
2340 | struct nand_chip *this = mtd->priv; | ||
2341 | 2343 | ||
2342 | /* Many callers got this wrong, so check for it for a while... */ | 2344 | if (!this->oob_buf) { |
2343 | if (!mtd->owner && caller_is_module()) { | 2345 | len = mtd->oobsize << |
2344 | printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n"); | 2346 | (this->phys_erase_shift - this->page_shift); |
2345 | BUG(); | 2347 | this->oob_buf = kmalloc(len, GFP_KERNEL); |
2348 | if (!this->oob_buf) | ||
2349 | goto outerr; | ||
2350 | this->options |= NAND_OOBBUF_ALLOC; | ||
2346 | } | 2351 | } |
2347 | 2352 | ||
2348 | /* Get buswidth to select the correct functions */ | 2353 | if (!this->data_buf) { |
2349 | busw = this->options & NAND_BUSWIDTH_16; | 2354 | len = mtd->writesize + mtd->oobsize; |
2355 | this->data_buf = kmalloc(len, GFP_KERNEL); | ||
2356 | if (!this->data_buf) | ||
2357 | goto outerr; | ||
2358 | this->options |= NAND_DATABUF_ALLOC; | ||
2359 | } | ||
2360 | |||
2361 | if (!this->controller) { | ||
2362 | this->controller = kzalloc(sizeof(struct nand_hw_control), | ||
2363 | GFP_KERNEL); | ||
2364 | if (!this->controller) | ||
2365 | goto outerr; | ||
2366 | this->options |= NAND_CONTROLLER_ALLOC; | ||
2367 | } | ||
2368 | return 0; | ||
2369 | |||
2370 | outerr: | ||
2371 | printk(KERN_ERR "nand_scan(): Cannot allocate buffers\n"); | ||
2372 | nand_free_kmem(this); | ||
2373 | return -ENOMEM; | ||
2374 | } | ||
2350 | 2375 | ||
2376 | /* | ||
2377 | * Set default functions | ||
2378 | */ | ||
2379 | static void nand_set_defaults(struct nand_chip *this, int busw) | ||
2380 | { | ||
2351 | /* check for proper chip_delay setup, set 20us if not */ | 2381 | /* check for proper chip_delay setup, set 20us if not */ |
2352 | if (!this->chip_delay) | 2382 | if (!this->chip_delay) |
2353 | this->chip_delay = 20; | 2383 | this->chip_delay = 20; |
@@ -2382,6 +2412,17 @@ int nand_scan(struct mtd_info *mtd, int maxchips) | |||
2382 | this->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf; | 2412 | this->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf; |
2383 | if (!this->scan_bbt) | 2413 | if (!this->scan_bbt) |
2384 | this->scan_bbt = nand_default_bbt; | 2414 | this->scan_bbt = nand_default_bbt; |
2415 | } | ||
2416 | |||
2417 | /* | ||
2418 | * Get the flash and manufacturer id and lookup if the typ is supported | ||
2419 | */ | ||
2420 | static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | ||
2421 | struct nand_chip *this, | ||
2422 | int busw, int *maf_id) | ||
2423 | { | ||
2424 | struct nand_flash_dev *type = NULL; | ||
2425 | int i, dev_id, maf_idx; | ||
2385 | 2426 | ||
2386 | /* Select the device */ | 2427 | /* Select the device */ |
2387 | this->select_chip(mtd, 0); | 2428 | this->select_chip(mtd, 0); |
@@ -2390,159 +2431,194 @@ int nand_scan(struct mtd_info *mtd, int maxchips) | |||
2390 | this->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); | 2431 | this->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); |
2391 | 2432 | ||
2392 | /* Read manufacturer and device IDs */ | 2433 | /* Read manufacturer and device IDs */ |
2393 | nand_maf_id = this->read_byte(mtd); | 2434 | *maf_id = this->read_byte(mtd); |
2394 | nand_dev_id = this->read_byte(mtd); | 2435 | dev_id = this->read_byte(mtd); |
2395 | 2436 | ||
2396 | /* Print and store flash device information */ | 2437 | /* Lookup the flash id */ |
2397 | for (i = 0; nand_flash_ids[i].name != NULL; i++) { | 2438 | for (i = 0; nand_flash_ids[i].name != NULL; i++) { |
2439 | if (dev_id == nand_flash_ids[i].id) { | ||
2440 | type = &nand_flash_ids[i]; | ||
2441 | break; | ||
2442 | } | ||
2443 | } | ||
2398 | 2444 | ||
2399 | if (nand_dev_id != nand_flash_ids[i].id) | 2445 | if (!type) |
2400 | continue; | 2446 | return ERR_PTR(-ENODEV); |
2401 | 2447 | ||
2402 | if (!mtd->name) | 2448 | this->chipsize = nand_flash_ids[i].chipsize << 20; |
2403 | mtd->name = nand_flash_ids[i].name; | 2449 | |
2404 | this->chipsize = nand_flash_ids[i].chipsize << 20; | 2450 | /* Newer devices have all the information in additional id bytes */ |
2405 | 2451 | if (!nand_flash_ids[i].pagesize) { | |
2406 | /* New devices have all the information in additional id bytes */ | 2452 | int extid; |
2407 | if (!nand_flash_ids[i].pagesize) { | 2453 | /* The 3rd id byte contains non relevant data ATM */ |
2408 | int extid; | 2454 | extid = this->read_byte(mtd); |
2409 | /* The 3rd id byte contains non relevant data ATM */ | 2455 | /* The 4th id byte is the important one */ |
2410 | extid = this->read_byte(mtd); | 2456 | extid = this->read_byte(mtd); |
2411 | /* The 4th id byte is the important one */ | 2457 | /* Calc pagesize */ |
2412 | extid = this->read_byte(mtd); | 2458 | mtd->writesize = 1024 << (extid & 0x3); |
2413 | /* Calc pagesize */ | 2459 | extid >>= 2; |
2414 | mtd->writesize = 1024 << (extid & 0x3); | 2460 | /* Calc oobsize */ |
2415 | extid >>= 2; | 2461 | mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9); |
2416 | /* Calc oobsize */ | 2462 | extid >>= 2; |
2417 | mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9); | 2463 | /* Calc blocksize. Blocksize is multiples of 64KiB */ |
2418 | extid >>= 2; | 2464 | mtd->erasesize = (64 * 1024) << (extid & 0x03); |
2419 | /* Calc blocksize. Blocksize is multiples of 64KiB */ | 2465 | extid >>= 2; |
2420 | mtd->erasesize = (64 * 1024) << (extid & 0x03); | 2466 | /* Get buswidth information */ |
2421 | extid >>= 2; | 2467 | busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; |
2422 | /* Get buswidth information */ | ||
2423 | busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; | ||
2424 | 2468 | ||
2425 | } else { | 2469 | } else { |
2426 | /* Old devices have this data hardcoded in the | 2470 | /* |
2427 | * device id table */ | 2471 | * Old devices have this data hardcoded in the device id table |
2428 | mtd->erasesize = nand_flash_ids[i].erasesize; | 2472 | */ |
2429 | mtd->writesize = nand_flash_ids[i].pagesize; | 2473 | mtd->erasesize = nand_flash_ids[i].erasesize; |
2430 | mtd->oobsize = mtd->writesize / 32; | 2474 | mtd->writesize = nand_flash_ids[i].pagesize; |
2431 | busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16; | 2475 | mtd->oobsize = mtd->writesize / 32; |
2432 | } | 2476 | busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16; |
2477 | } | ||
2433 | 2478 | ||
2434 | /* Try to identify manufacturer */ | 2479 | /* Try to identify manufacturer */ |
2435 | for (maf_id = 0; nand_manuf_ids[maf_id].id != 0x0; maf_id++) { | 2480 | for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_id++) { |
2436 | if (nand_manuf_ids[maf_id].id == nand_maf_id) | 2481 | if (nand_manuf_ids[maf_idx].id == *maf_id) |
2437 | break; | 2482 | break; |
2438 | } | 2483 | } |
2439 | 2484 | ||
2440 | /* Check, if buswidth is correct. Hardware drivers should set | 2485 | /* |
2441 | * this correct ! */ | 2486 | * Check, if buswidth is correct. Hardware drivers should set |
2442 | if (busw != (this->options & NAND_BUSWIDTH_16)) { | 2487 | * this correct ! |
2443 | printk(KERN_INFO "NAND device: Manufacturer ID:" | 2488 | */ |
2444 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, | 2489 | if (busw != (this->options & NAND_BUSWIDTH_16)) { |
2445 | nand_manuf_ids[maf_id].name, mtd->name); | 2490 | printk(KERN_INFO "NAND device: Manufacturer ID:" |
2446 | printk(KERN_WARNING | 2491 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, |
2447 | "NAND bus width %d instead %d bit\n", | 2492 | dev_id, nand_manuf_ids[maf_idx].name, mtd->name); |
2448 | (this->options & NAND_BUSWIDTH_16) ? 16 : 8, busw ? 16 : 8); | 2493 | printk(KERN_WARNING "NAND bus width %d instead %d bit\n", |
2449 | this->select_chip(mtd, -1); | 2494 | (this->options & NAND_BUSWIDTH_16) ? 16 : 8, |
2450 | return 1; | 2495 | busw ? 16 : 8); |
2451 | } | 2496 | return ERR_PTR(-EINVAL); |
2497 | } | ||
2452 | 2498 | ||
2453 | /* Calculate the address shift from the page size */ | 2499 | /* Calculate the address shift from the page size */ |
2454 | this->page_shift = ffs(mtd->writesize) - 1; | 2500 | this->page_shift = ffs(mtd->writesize) - 1; |
2455 | this->bbt_erase_shift = this->phys_erase_shift = ffs(mtd->erasesize) - 1; | 2501 | /* Convert chipsize to number of pages per chip -1. */ |
2456 | this->chip_shift = ffs(this->chipsize) - 1; | 2502 | this->pagemask = (this->chipsize >> this->page_shift) - 1; |
2457 | |||
2458 | /* Set the bad block position */ | ||
2459 | this->badblockpos = mtd->writesize > 512 ? NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS; | ||
2460 | |||
2461 | /* Get chip options, preserve non chip based options */ | ||
2462 | this->options &= ~NAND_CHIPOPTIONS_MSK; | ||
2463 | this->options |= nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK; | ||
2464 | /* Set this as a default. Board drivers can override it, if necessary */ | ||
2465 | this->options |= NAND_NO_AUTOINCR; | ||
2466 | /* Check if this is a not a samsung device. Do not clear the options | ||
2467 | * for chips which are not having an extended id. | ||
2468 | */ | ||
2469 | if (nand_maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize) | ||
2470 | this->options &= ~NAND_SAMSUNG_LP_OPTIONS; | ||
2471 | 2503 | ||
2472 | /* Check for AND chips with 4 page planes */ | 2504 | this->bbt_erase_shift = this->phys_erase_shift = |
2473 | if (this->options & NAND_4PAGE_ARRAY) | 2505 | ffs(mtd->erasesize) - 1; |
2474 | this->erase_cmd = multi_erase_cmd; | 2506 | this->chip_shift = ffs(this->chipsize) - 1; |
2475 | else | ||
2476 | this->erase_cmd = single_erase_cmd; | ||
2477 | 2507 | ||
2478 | /* Do not replace user supplied command function ! */ | 2508 | /* Set the bad block position */ |
2479 | if (mtd->writesize > 512 && this->cmdfunc == nand_command) | 2509 | this->badblockpos = mtd->writesize > 512 ? |
2480 | this->cmdfunc = nand_command_lp; | 2510 | NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS; |
2481 | 2511 | ||
2482 | printk(KERN_INFO "NAND device: Manufacturer ID:" | 2512 | /* Get chip options, preserve non chip based options */ |
2483 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, | 2513 | this->options &= ~NAND_CHIPOPTIONS_MSK; |
2484 | nand_manuf_ids[maf_id].name, nand_flash_ids[i].name); | 2514 | this->options |= nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK; |
2485 | break; | 2515 | |
2516 | /* | ||
2517 | * Set this as a default. Board drivers can override it, if necessary | ||
2518 | */ | ||
2519 | this->options |= NAND_NO_AUTOINCR; | ||
2520 | |||
2521 | /* Check if this is a not a samsung device. Do not clear the | ||
2522 | * options for chips which are not having an extended id. | ||
2523 | */ | ||
2524 | if (*maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize) | ||
2525 | this->options &= ~NAND_SAMSUNG_LP_OPTIONS; | ||
2526 | |||
2527 | /* Check for AND chips with 4 page planes */ | ||
2528 | if (this->options & NAND_4PAGE_ARRAY) | ||
2529 | this->erase_cmd = multi_erase_cmd; | ||
2530 | else | ||
2531 | this->erase_cmd = single_erase_cmd; | ||
2532 | |||
2533 | /* Do not replace user supplied command function ! */ | ||
2534 | if (mtd->writesize > 512 && this->cmdfunc == nand_command) | ||
2535 | this->cmdfunc = nand_command_lp; | ||
2536 | |||
2537 | printk(KERN_INFO "NAND device: Manufacturer ID:" | ||
2538 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id, | ||
2539 | nand_manuf_ids[maf_idx].name, type->name); | ||
2540 | |||
2541 | return type; | ||
2542 | } | ||
2543 | |||
2544 | /* module_text_address() isn't exported, and it's mostly a pointless | ||
2545 | test if this is a module _anyway_ -- they'd have to try _really_ hard | ||
2546 | to call us from in-kernel code if the core NAND support is modular. */ | ||
2547 | #ifdef MODULE | ||
2548 | #define caller_is_module() (1) | ||
2549 | #else | ||
2550 | #define caller_is_module() \ | ||
2551 | module_text_address((unsigned long)__builtin_return_address(0)) | ||
2552 | #endif | ||
2553 | |||
2554 | /** | ||
2555 | * nand_scan - [NAND Interface] Scan for the NAND device | ||
2556 | * @mtd: MTD device structure | ||
2557 | * @maxchips: Number of chips to scan for | ||
2558 | * | ||
2559 | * This fills out all the uninitialized function pointers | ||
2560 | * with the defaults. | ||
2561 | * The flash ID is read and the mtd/chip structures are | ||
2562 | * filled with the appropriate values. Buffers are allocated if | ||
2563 | * they are not provided by the board driver | ||
2564 | * The mtd->owner field must be set to the module of the caller | ||
2565 | * | ||
2566 | */ | ||
2567 | int nand_scan(struct mtd_info *mtd, int maxchips) | ||
2568 | { | ||
2569 | int i, busw, nand_maf_id; | ||
2570 | struct nand_chip *this = mtd->priv; | ||
2571 | struct nand_flash_dev *type; | ||
2572 | |||
2573 | /* Many callers got this wrong, so check for it for a while... */ | ||
2574 | if (!mtd->owner && caller_is_module()) { | ||
2575 | printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n"); | ||
2576 | BUG(); | ||
2486 | } | 2577 | } |
2487 | 2578 | ||
2488 | if (!nand_flash_ids[i].name) { | 2579 | /* Get buswidth to select the correct functions */ |
2580 | busw = this->options & NAND_BUSWIDTH_16; | ||
2581 | /* Set the default functions */ | ||
2582 | nand_set_defaults(this, busw); | ||
2583 | |||
2584 | /* Read the flash type */ | ||
2585 | type = nand_get_flash_type(mtd, this, busw, &nand_maf_id); | ||
2586 | |||
2587 | if (IS_ERR(type)) { | ||
2489 | printk(KERN_WARNING "No NAND device found!!!\n"); | 2588 | printk(KERN_WARNING "No NAND device found!!!\n"); |
2490 | this->select_chip(mtd, -1); | 2589 | this->select_chip(mtd, -1); |
2491 | return 1; | 2590 | return PTR_ERR(type); |
2492 | } | 2591 | } |
2493 | 2592 | ||
2593 | /* Check for a chip array */ | ||
2494 | for (i = 1; i < maxchips; i++) { | 2594 | for (i = 1; i < maxchips; i++) { |
2495 | this->select_chip(mtd, i); | 2595 | this->select_chip(mtd, i); |
2496 | |||
2497 | /* Send the command for reading device ID */ | 2596 | /* Send the command for reading device ID */ |
2498 | this->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); | 2597 | this->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); |
2499 | |||
2500 | /* Read manufacturer and device IDs */ | 2598 | /* Read manufacturer and device IDs */ |
2501 | if (nand_maf_id != this->read_byte(mtd) || | 2599 | if (nand_maf_id != this->read_byte(mtd) || |
2502 | nand_dev_id != this->read_byte(mtd)) | 2600 | type->id != this->read_byte(mtd)) |
2503 | break; | 2601 | break; |
2504 | } | 2602 | } |
2505 | if (i > 1) | 2603 | if (i > 1) |
2506 | printk(KERN_INFO "%d NAND chips detected\n", i); | 2604 | printk(KERN_INFO "%d NAND chips detected\n", i); |
2507 | 2605 | ||
2508 | /* Allocate buffers, if necessary */ | ||
2509 | if (!this->oob_buf) { | ||
2510 | size_t len; | ||
2511 | len = mtd->oobsize << (this->phys_erase_shift - this->page_shift); | ||
2512 | this->oob_buf = kmalloc(len, GFP_KERNEL); | ||
2513 | if (!this->oob_buf) { | ||
2514 | printk(KERN_ERR "nand_scan(): Cannot allocate oob_buf\n"); | ||
2515 | return -ENOMEM; | ||
2516 | } | ||
2517 | this->options |= NAND_OOBBUF_ALLOC; | ||
2518 | } | ||
2519 | |||
2520 | if (!this->data_buf) { | ||
2521 | size_t len; | ||
2522 | len = mtd->writesize + mtd->oobsize; | ||
2523 | this->data_buf = kmalloc(len, GFP_KERNEL); | ||
2524 | if (!this->data_buf) { | ||
2525 | if (this->options & NAND_OOBBUF_ALLOC) | ||
2526 | kfree(this->oob_buf); | ||
2527 | printk(KERN_ERR "nand_scan(): Cannot allocate data_buf\n"); | ||
2528 | return -ENOMEM; | ||
2529 | } | ||
2530 | this->options |= NAND_DATABUF_ALLOC; | ||
2531 | } | ||
2532 | |||
2533 | /* Store the number of chips and calc total size for mtd */ | 2606 | /* Store the number of chips and calc total size for mtd */ |
2534 | this->numchips = i; | 2607 | this->numchips = i; |
2535 | mtd->size = i * this->chipsize; | 2608 | mtd->size = i * this->chipsize; |
2536 | /* Convert chipsize to number of pages per chip -1. */ | 2609 | |
2537 | this->pagemask = (this->chipsize >> this->page_shift) - 1; | 2610 | /* Allocate buffers and data structures */ |
2611 | if (nand_allocate_kmem(mtd, this)) | ||
2612 | return -ENOMEM; | ||
2613 | |||
2538 | /* Preset the internal oob buffer */ | 2614 | /* Preset the internal oob buffer */ |
2539 | memset(this->oob_buf, 0xff, mtd->oobsize << (this->phys_erase_shift - this->page_shift)); | 2615 | memset(this->oob_buf, 0xff, |
2616 | mtd->oobsize << (this->phys_erase_shift - this->page_shift)); | ||
2540 | 2617 | ||
2541 | /* If no default placement scheme is given, select an | 2618 | /* |
2542 | * appropriate one */ | 2619 | * If no default placement scheme is given, select an appropriate one |
2620 | */ | ||
2543 | if (!this->autooob) { | 2621 | if (!this->autooob) { |
2544 | /* Select the appropriate default oob placement scheme for | ||
2545 | * placement agnostic filesystems */ | ||
2546 | switch (mtd->oobsize) { | 2622 | switch (mtd->oobsize) { |
2547 | case 8: | 2623 | case 8: |
2548 | this->autooob = &nand_oob_8; | 2624 | this->autooob = &nand_oob_8; |
@@ -2554,111 +2630,73 @@ int nand_scan(struct mtd_info *mtd, int maxchips) | |||
2554 | this->autooob = &nand_oob_64; | 2630 | this->autooob = &nand_oob_64; |
2555 | break; | 2631 | break; |
2556 | default: | 2632 | default: |
2557 | printk(KERN_WARNING "No oob scheme defined for oobsize %d\n", mtd->oobsize); | 2633 | printk(KERN_WARNING "No oob scheme defined for " |
2634 | "oobsize %d\n", mtd->oobsize); | ||
2558 | BUG(); | 2635 | BUG(); |
2559 | } | 2636 | } |
2560 | } | 2637 | } |
2561 | 2638 | ||
2562 | /* The number of bytes available for the filesystem to place fs dependend | 2639 | /* |
2563 | * oob data */ | 2640 | * The number of bytes available for the filesystem to place fs |
2641 | * dependend oob data | ||
2642 | */ | ||
2564 | mtd->oobavail = 0; | 2643 | mtd->oobavail = 0; |
2565 | for (i = 0; this->autooob->oobfree[i][1]; i++) | 2644 | for (i = 0; this->autooob->oobfree[i][1]; i++) |
2566 | mtd->oobavail += this->autooob->oobfree[i][1]; | 2645 | mtd->oobavail += this->autooob->oobfree[i][1]; |
2567 | 2646 | ||
2568 | /* | 2647 | /* |
2569 | * check ECC mode, default to software | 2648 | * check ECC mode, default to software if 3byte/512byte hardware ECC is |
2570 | * if 3byte/512byte hardware ECC is selected and we have 256 byte pagesize | 2649 | * selected and we have 256 byte pagesize fallback to software ECC |
2571 | * fallback to software ECC | ||
2572 | */ | 2650 | */ |
2573 | this->eccsize = 256; /* set default eccsize */ | 2651 | switch (this->ecc.mode) { |
2574 | this->eccbytes = 3; | 2652 | case NAND_ECC_HW: |
2575 | 2653 | case NAND_ECC_HW_SYNDROME: | |
2576 | switch (this->eccmode) { | 2654 | if (!this->ecc.calculate || !this->ecc.correct || |
2577 | case NAND_ECC_HW12_2048: | 2655 | !this->ecc.hwctl) { |
2578 | if (mtd->writesize < 2048) { | 2656 | printk(KERN_WARNING "No ECC functions supplied, " |
2579 | printk(KERN_WARNING "2048 byte HW ECC not possible on %d byte page size, fallback to SW ECC\n", | 2657 | "Hardware ECC not possible\n"); |
2580 | mtd->writesize); | 2658 | BUG(); |
2581 | this->eccmode = NAND_ECC_SOFT; | 2659 | } |
2582 | this->calculate_ecc = nand_calculate_ecc; | 2660 | if (mtd->writesize >= this->ecc.size) |
2583 | this->correct_data = nand_correct_data; | 2661 | break; |
2584 | } else | 2662 | printk(KERN_WARNING "%d byte HW ECC not possible on " |
2585 | this->eccsize = 2048; | 2663 | "%d byte page size, fallback to SW ECC\n", |
2586 | break; | 2664 | this->ecc.size, mtd->writesize); |
2587 | 2665 | this->ecc.mode = NAND_ECC_SOFT; | |
2588 | case NAND_ECC_HW3_512: | ||
2589 | case NAND_ECC_HW6_512: | ||
2590 | case NAND_ECC_HW8_512: | ||
2591 | if (mtd->writesize == 256) { | ||
2592 | printk(KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n"); | ||
2593 | this->eccmode = NAND_ECC_SOFT; | ||
2594 | this->calculate_ecc = nand_calculate_ecc; | ||
2595 | this->correct_data = nand_correct_data; | ||
2596 | } else | ||
2597 | this->eccsize = 512; /* set eccsize to 512 */ | ||
2598 | break; | ||
2599 | 2666 | ||
2600 | case NAND_ECC_HW3_256: | 2667 | case NAND_ECC_SOFT: |
2668 | this->ecc.calculate = nand_calculate_ecc; | ||
2669 | this->ecc.correct = nand_correct_data; | ||
2670 | this->ecc.size = 256; | ||
2671 | this->ecc.bytes = 3; | ||
2601 | break; | 2672 | break; |
2602 | 2673 | ||
2603 | case NAND_ECC_NONE: | 2674 | case NAND_ECC_NONE: |
2604 | printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. This is not recommended !!\n"); | 2675 | printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. " |
2605 | this->eccmode = NAND_ECC_NONE; | 2676 | "This is not recommended !!\n"); |
2606 | break; | 2677 | this->ecc.size = mtd->writesize; |
2607 | 2678 | this->ecc.bytes = 0; | |
2608 | case NAND_ECC_SOFT: | ||
2609 | this->calculate_ecc = nand_calculate_ecc; | ||
2610 | this->correct_data = nand_correct_data; | ||
2611 | break; | 2679 | break; |
2612 | |||
2613 | default: | 2680 | default: |
2614 | printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode); | 2681 | printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n", |
2682 | this->ecc.mode); | ||
2615 | BUG(); | 2683 | BUG(); |
2616 | } | 2684 | } |
2617 | 2685 | ||
2618 | /* Check hardware ecc function availability and adjust number of ecc bytes per | 2686 | /* |
2619 | * calculation step | 2687 | * Set the number of read / write steps for one page depending on ECC |
2688 | * mode | ||
2620 | */ | 2689 | */ |
2621 | switch (this->eccmode) { | 2690 | this->ecc.steps = mtd->writesize / this->ecc.size; |
2622 | case NAND_ECC_HW12_2048: | 2691 | if(this->ecc.steps * this->ecc.size != mtd->writesize) { |
2623 | this->eccbytes += 4; | 2692 | printk(KERN_WARNING "Invalid ecc parameters\n"); |
2624 | case NAND_ECC_HW8_512: | ||
2625 | this->eccbytes += 2; | ||
2626 | case NAND_ECC_HW6_512: | ||
2627 | this->eccbytes += 3; | ||
2628 | case NAND_ECC_HW3_512: | ||
2629 | case NAND_ECC_HW3_256: | ||
2630 | if (this->calculate_ecc && this->correct_data && this->enable_hwecc) | ||
2631 | break; | ||
2632 | printk(KERN_WARNING "No ECC functions supplied, Hardware ECC not possible\n"); | ||
2633 | BUG(); | 2693 | BUG(); |
2634 | } | 2694 | } |
2635 | 2695 | ||
2636 | mtd->eccsize = this->eccsize; | ||
2637 | |||
2638 | /* Set the number of read / write steps for one page to ensure ECC generation */ | ||
2639 | switch (this->eccmode) { | ||
2640 | case NAND_ECC_HW12_2048: | ||
2641 | this->eccsteps = mtd->writesize / 2048; | ||
2642 | break; | ||
2643 | case NAND_ECC_HW3_512: | ||
2644 | case NAND_ECC_HW6_512: | ||
2645 | case NAND_ECC_HW8_512: | ||
2646 | this->eccsteps = mtd->writesize / 512; | ||
2647 | break; | ||
2648 | case NAND_ECC_HW3_256: | ||
2649 | case NAND_ECC_SOFT: | ||
2650 | this->eccsteps = mtd->writesize / 256; | ||
2651 | break; | ||
2652 | |||
2653 | case NAND_ECC_NONE: | ||
2654 | this->eccsteps = 1; | ||
2655 | break; | ||
2656 | } | ||
2657 | |||
2658 | /* Initialize state, waitqueue and spinlock */ | 2696 | /* Initialize state, waitqueue and spinlock */ |
2659 | this->state = FL_READY; | 2697 | this->state = FL_READY; |
2660 | init_waitqueue_head(&this->wq); | 2698 | init_waitqueue_head(&this->controller->wq); |
2661 | spin_lock_init(&this->chip_lock); | 2699 | spin_lock_init(&this->controller->lock); |
2662 | 2700 | ||
2663 | /* De-select the device */ | 2701 | /* De-select the device */ |
2664 | this->select_chip(mtd, -1); | 2702 | this->select_chip(mtd, -1); |
@@ -2718,12 +2756,8 @@ void nand_release(struct mtd_info *mtd) | |||
2718 | 2756 | ||
2719 | /* Free bad block table memory */ | 2757 | /* Free bad block table memory */ |
2720 | kfree(this->bbt); | 2758 | kfree(this->bbt); |
2721 | /* Buffer allocated by nand_scan ? */ | 2759 | /* Free buffers */ |
2722 | if (this->options & NAND_OOBBUF_ALLOC) | 2760 | nand_free_kmem(this); |
2723 | kfree(this->oob_buf); | ||
2724 | /* Buffer allocated by nand_scan ? */ | ||
2725 | if (this->options & NAND_DATABUF_ALLOC) | ||
2726 | kfree(this->data_buf); | ||
2727 | } | 2761 | } |
2728 | 2762 | ||
2729 | EXPORT_SYMBOL_GPL(nand_scan); | 2763 | EXPORT_SYMBOL_GPL(nand_scan); |
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c index 101892985b02..2a163e4084df 100644 --- a/drivers/mtd/nand/nand_ecc.c +++ b/drivers/mtd/nand/nand_ecc.c | |||
@@ -7,6 +7,8 @@ | |||
7 | * Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com) | 7 | * Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com) |
8 | * Toshiba America Electronics Components, Inc. | 8 | * Toshiba America Electronics Components, Inc. |
9 | * | 9 | * |
10 | * Copyright (C) 2006 Thomas Gleixner <tglx@linutronix.de> | ||
11 | * | ||
10 | * $Id: nand_ecc.c,v 1.15 2005/11/07 11:14:30 gleixner Exp $ | 12 | * $Id: nand_ecc.c,v 1.15 2005/11/07 11:14:30 gleixner Exp $ |
11 | * | 13 | * |
12 | * This file is free software; you can redistribute it and/or modify it | 14 | * This file is free software; you can redistribute it and/or modify it |
@@ -63,87 +65,75 @@ static const u_char nand_ecc_precalc_table[] = { | |||
63 | }; | 65 | }; |
64 | 66 | ||
65 | /** | 67 | /** |
66 | * nand_trans_result - [GENERIC] create non-inverted ECC | 68 | * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code |
67 | * @reg2: line parity reg 2 | 69 | * for 256 byte block |
68 | * @reg3: line parity reg 3 | ||
69 | * @ecc_code: ecc | ||
70 | * | ||
71 | * Creates non-inverted ECC code from line parity | ||
72 | */ | ||
73 | static void nand_trans_result(u_char reg2, u_char reg3, u_char *ecc_code) | ||
74 | { | ||
75 | u_char a, b, i, tmp1, tmp2; | ||
76 | |||
77 | /* Initialize variables */ | ||
78 | a = b = 0x80; | ||
79 | tmp1 = tmp2 = 0; | ||
80 | |||
81 | /* Calculate first ECC byte */ | ||
82 | for (i = 0; i < 4; i++) { | ||
83 | if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */ | ||
84 | tmp1 |= b; | ||
85 | b >>= 1; | ||
86 | if (reg2 & a) /* LP14,12,10,8 --> ecc_code[0] */ | ||
87 | tmp1 |= b; | ||
88 | b >>= 1; | ||
89 | a >>= 1; | ||
90 | } | ||
91 | |||
92 | /* Calculate second ECC byte */ | ||
93 | b = 0x80; | ||
94 | for (i = 0; i < 4; i++) { | ||
95 | if (reg3 & a) /* LP7,5,3,1 --> ecc_code[1] */ | ||
96 | tmp2 |= b; | ||
97 | b >>= 1; | ||
98 | if (reg2 & a) /* LP6,4,2,0 --> ecc_code[1] */ | ||
99 | tmp2 |= b; | ||
100 | b >>= 1; | ||
101 | a >>= 1; | ||
102 | } | ||
103 | |||
104 | /* Store two of the ECC bytes */ | ||
105 | ecc_code[0] = tmp1; | ||
106 | ecc_code[1] = tmp2; | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code for 256 byte block | ||
111 | * @mtd: MTD block structure | 70 | * @mtd: MTD block structure |
112 | * @dat: raw data | 71 | * @dat: raw data |
113 | * @ecc_code: buffer for ECC | 72 | * @ecc_code: buffer for ECC |
114 | */ | 73 | */ |
115 | int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) | 74 | int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, |
75 | u_char *ecc_code) | ||
116 | { | 76 | { |
117 | u_char idx, reg1, reg2, reg3; | 77 | uint8_t idx, reg1, reg2, reg3, tmp1, tmp2; |
118 | int j; | 78 | int i; |
119 | 79 | ||
120 | /* Initialize variables */ | 80 | /* Initialize variables */ |
121 | reg1 = reg2 = reg3 = 0; | 81 | reg1 = reg2 = reg3 = 0; |
122 | ecc_code[0] = ecc_code[1] = ecc_code[2] = 0; | ||
123 | 82 | ||
124 | /* Build up column parity */ | 83 | /* Build up column parity */ |
125 | for (j = 0; j < 256; j++) { | 84 | for(i = 0; i < 256; i++) { |
126 | |||
127 | /* Get CP0 - CP5 from table */ | 85 | /* Get CP0 - CP5 from table */ |
128 | idx = nand_ecc_precalc_table[dat[j]]; | 86 | idx = nand_ecc_precalc_table[*dat++]; |
129 | reg1 ^= (idx & 0x3f); | 87 | reg1 ^= (idx & 0x3f); |
130 | 88 | ||
131 | /* All bit XOR = 1 ? */ | 89 | /* All bit XOR = 1 ? */ |
132 | if (idx & 0x40) { | 90 | if (idx & 0x40) { |
133 | reg3 ^= (u_char) j; | 91 | reg3 ^= (uint8_t) i; |
134 | reg2 ^= ~((u_char) j); | 92 | reg2 ^= ~((uint8_t) i); |
135 | } | 93 | } |
136 | } | 94 | } |
137 | 95 | ||
138 | /* Create non-inverted ECC code from line parity */ | 96 | /* Create non-inverted ECC code from line parity */ |
139 | nand_trans_result(reg2, reg3, ecc_code); | 97 | tmp1 = (reg3 & 0x80) >> 0; /* B7 -> B7 */ |
98 | tmp1 |= (reg2 & 0x80) >> 1; /* B7 -> B6 */ | ||
99 | tmp1 |= (reg3 & 0x40) >> 1; /* B6 -> B5 */ | ||
100 | tmp1 |= (reg2 & 0x40) >> 2; /* B6 -> B4 */ | ||
101 | tmp1 |= (reg3 & 0x20) >> 2; /* B5 -> B3 */ | ||
102 | tmp1 |= (reg2 & 0x20) >> 3; /* B5 -> B2 */ | ||
103 | tmp1 |= (reg3 & 0x10) >> 3; /* B4 -> B1 */ | ||
104 | tmp1 |= (reg2 & 0x10) >> 4; /* B4 -> B0 */ | ||
105 | |||
106 | tmp2 = (reg3 & 0x08) << 4; /* B3 -> B7 */ | ||
107 | tmp2 |= (reg2 & 0x08) << 3; /* B3 -> B6 */ | ||
108 | tmp2 |= (reg3 & 0x04) << 3; /* B2 -> B5 */ | ||
109 | tmp2 |= (reg2 & 0x04) << 2; /* B2 -> B4 */ | ||
110 | tmp2 |= (reg3 & 0x02) << 2; /* B1 -> B3 */ | ||
111 | tmp2 |= (reg2 & 0x02) << 1; /* B1 -> B2 */ | ||
112 | tmp2 |= (reg3 & 0x01) << 1; /* B0 -> B1 */ | ||
113 | tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */ | ||
140 | 114 | ||
141 | /* Calculate final ECC code */ | 115 | /* Calculate final ECC code */ |
142 | ecc_code[0] = ~ecc_code[0]; | 116 | #ifdef CONFIG_NAND_ECC_SMC |
143 | ecc_code[1] = ~ecc_code[1]; | 117 | ecc_code[0] = ~tmp2; |
118 | ecc_code[1] = ~tmp1; | ||
119 | #else | ||
120 | ecc_code[0] = ~tmp1; | ||
121 | ecc_code[1] = ~tmp2; | ||
122 | #endif | ||
144 | ecc_code[2] = ((~reg1) << 2) | 0x03; | 123 | ecc_code[2] = ((~reg1) << 2) | 0x03; |
124 | |||
145 | return 0; | 125 | return 0; |
146 | } | 126 | } |
127 | EXPORT_SYMBOL(nand_calculate_ecc); | ||
128 | |||
129 | static inline int countbits(uint32_t byte) | ||
130 | { | ||
131 | int res = 0; | ||
132 | |||
133 | for (;byte; byte >>= 1) | ||
134 | res += byte & 0x01; | ||
135 | return res; | ||
136 | } | ||
147 | 137 | ||
148 | /** | 138 | /** |
149 | * nand_correct_data - [NAND Interface] Detect and correct bit error(s) | 139 | * nand_correct_data - [NAND Interface] Detect and correct bit error(s) |
@@ -154,90 +144,54 @@ int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code | |||
154 | * | 144 | * |
155 | * Detect and correct a 1 bit error for 256 byte block | 145 | * Detect and correct a 1 bit error for 256 byte block |
156 | */ | 146 | */ |
157 | int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) | 147 | int nand_correct_data(struct mtd_info *mtd, u_char *dat, |
148 | u_char *read_ecc, u_char *calc_ecc) | ||
158 | { | 149 | { |
159 | u_char a, b, c, d1, d2, d3, add, bit, i; | 150 | uint8_t s0, s1, s2; |
151 | |||
152 | #ifdef CONFIG_NAND_ECC_SMC | ||
153 | s0 = calc_ecc[0] ^ read_ecc[0]; | ||
154 | s1 = calc_ecc[1] ^ read_ecc[1]; | ||
155 | s2 = calc_ecc[2] ^ read_ecc[2]; | ||
156 | #else | ||
157 | s1 = calc_ecc[0] ^ read_ecc[0]; | ||
158 | s0 = calc_ecc[1] ^ read_ecc[1]; | ||
159 | s2 = calc_ecc[2] ^ read_ecc[2]; | ||
160 | #endif | ||
161 | if ((s0 | s1 | s2) == 0) | ||
162 | return 0; | ||
160 | 163 | ||
161 | /* Do error detection */ | 164 | /* Check for a single bit error */ |
162 | d1 = calc_ecc[0] ^ read_ecc[0]; | 165 | if( ((s0 ^ (s0 >> 1)) & 0x55) == 0x55 && |
163 | d2 = calc_ecc[1] ^ read_ecc[1]; | 166 | ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 && |
164 | d3 = calc_ecc[2] ^ read_ecc[2]; | 167 | ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) { |
165 | 168 | ||
166 | if ((d1 | d2 | d3) == 0) { | 169 | uint32_t byteoffs, bitnum; |
167 | /* No errors */ | 170 | |
168 | return 0; | 171 | byteoffs = (s1 << 0) & 0x80; |
169 | } else { | 172 | byteoffs |= (s1 << 1) & 0x40; |
170 | a = (d1 ^ (d1 >> 1)) & 0x55; | 173 | byteoffs |= (s1 << 2) & 0x20; |
171 | b = (d2 ^ (d2 >> 1)) & 0x55; | 174 | byteoffs |= (s1 << 3) & 0x10; |
172 | c = (d3 ^ (d3 >> 1)) & 0x54; | 175 | |
173 | 176 | byteoffs |= (s0 >> 4) & 0x08; | |
174 | /* Found and will correct single bit error in the data */ | 177 | byteoffs |= (s0 >> 3) & 0x04; |
175 | if ((a == 0x55) && (b == 0x55) && (c == 0x54)) { | 178 | byteoffs |= (s0 >> 2) & 0x02; |
176 | c = 0x80; | 179 | byteoffs |= (s0 >> 1) & 0x01; |
177 | add = 0; | 180 | |
178 | a = 0x80; | 181 | bitnum = (s2 >> 5) & 0x04; |
179 | for (i = 0; i < 4; i++) { | 182 | bitnum |= (s2 >> 4) & 0x02; |
180 | if (d1 & c) | 183 | bitnum |= (s2 >> 3) & 0x01; |
181 | add |= a; | 184 | |
182 | c >>= 2; | 185 | dat[byteoffs] ^= (1 << bitnum); |
183 | a >>= 1; | 186 | |
184 | } | 187 | return 1; |
185 | c = 0x80; | ||
186 | for (i = 0; i < 4; i++) { | ||
187 | if (d2 & c) | ||
188 | add |= a; | ||
189 | c >>= 2; | ||
190 | a >>= 1; | ||
191 | } | ||
192 | bit = 0; | ||
193 | b = 0x04; | ||
194 | c = 0x80; | ||
195 | for (i = 0; i < 3; i++) { | ||
196 | if (d3 & c) | ||
197 | bit |= b; | ||
198 | c >>= 2; | ||
199 | b >>= 1; | ||
200 | } | ||
201 | b = 0x01; | ||
202 | a = dat[add]; | ||
203 | a ^= (b << bit); | ||
204 | dat[add] = a; | ||
205 | return 1; | ||
206 | } else { | ||
207 | i = 0; | ||
208 | while (d1) { | ||
209 | if (d1 & 0x01) | ||
210 | ++i; | ||
211 | d1 >>= 1; | ||
212 | } | ||
213 | while (d2) { | ||
214 | if (d2 & 0x01) | ||
215 | ++i; | ||
216 | d2 >>= 1; | ||
217 | } | ||
218 | while (d3) { | ||
219 | if (d3 & 0x01) | ||
220 | ++i; | ||
221 | d3 >>= 1; | ||
222 | } | ||
223 | if (i == 1) { | ||
224 | /* ECC Code Error Correction */ | ||
225 | read_ecc[0] = calc_ecc[0]; | ||
226 | read_ecc[1] = calc_ecc[1]; | ||
227 | read_ecc[2] = calc_ecc[2]; | ||
228 | return 2; | ||
229 | } else { | ||
230 | /* Uncorrectable Error */ | ||
231 | return -1; | ||
232 | } | ||
233 | } | ||
234 | } | 188 | } |
235 | 189 | ||
236 | /* Should never happen */ | 190 | if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1) |
191 | return 1; | ||
192 | |||
237 | return -1; | 193 | return -1; |
238 | } | 194 | } |
239 | |||
240 | EXPORT_SYMBOL(nand_calculate_ecc); | ||
241 | EXPORT_SYMBOL(nand_correct_data); | 195 | EXPORT_SYMBOL(nand_correct_data); |
242 | 196 | ||
243 | MODULE_LICENSE("GPL"); | 197 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 8674f1e9d3c6..22af9b29d2bf 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c | |||
@@ -1523,7 +1523,7 @@ static int __init ns_init_module(void) | |||
1523 | chip->verify_buf = ns_nand_verify_buf; | 1523 | chip->verify_buf = ns_nand_verify_buf; |
1524 | chip->write_word = ns_nand_write_word; | 1524 | chip->write_word = ns_nand_write_word; |
1525 | chip->read_word = ns_nand_read_word; | 1525 | chip->read_word = ns_nand_read_word; |
1526 | chip->eccmode = NAND_ECC_SOFT; | 1526 | chip->ecc.mode = NAND_ECC_SOFT; |
1527 | chip->options |= NAND_SKIP_BBTSCAN; | 1527 | chip->options |= NAND_SKIP_BBTSCAN; |
1528 | 1528 | ||
1529 | /* | 1529 | /* |
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c new file mode 100644 index 000000000000..e2dc81de106a --- /dev/null +++ b/drivers/mtd/nand/ndfc.c | |||
@@ -0,0 +1,319 @@ | |||
1 | /* | ||
2 | * drivers/mtd/ndfc.c | ||
3 | * | ||
4 | * Overview: | ||
5 | * Platform independend driver for NDFC (NanD Flash Controller) | ||
6 | * integrated into EP440 cores | ||
7 | * | ||
8 | * Author: Thomas Gleixner | ||
9 | * | ||
10 | * Copyright 2006 IBM | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | * | ||
17 | */ | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/mtd/nand.h> | ||
20 | #include <linux/mtd/nand_ecc.h> | ||
21 | #include <linux/mtd/partitions.h> | ||
22 | #include <linux/mtd/ndfc.h> | ||
23 | #include <linux/mtd/ubi.h> | ||
24 | #include <linux/mtd/mtd.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | |||
27 | #include <asm/io.h> | ||
28 | #include <asm/ibm44x.h> | ||
29 | |||
30 | struct ndfc_nand_mtd { | ||
31 | struct mtd_info mtd; | ||
32 | struct nand_chip chip; | ||
33 | struct platform_nand_chip *pl_chip; | ||
34 | }; | ||
35 | |||
36 | static struct ndfc_nand_mtd ndfc_mtd[NDFC_MAX_BANKS]; | ||
37 | |||
38 | struct ndfc_controller { | ||
39 | void __iomem *ndfcbase; | ||
40 | struct nand_hw_control ndfc_control; | ||
41 | atomic_t childs_active; | ||
42 | }; | ||
43 | |||
44 | static struct ndfc_controller ndfc_ctrl; | ||
45 | |||
46 | static void ndfc_select_chip(struct mtd_info *mtd, int chip) | ||
47 | { | ||
48 | uint32_t ccr; | ||
49 | struct ndfc_controller *ndfc = &ndfc_ctrl; | ||
50 | struct nand_chip *nandchip = mtd->priv; | ||
51 | struct ndfc_nand_mtd *nandmtd = nandchip->priv; | ||
52 | struct platform_nand_chip *pchip = nandmtd->pl_chip; | ||
53 | |||
54 | ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR); | ||
55 | if (chip >= 0) { | ||
56 | ccr &= ~NDFC_CCR_BS_MASK; | ||
57 | ccr |= NDFC_CCR_BS(chip + pchip->chip_offset); | ||
58 | } else | ||
59 | ccr |= NDFC_CCR_RESET_CE; | ||
60 | writel(ccr, ndfc->ndfcbase + NDFC_CCR); | ||
61 | } | ||
62 | |||
63 | static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd) | ||
64 | { | ||
65 | struct ndfc_controller *ndfc = &ndfc_ctrl; | ||
66 | struct nand_chip *chip = mtd->priv; | ||
67 | |||
68 | switch (cmd) { | ||
69 | case NAND_CTL_SETCLE: | ||
70 | chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_CMD; | ||
71 | break; | ||
72 | case NAND_CTL_SETALE: | ||
73 | chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_ALE; | ||
74 | break; | ||
75 | default: | ||
76 | chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA; | ||
77 | break; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | static int ndfc_ready(struct mtd_info *mtd) | ||
82 | { | ||
83 | struct ndfc_controller *ndfc = &ndfc_ctrl; | ||
84 | |||
85 | return __raw_readl(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY; | ||
86 | } | ||
87 | |||
88 | static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode) | ||
89 | { | ||
90 | uint32_t ccr; | ||
91 | struct ndfc_controller *ndfc = &ndfc_ctrl; | ||
92 | |||
93 | ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR); | ||
94 | ccr |= NDFC_CCR_RESET_ECC; | ||
95 | __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR); | ||
96 | wmb(); | ||
97 | } | ||
98 | |||
99 | static int ndfc_calculate_ecc(struct mtd_info *mtd, | ||
100 | const u_char *dat, u_char *ecc_code) | ||
101 | { | ||
102 | struct ndfc_controller *ndfc = &ndfc_ctrl; | ||
103 | uint32_t ecc; | ||
104 | uint8_t *p = (uint8_t *)&ecc; | ||
105 | |||
106 | wmb(); | ||
107 | ecc = __raw_readl(ndfc->ndfcbase + NDFC_ECC); | ||
108 | ecc_code[0] = p[1]; | ||
109 | ecc_code[1] = p[2]; | ||
110 | ecc_code[2] = p[3]; | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | /* | ||
116 | * Speedups for buffer read/write/verify | ||
117 | * | ||
118 | * NDFC allows 32bit read/write of data. So we can speed up the buffer | ||
119 | * functions. No further checking, as nand_base will always read/write | ||
120 | * page aligned. | ||
121 | */ | ||
122 | static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | ||
123 | { | ||
124 | struct ndfc_controller *ndfc = &ndfc_ctrl; | ||
125 | uint32_t *p = (uint32_t *) buf; | ||
126 | |||
127 | for(;len > 0; len -= 4) | ||
128 | *p++ = __raw_readl(ndfc->ndfcbase + NDFC_DATA); | ||
129 | } | ||
130 | |||
131 | static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | ||
132 | { | ||
133 | struct ndfc_controller *ndfc = &ndfc_ctrl; | ||
134 | uint32_t *p = (uint32_t *) buf; | ||
135 | |||
136 | for(;len > 0; len -= 4) | ||
137 | __raw_writel(*p++, ndfc->ndfcbase + NDFC_DATA); | ||
138 | } | ||
139 | |||
140 | static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | ||
141 | { | ||
142 | struct ndfc_controller *ndfc = &ndfc_ctrl; | ||
143 | uint32_t *p = (uint32_t *) buf; | ||
144 | |||
145 | for(;len > 0; len -= 4) | ||
146 | if (*p++ != __raw_readl(ndfc->ndfcbase + NDFC_DATA)) | ||
147 | return -EFAULT; | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | /* | ||
152 | * Initialize chip structure | ||
153 | */ | ||
154 | static void ndfc_chip_init(struct ndfc_nand_mtd *mtd) | ||
155 | { | ||
156 | struct ndfc_controller *ndfc = &ndfc_ctrl; | ||
157 | struct nand_chip *chip = &mtd->chip; | ||
158 | |||
159 | chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA; | ||
160 | chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA; | ||
161 | chip->hwcontrol = ndfc_hwcontrol; | ||
162 | chip->dev_ready = ndfc_ready; | ||
163 | chip->select_chip = ndfc_select_chip; | ||
164 | chip->chip_delay = 50; | ||
165 | chip->priv = mtd; | ||
166 | chip->options = mtd->pl_chip->options; | ||
167 | chip->controller = &ndfc->ndfc_control; | ||
168 | chip->read_buf = ndfc_read_buf; | ||
169 | chip->write_buf = ndfc_write_buf; | ||
170 | chip->verify_buf = ndfc_verify_buf; | ||
171 | chip->ecc.correct = nand_correct_data; | ||
172 | chip->ecc.hwctl = ndfc_enable_hwecc; | ||
173 | chip->ecc.calculate = ndfc_calculate_ecc; | ||
174 | chip->ecc.mode = NAND_ECC_HW; | ||
175 | chip->ecc.size = 256; | ||
176 | chip->ecc.bytes = 3; | ||
177 | chip->autooob = mtd->pl_chip->autooob; | ||
178 | mtd->mtd.priv = chip; | ||
179 | mtd->mtd.owner = THIS_MODULE; | ||
180 | } | ||
181 | |||
182 | static int ndfc_chip_probe(struct platform_device *pdev) | ||
183 | { | ||
184 | int rc; | ||
185 | struct platform_nand_chip *nc = pdev->dev.platform_data; | ||
186 | struct ndfc_chip_settings *settings = nc->priv; | ||
187 | struct ndfc_controller *ndfc = &ndfc_ctrl; | ||
188 | struct ndfc_nand_mtd *nandmtd; | ||
189 | |||
190 | if (nc->chip_offset >= NDFC_MAX_BANKS || nc->nr_chips > NDFC_MAX_BANKS) | ||
191 | return -EINVAL; | ||
192 | |||
193 | /* Set the bank settings */ | ||
194 | __raw_writel(settings->bank_settings, | ||
195 | ndfc->ndfcbase + NDFC_BCFG0 + (nc->chip_offset << 2)); | ||
196 | |||
197 | nandmtd = &ndfc_mtd[pdev->id]; | ||
198 | if (nandmtd->pl_chip) | ||
199 | return -EBUSY; | ||
200 | |||
201 | nandmtd->pl_chip = nc; | ||
202 | ndfc_chip_init(nandmtd); | ||
203 | |||
204 | /* Scan for chips */ | ||
205 | if (nand_scan(&nandmtd->mtd, nc->nr_chips)) { | ||
206 | nandmtd->pl_chip = NULL; | ||
207 | return -ENODEV; | ||
208 | } | ||
209 | |||
210 | #ifdef CONFIG_MTD_PARTITIONS | ||
211 | printk("Number of partitions %d\n", nc->nr_partitions); | ||
212 | if (nc->nr_partitions) { | ||
213 | struct mtd_info *mtd_ubi; | ||
214 | nc->partitions[NAND_PARTS_CONTENT_IDX].mtdp = &mtd_ubi; | ||
215 | |||
216 | add_mtd_device(&nandmtd->mtd); /* for testing */ | ||
217 | add_mtd_partitions(&nandmtd->mtd, | ||
218 | nc->partitions, | ||
219 | nc->nr_partitions); | ||
220 | |||
221 | add_mtd_device(mtd_ubi); | ||
222 | |||
223 | } else | ||
224 | #else | ||
225 | add_mtd_device(&nandmtd->mtd); | ||
226 | #endif | ||
227 | |||
228 | atomic_inc(&ndfc->childs_active); | ||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static int ndfc_chip_remove(struct platform_device *pdev) | ||
233 | { | ||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | static int ndfc_nand_probe(struct platform_device *pdev) | ||
238 | { | ||
239 | struct platform_nand_ctrl *nc = pdev->dev.platform_data; | ||
240 | struct ndfc_controller_settings *settings = nc->priv; | ||
241 | struct resource *res = pdev->resource; | ||
242 | struct ndfc_controller *ndfc = &ndfc_ctrl; | ||
243 | unsigned long long phys = NDFC_PHYSADDR_OFFS | res->start; | ||
244 | |||
245 | ndfc->ndfcbase = ioremap64(phys, res->end - res->start + 1); | ||
246 | if (!ndfc->ndfcbase) { | ||
247 | printk(KERN_ERR "NDFC: ioremap failed\n"); | ||
248 | return -EIO; | ||
249 | } | ||
250 | |||
251 | __raw_writel(settings->ccr_settings, ndfc->ndfcbase + NDFC_CCR); | ||
252 | |||
253 | spin_lock_init(&ndfc->ndfc_control.lock); | ||
254 | init_waitqueue_head(&ndfc->ndfc_control.wq); | ||
255 | |||
256 | platform_set_drvdata(pdev, ndfc); | ||
257 | |||
258 | printk("NDFC NAND Driver initialized. Chip-Rev: 0x%08x\n", | ||
259 | __raw_readl(ndfc->ndfcbase + NDFC_REVID)); | ||
260 | |||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | static int ndfc_nand_remove(struct platform_device *pdev) | ||
265 | { | ||
266 | struct ndfc_controller *ndfc = platform_get_drvdata(pdev); | ||
267 | |||
268 | if (atomic_read(&ndfc->childs_active)) | ||
269 | return -EBUSY; | ||
270 | |||
271 | if (ndfc) { | ||
272 | platform_set_drvdata(pdev, NULL); | ||
273 | iounmap(ndfc_ctrl.ndfcbase); | ||
274 | ndfc_ctrl.ndfcbase = NULL; | ||
275 | } | ||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | /* driver device registration */ | ||
280 | |||
281 | static struct platform_driver ndfc_chip_driver = { | ||
282 | .probe = ndfc_chip_probe, | ||
283 | .remove = ndfc_chip_remove, | ||
284 | .driver = { | ||
285 | .name = "ndfc-chip", | ||
286 | .owner = THIS_MODULE, | ||
287 | }, | ||
288 | }; | ||
289 | |||
290 | static struct platform_driver ndfc_nand_driver = { | ||
291 | .probe = ndfc_nand_probe, | ||
292 | .remove = ndfc_nand_remove, | ||
293 | .driver = { | ||
294 | .name = "ndfc-nand", | ||
295 | .owner = THIS_MODULE, | ||
296 | }, | ||
297 | }; | ||
298 | |||
299 | static int __init ndfc_nand_init(void) | ||
300 | { | ||
301 | int ret = platform_driver_register(&ndfc_nand_driver); | ||
302 | |||
303 | if (!ret) | ||
304 | ret = platform_driver_register(&ndfc_chip_driver); | ||
305 | return ret; | ||
306 | } | ||
307 | |||
308 | static void __exit ndfc_nand_exit(void) | ||
309 | { | ||
310 | platform_driver_unregister(&ndfc_chip_driver); | ||
311 | platform_driver_unregister(&ndfc_nand_driver); | ||
312 | } | ||
313 | |||
314 | module_init(ndfc_nand_init); | ||
315 | module_exit(ndfc_nand_exit); | ||
316 | |||
317 | MODULE_LICENSE("GPL"); | ||
318 | MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>"); | ||
319 | MODULE_DESCRIPTION("Platform driver for NDFC"); | ||
diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c index 5d4d16fb1df6..9fab0998524d 100644 --- a/drivers/mtd/nand/ppchameleonevb.c +++ b/drivers/mtd/nand/ppchameleonevb.c | |||
@@ -257,7 +257,7 @@ static int __init ppchameleonevb_init(void) | |||
257 | #endif | 257 | #endif |
258 | this->chip_delay = NAND_BIG_DELAY_US; | 258 | this->chip_delay = NAND_BIG_DELAY_US; |
259 | /* ECC mode */ | 259 | /* ECC mode */ |
260 | this->eccmode = NAND_ECC_SOFT; | 260 | this->ecc.mode = NAND_ECC_SOFT; |
261 | 261 | ||
262 | /* Scan to find existence of the device (it could not be mounted) */ | 262 | /* Scan to find existence of the device (it could not be mounted) */ |
263 | if (nand_scan(ppchameleon_mtd, 1)) { | 263 | if (nand_scan(ppchameleon_mtd, 1)) { |
@@ -358,7 +358,7 @@ static int __init ppchameleonevb_init(void) | |||
358 | this->chip_delay = NAND_SMALL_DELAY_US; | 358 | this->chip_delay = NAND_SMALL_DELAY_US; |
359 | 359 | ||
360 | /* ECC mode */ | 360 | /* ECC mode */ |
361 | this->eccmode = NAND_ECC_SOFT; | 361 | this->ecc.mode = NAND_ECC_SOFT; |
362 | 362 | ||
363 | /* Scan to find existence of the device */ | 363 | /* Scan to find existence of the device */ |
364 | if (nand_scan(ppchameleonevb_mtd, 1)) { | 364 | if (nand_scan(ppchameleonevb_mtd, 1)) { |
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c index 64ccf4c9613f..f8e631c89a60 100644 --- a/drivers/mtd/nand/rtc_from4.c +++ b/drivers/mtd/nand/rtc_from4.c | |||
@@ -570,19 +570,21 @@ static int __init rtc_from4_init(void) | |||
570 | #ifdef RTC_FROM4_HWECC | 570 | #ifdef RTC_FROM4_HWECC |
571 | printk(KERN_INFO "rtc_from4_init: using hardware ECC detection.\n"); | 571 | printk(KERN_INFO "rtc_from4_init: using hardware ECC detection.\n"); |
572 | 572 | ||
573 | this->eccmode = NAND_ECC_HW8_512; | 573 | this->ecc.mode = NAND_ECC_HW_SYNDROME; |
574 | this->ecc.size = 512; | ||
575 | this->ecc.bytes = 8; | ||
574 | this->options |= NAND_HWECC_SYNDROME; | 576 | this->options |= NAND_HWECC_SYNDROME; |
575 | /* return the status of extra status and ECC checks */ | 577 | /* return the status of extra status and ECC checks */ |
576 | this->errstat = rtc_from4_errstat; | 578 | this->errstat = rtc_from4_errstat; |
577 | /* set the nand_oobinfo to support FPGA H/W error detection */ | 579 | /* set the nand_oobinfo to support FPGA H/W error detection */ |
578 | this->autooob = &rtc_from4_nand_oobinfo; | 580 | this->autooob = &rtc_from4_nand_oobinfo; |
579 | this->enable_hwecc = rtc_from4_enable_hwecc; | 581 | this->ecc.hwctl = rtc_from4_enable_hwecc; |
580 | this->calculate_ecc = rtc_from4_calculate_ecc; | 582 | this->ecc.calculate = rtc_from4_calculate_ecc; |
581 | this->correct_data = rtc_from4_correct_data; | 583 | this->ecc.correct = rtc_from4_correct_data; |
582 | #else | 584 | #else |
583 | printk(KERN_INFO "rtc_from4_init: using software ECC detection.\n"); | 585 | printk(KERN_INFO "rtc_from4_init: using software ECC detection.\n"); |
584 | 586 | ||
585 | this->eccmode = NAND_ECC_SOFT; | 587 | this->ecc.mode = NAND_ECC_SOFT; |
586 | #endif | 588 | #endif |
587 | 589 | ||
588 | /* set the bad block tables to support debugging */ | 590 | /* set the bad block tables to support debugging */ |
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index f8002596de8b..608340a25278 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c | |||
@@ -520,18 +520,20 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, | |||
520 | nmtd->set = set; | 520 | nmtd->set = set; |
521 | 521 | ||
522 | if (hardware_ecc) { | 522 | if (hardware_ecc) { |
523 | chip->correct_data = s3c2410_nand_correct_data; | 523 | chip->ecc.correct = s3c2410_nand_correct_data; |
524 | chip->enable_hwecc = s3c2410_nand_enable_hwecc; | 524 | chip->ecc.hwctl = s3c2410_nand_enable_hwecc; |
525 | chip->calculate_ecc = s3c2410_nand_calculate_ecc; | 525 | chip->ecc.calculate = s3c2410_nand_calculate_ecc; |
526 | chip->eccmode = NAND_ECC_HW3_512; | 526 | chip->ecc.mode = NAND_ECC_HW; |
527 | chip->ecc.size = 512; | ||
528 | chip->ecc.bytes = 3; | ||
527 | chip->autooob = &nand_hw_eccoob; | 529 | chip->autooob = &nand_hw_eccoob; |
528 | 530 | ||
529 | if (info->is_s3c2440) { | 531 | if (info->is_s3c2440) { |
530 | chip->enable_hwecc = s3c2440_nand_enable_hwecc; | 532 | chip->ecc.hwctl = s3c2440_nand_enable_hwecc; |
531 | chip->calculate_ecc = s3c2440_nand_calculate_ecc; | 533 | chip->ecc.calculate = s3c2440_nand_calculate_ecc; |
532 | } | 534 | } |
533 | } else { | 535 | } else { |
534 | chip->eccmode = NAND_ECC_SOFT; | 536 | chip->ecc.mode = NAND_ECC_SOFT; |
535 | } | 537 | } |
536 | } | 538 | } |
537 | 539 | ||
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 60e10c0d6980..5554d0b97c8c 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c | |||
@@ -201,15 +201,17 @@ static int __init sharpsl_nand_init(void) | |||
201 | /* 15 us command delay time */ | 201 | /* 15 us command delay time */ |
202 | this->chip_delay = 15; | 202 | this->chip_delay = 15; |
203 | /* set eccmode using hardware ECC */ | 203 | /* set eccmode using hardware ECC */ |
204 | this->eccmode = NAND_ECC_HW3_256; | 204 | this->ecc.mode = NAND_ECC_HW; |
205 | this->ecc.size = 256; | ||
206 | this->ecc.bytes = 3; | ||
205 | this->badblock_pattern = &sharpsl_bbt; | 207 | this->badblock_pattern = &sharpsl_bbt; |
206 | if (machine_is_akita() || machine_is_borzoi()) { | 208 | if (machine_is_akita() || machine_is_borzoi()) { |
207 | this->badblock_pattern = &sharpsl_akita_bbt; | 209 | this->badblock_pattern = &sharpsl_akita_bbt; |
208 | this->autooob = &akita_oobinfo; | 210 | this->autooob = &akita_oobinfo; |
209 | } | 211 | } |
210 | this->enable_hwecc = sharpsl_nand_enable_hwecc; | 212 | this->ecc.hwctl = sharpsl_nand_enable_hwecc; |
211 | this->calculate_ecc = sharpsl_nand_calculate_ecc; | 213 | this->ecc.calculate = sharpsl_nand_calculate_ecc; |
212 | this->correct_data = nand_correct_data; | 214 | this->ecc.correct = nand_correct_data; |
213 | 215 | ||
214 | /* Scan to find existence of the device */ | 216 | /* Scan to find existence of the device */ |
215 | err = nand_scan(sharpsl_mtd, 1); | 217 | err = nand_scan(sharpsl_mtd, 1); |
diff --git a/drivers/mtd/nand/toto.c b/drivers/mtd/nand/toto.c index c51c89559514..50aa6a46911f 100644 --- a/drivers/mtd/nand/toto.c +++ b/drivers/mtd/nand/toto.c | |||
@@ -146,7 +146,7 @@ static int __init toto_init(void) | |||
146 | this->dev_ready = NULL; | 146 | this->dev_ready = NULL; |
147 | /* 25 us command delay time */ | 147 | /* 25 us command delay time */ |
148 | this->chip_delay = 30; | 148 | this->chip_delay = 30; |
149 | this->eccmode = NAND_ECC_SOFT; | 149 | this->ecc.mode = NAND_ECC_SOFT; |
150 | 150 | ||
151 | /* Scan to find existance of the device */ | 151 | /* Scan to find existance of the device */ |
152 | if (nand_scan(toto_mtd, 1)) { | 152 | if (nand_scan(toto_mtd, 1)) { |
diff --git a/drivers/mtd/nand/ts7250.c b/drivers/mtd/nand/ts7250.c index 622db3127f7c..70bce1b0326c 100644 --- a/drivers/mtd/nand/ts7250.c +++ b/drivers/mtd/nand/ts7250.c | |||
@@ -155,7 +155,7 @@ static int __init ts7250_init(void) | |||
155 | this->hwcontrol = ts7250_hwcontrol; | 155 | this->hwcontrol = ts7250_hwcontrol; |
156 | this->dev_ready = ts7250_device_ready; | 156 | this->dev_ready = ts7250_device_ready; |
157 | this->chip_delay = 15; | 157 | this->chip_delay = 15; |
158 | this->eccmode = NAND_ECC_SOFT; | 158 | this->ecc.mode = NAND_ECC_SOFT; |
159 | 159 | ||
160 | printk("Searching for NAND flash...\n"); | 160 | printk("Searching for NAND flash...\n"); |
161 | /* Scan to find existence of the device */ | 161 | /* Scan to find existence of the device */ |