diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-10 16:45:22 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-10 16:45:22 -0500 |
commit | 7b3480f8b701170c046e1ed362946f5f0d005e13 (patch) | |
tree | bd25e05b4f35699689b485480dddf24f840f80af /drivers/mtd/devices | |
parent | 1c8106528aa6bf16b3f457de80df1cf7462a49a4 (diff) | |
parent | b60ef99c1164a8ad346cf41f9e71acfffb6d25a6 (diff) |
Merge tag 'for-linus-3.3' of git://git.infradead.org/mtd-2.6
MTD pull for 3.3
* tag 'for-linus-3.3' of git://git.infradead.org/mtd-2.6: (113 commits)
mtd: Fix dependency for MTD_DOC200x
mtd: do not use mtd->block_markbad directly
logfs: do not use 'mtd->block_isbad' directly
mtd: introduce mtd_can_have_bb helper
mtd: do not use mtd->suspend and mtd->resume directly
mtd: do not use mtd->lock, unlock and is_locked directly
mtd: do not use mtd->sync directly
mtd: harmonize mtd_writev usage
mtd: do not use mtd->lock_user_prot_reg directly
mtd: mtd->write_user_prot_reg directly
mtd: do not use mtd->read_*_prot_reg directly
mtd: do not use mtd->get_*_prot_info directly
mtd: do not use mtd->read_oob directly
mtd: mtdoops: do not use mtd->panic_write directly
romfs: do not use mtd->get_unmapped_area directly
mtd: do not use mtd->get_unmapped_area directly
mtd: do use mtd->point directly
mtd: introduce mtd_has_oob helper
mtd: mtdcore: export symbols cleanup
mtd: clean-up the default_mtd_writev function
...
Fix up trivial edit/remove conflict in drivers/staging/spectra/lld_mtd.c
Diffstat (limited to 'drivers/mtd/devices')
-rw-r--r-- | drivers/mtd/devices/Kconfig | 12 | ||||
-rw-r--r-- | drivers/mtd/devices/block2mtd.c | 2 | ||||
-rw-r--r-- | drivers/mtd/devices/doc2000.c | 9 | ||||
-rw-r--r-- | drivers/mtd/devices/doc2001.c | 8 | ||||
-rw-r--r-- | drivers/mtd/devices/doc2001plus.c | 9 | ||||
-rw-r--r-- | drivers/mtd/devices/docg3.c | 1441 | ||||
-rw-r--r-- | drivers/mtd/devices/docg3.h | 65 | ||||
-rw-r--r-- | drivers/mtd/devices/docprobe.c | 7 | ||||
-rw-r--r-- | drivers/mtd/devices/m25p80.c | 1 | ||||
-rw-r--r-- | drivers/mtd/devices/mtd_dataflash.c | 1 | ||||
-rw-r--r-- | drivers/mtd/devices/sst25l.c | 3 |
11 files changed, 1302 insertions, 256 deletions
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 283d887f7825..37b05c3f2792 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig | |||
@@ -191,6 +191,7 @@ comment "Disk-On-Chip Device Drivers" | |||
191 | 191 | ||
192 | config MTD_DOC2000 | 192 | config MTD_DOC2000 |
193 | tristate "M-Systems Disk-On-Chip 2000 and Millennium (DEPRECATED)" | 193 | tristate "M-Systems Disk-On-Chip 2000 and Millennium (DEPRECATED)" |
194 | depends on MTD_NAND | ||
194 | select MTD_DOCPROBE | 195 | select MTD_DOCPROBE |
195 | select MTD_NAND_IDS | 196 | select MTD_NAND_IDS |
196 | ---help--- | 197 | ---help--- |
@@ -213,6 +214,7 @@ config MTD_DOC2000 | |||
213 | 214 | ||
214 | config MTD_DOC2001 | 215 | config MTD_DOC2001 |
215 | tristate "M-Systems Disk-On-Chip Millennium-only alternative driver (DEPRECATED)" | 216 | tristate "M-Systems Disk-On-Chip Millennium-only alternative driver (DEPRECATED)" |
217 | depends on MTD_NAND | ||
216 | select MTD_DOCPROBE | 218 | select MTD_DOCPROBE |
217 | select MTD_NAND_IDS | 219 | select MTD_NAND_IDS |
218 | ---help--- | 220 | ---help--- |
@@ -234,6 +236,7 @@ config MTD_DOC2001 | |||
234 | 236 | ||
235 | config MTD_DOC2001PLUS | 237 | config MTD_DOC2001PLUS |
236 | tristate "M-Systems Disk-On-Chip Millennium Plus" | 238 | tristate "M-Systems Disk-On-Chip Millennium Plus" |
239 | depends on MTD_NAND | ||
237 | select MTD_DOCPROBE | 240 | select MTD_DOCPROBE |
238 | select MTD_NAND_IDS | 241 | select MTD_NAND_IDS |
239 | ---help--- | 242 | ---help--- |
@@ -251,6 +254,8 @@ config MTD_DOC2001PLUS | |||
251 | 254 | ||
252 | config MTD_DOCG3 | 255 | config MTD_DOCG3 |
253 | tristate "M-Systems Disk-On-Chip G3" | 256 | tristate "M-Systems Disk-On-Chip G3" |
257 | select BCH | ||
258 | select BCH_CONST_PARAMS | ||
254 | ---help--- | 259 | ---help--- |
255 | This provides an MTD device driver for the M-Systems DiskOnChip | 260 | This provides an MTD device driver for the M-Systems DiskOnChip |
256 | G3 devices. | 261 | G3 devices. |
@@ -259,6 +264,13 @@ config MTD_DOCG3 | |||
259 | M-Systems and now Sandisk. The support is very experimental, | 264 | M-Systems and now Sandisk. The support is very experimental, |
260 | and doesn't give access to any write operations. | 265 | and doesn't give access to any write operations. |
261 | 266 | ||
267 | if MTD_DOCG3 | ||
268 | config BCH_CONST_M | ||
269 | default 14 | ||
270 | config BCH_CONST_T | ||
271 | default 4 | ||
272 | endif | ||
273 | |||
262 | config MTD_DOCPROBE | 274 | config MTD_DOCPROBE |
263 | tristate | 275 | tristate |
264 | select MTD_DOCECC | 276 | select MTD_DOCECC |
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index ebeabc727f70..e7e46d1e7463 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c | |||
@@ -287,7 +287,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) | |||
287 | dev->mtd.flags = MTD_CAP_RAM; | 287 | dev->mtd.flags = MTD_CAP_RAM; |
288 | dev->mtd.erase = block2mtd_erase; | 288 | dev->mtd.erase = block2mtd_erase; |
289 | dev->mtd.write = block2mtd_write; | 289 | dev->mtd.write = block2mtd_write; |
290 | dev->mtd.writev = default_mtd_writev; | 290 | dev->mtd.writev = mtd_writev; |
291 | dev->mtd.sync = block2mtd_sync; | 291 | dev->mtd.sync = block2mtd_sync; |
292 | dev->mtd.read = block2mtd_read; | 292 | dev->mtd.read = block2mtd_read; |
293 | dev->mtd.priv = dev; | 293 | dev->mtd.priv = dev; |
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index e9fad9151219..b1cdf6479019 100644 --- a/drivers/mtd/devices/doc2000.c +++ b/drivers/mtd/devices/doc2000.c | |||
@@ -562,23 +562,14 @@ void DoC2k_init(struct mtd_info *mtd) | |||
562 | 562 | ||
563 | mtd->type = MTD_NANDFLASH; | 563 | mtd->type = MTD_NANDFLASH; |
564 | mtd->flags = MTD_CAP_NANDFLASH; | 564 | mtd->flags = MTD_CAP_NANDFLASH; |
565 | mtd->size = 0; | ||
566 | mtd->erasesize = 0; | ||
567 | mtd->writesize = 512; | 565 | mtd->writesize = 512; |
568 | mtd->oobsize = 16; | 566 | mtd->oobsize = 16; |
569 | mtd->owner = THIS_MODULE; | 567 | mtd->owner = THIS_MODULE; |
570 | mtd->erase = doc_erase; | 568 | mtd->erase = doc_erase; |
571 | mtd->point = NULL; | ||
572 | mtd->unpoint = NULL; | ||
573 | mtd->read = doc_read; | 569 | mtd->read = doc_read; |
574 | mtd->write = doc_write; | 570 | mtd->write = doc_write; |
575 | mtd->read_oob = doc_read_oob; | 571 | mtd->read_oob = doc_read_oob; |
576 | mtd->write_oob = doc_write_oob; | 572 | mtd->write_oob = doc_write_oob; |
577 | mtd->sync = NULL; | ||
578 | |||
579 | this->totlen = 0; | ||
580 | this->numchips = 0; | ||
581 | |||
582 | this->curfloor = -1; | 573 | this->curfloor = -1; |
583 | this->curchip = -1; | 574 | this->curchip = -1; |
584 | mutex_init(&this->lock); | 575 | mutex_init(&this->lock); |
diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c index a3f7a27499be..7543b98f46c4 100644 --- a/drivers/mtd/devices/doc2001.c +++ b/drivers/mtd/devices/doc2001.c | |||
@@ -343,25 +343,17 @@ void DoCMil_init(struct mtd_info *mtd) | |||
343 | 343 | ||
344 | mtd->type = MTD_NANDFLASH; | 344 | mtd->type = MTD_NANDFLASH; |
345 | mtd->flags = MTD_CAP_NANDFLASH; | 345 | mtd->flags = MTD_CAP_NANDFLASH; |
346 | mtd->size = 0; | ||
347 | 346 | ||
348 | /* FIXME: erase size is not always 8KiB */ | 347 | /* FIXME: erase size is not always 8KiB */ |
349 | mtd->erasesize = 0x2000; | 348 | mtd->erasesize = 0x2000; |
350 | |||
351 | mtd->writesize = 512; | 349 | mtd->writesize = 512; |
352 | mtd->oobsize = 16; | 350 | mtd->oobsize = 16; |
353 | mtd->owner = THIS_MODULE; | 351 | mtd->owner = THIS_MODULE; |
354 | mtd->erase = doc_erase; | 352 | mtd->erase = doc_erase; |
355 | mtd->point = NULL; | ||
356 | mtd->unpoint = NULL; | ||
357 | mtd->read = doc_read; | 353 | mtd->read = doc_read; |
358 | mtd->write = doc_write; | 354 | mtd->write = doc_write; |
359 | mtd->read_oob = doc_read_oob; | 355 | mtd->read_oob = doc_read_oob; |
360 | mtd->write_oob = doc_write_oob; | 356 | mtd->write_oob = doc_write_oob; |
361 | mtd->sync = NULL; | ||
362 | |||
363 | this->totlen = 0; | ||
364 | this->numchips = 0; | ||
365 | this->curfloor = -1; | 357 | this->curfloor = -1; |
366 | this->curchip = -1; | 358 | this->curchip = -1; |
367 | 359 | ||
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c index 99351bc3e0ed..177510d0e7ee 100644 --- a/drivers/mtd/devices/doc2001plus.c +++ b/drivers/mtd/devices/doc2001plus.c | |||
@@ -467,23 +467,14 @@ void DoCMilPlus_init(struct mtd_info *mtd) | |||
467 | 467 | ||
468 | mtd->type = MTD_NANDFLASH; | 468 | mtd->type = MTD_NANDFLASH; |
469 | mtd->flags = MTD_CAP_NANDFLASH; | 469 | mtd->flags = MTD_CAP_NANDFLASH; |
470 | mtd->size = 0; | ||
471 | |||
472 | mtd->erasesize = 0; | ||
473 | mtd->writesize = 512; | 470 | mtd->writesize = 512; |
474 | mtd->oobsize = 16; | 471 | mtd->oobsize = 16; |
475 | mtd->owner = THIS_MODULE; | 472 | mtd->owner = THIS_MODULE; |
476 | mtd->erase = doc_erase; | 473 | mtd->erase = doc_erase; |
477 | mtd->point = NULL; | ||
478 | mtd->unpoint = NULL; | ||
479 | mtd->read = doc_read; | 474 | mtd->read = doc_read; |
480 | mtd->write = doc_write; | 475 | mtd->write = doc_write; |
481 | mtd->read_oob = doc_read_oob; | 476 | mtd->read_oob = doc_read_oob; |
482 | mtd->write_oob = doc_write_oob; | 477 | mtd->write_oob = doc_write_oob; |
483 | mtd->sync = NULL; | ||
484 | |||
485 | this->totlen = 0; | ||
486 | this->numchips = 0; | ||
487 | this->curfloor = -1; | 478 | this->curfloor = -1; |
488 | this->curchip = -1; | 479 | this->curchip = -1; |
489 | 480 | ||
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c index bdcf5df982e8..ad11ef0a81f4 100644 --- a/drivers/mtd/devices/docg3.c +++ b/drivers/mtd/devices/docg3.c | |||
@@ -29,6 +29,9 @@ | |||
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/mtd/mtd.h> | 30 | #include <linux/mtd/mtd.h> |
31 | #include <linux/mtd/partitions.h> | 31 | #include <linux/mtd/partitions.h> |
32 | #include <linux/bitmap.h> | ||
33 | #include <linux/bitrev.h> | ||
34 | #include <linux/bch.h> | ||
32 | 35 | ||
33 | #include <linux/debugfs.h> | 36 | #include <linux/debugfs.h> |
34 | #include <linux/seq_file.h> | 37 | #include <linux/seq_file.h> |
@@ -41,11 +44,7 @@ | |||
41 | * | 44 | * |
42 | * As no specification is available from M-Systems/Sandisk, this drivers lacks | 45 | * As no specification is available from M-Systems/Sandisk, this drivers lacks |
43 | * several functions available on the chip, as : | 46 | * several functions available on the chip, as : |
44 | * - block erase | ||
45 | * - page write | ||
46 | * - IPL write | 47 | * - IPL write |
47 | * - ECC fixing (lack of BCH algorith understanding) | ||
48 | * - powerdown / powerup | ||
49 | * | 48 | * |
50 | * The bus data width (8bits versus 16bits) is not handled (if_cfg flag), and | 49 | * The bus data width (8bits versus 16bits) is not handled (if_cfg flag), and |
51 | * the driver assumes a 16bits data bus. | 50 | * the driver assumes a 16bits data bus. |
@@ -53,8 +52,7 @@ | |||
53 | * DocG3 relies on 2 ECC algorithms, which are handled in hardware : | 52 | * DocG3 relies on 2 ECC algorithms, which are handled in hardware : |
54 | * - a 1 byte Hamming code stored in the OOB for each page | 53 | * - a 1 byte Hamming code stored in the OOB for each page |
55 | * - a 7 bytes BCH code stored in the OOB for each page | 54 | * - a 7 bytes BCH code stored in the OOB for each page |
56 | * The BCH part is only used for check purpose, no correction is available as | 55 | * The BCH ECC is : |
57 | * some information is missing. What is known is that : | ||
58 | * - BCH is in GF(2^14) | 56 | * - BCH is in GF(2^14) |
59 | * - BCH is over data of 520 bytes (512 page + 7 page_info bytes | 57 | * - BCH is over data of 520 bytes (512 page + 7 page_info bytes |
60 | * + 1 hamming byte) | 58 | * + 1 hamming byte) |
@@ -63,6 +61,30 @@ | |||
63 | * | 61 | * |
64 | */ | 62 | */ |
65 | 63 | ||
64 | static unsigned int reliable_mode; | ||
65 | module_param(reliable_mode, uint, 0); | ||
66 | MODULE_PARM_DESC(reliable_mode, "Set the docg3 mode (0=normal MLC, 1=fast, " | ||
67 | "2=reliable) : MLC normal operations are in normal mode"); | ||
68 | |||
69 | /** | ||
70 | * struct docg3_oobinfo - DiskOnChip G3 OOB layout | ||
71 | * @eccbytes: 8 bytes are used (1 for Hamming ECC, 7 for BCH ECC) | ||
72 | * @eccpos: ecc positions (byte 7 is Hamming ECC, byte 8-14 are BCH ECC) | ||
73 | * @oobfree: free pageinfo bytes (byte 0 until byte 6, byte 15 | ||
74 | * @oobavail: 8 available bytes remaining after ECC toll | ||
75 | */ | ||
76 | static struct nand_ecclayout docg3_oobinfo = { | ||
77 | .eccbytes = 8, | ||
78 | .eccpos = {7, 8, 9, 10, 11, 12, 13, 14}, | ||
79 | .oobfree = {{0, 7}, {15, 1} }, | ||
80 | .oobavail = 8, | ||
81 | }; | ||
82 | |||
83 | /** | ||
84 | * struct docg3_bch - BCH engine | ||
85 | */ | ||
86 | static struct bch_control *docg3_bch; | ||
87 | |||
66 | static inline u8 doc_readb(struct docg3 *docg3, u16 reg) | 88 | static inline u8 doc_readb(struct docg3 *docg3, u16 reg) |
67 | { | 89 | { |
68 | u8 val = readb(docg3->base + reg); | 90 | u8 val = readb(docg3->base + reg); |
@@ -82,7 +104,7 @@ static inline u16 doc_readw(struct docg3 *docg3, u16 reg) | |||
82 | static inline void doc_writeb(struct docg3 *docg3, u8 val, u16 reg) | 104 | static inline void doc_writeb(struct docg3 *docg3, u8 val, u16 reg) |
83 | { | 105 | { |
84 | writeb(val, docg3->base + reg); | 106 | writeb(val, docg3->base + reg); |
85 | trace_docg3_io(1, 16, reg, val); | 107 | trace_docg3_io(1, 8, reg, val); |
86 | } | 108 | } |
87 | 109 | ||
88 | static inline void doc_writew(struct docg3 *docg3, u16 val, u16 reg) | 110 | static inline void doc_writew(struct docg3 *docg3, u16 val, u16 reg) |
@@ -143,7 +165,7 @@ static void doc_delay(struct docg3 *docg3, int nbNOPs) | |||
143 | { | 165 | { |
144 | int i; | 166 | int i; |
145 | 167 | ||
146 | doc_dbg("NOP x %d\n", nbNOPs); | 168 | doc_vdbg("NOP x %d\n", nbNOPs); |
147 | for (i = 0; i < nbNOPs; i++) | 169 | for (i = 0; i < nbNOPs; i++) |
148 | doc_writeb(docg3, 0, DOC_NOP); | 170 | doc_writeb(docg3, 0, DOC_NOP); |
149 | } | 171 | } |
@@ -196,8 +218,8 @@ static int doc_reset_seq(struct docg3 *docg3) | |||
196 | /** | 218 | /** |
197 | * doc_read_data_area - Read data from data area | 219 | * doc_read_data_area - Read data from data area |
198 | * @docg3: the device | 220 | * @docg3: the device |
199 | * @buf: the buffer to fill in | 221 | * @buf: the buffer to fill in (might be NULL is dummy reads) |
200 | * @len: the lenght to read | 222 | * @len: the length to read |
201 | * @first: first time read, DOC_READADDRESS should be set | 223 | * @first: first time read, DOC_READADDRESS should be set |
202 | * | 224 | * |
203 | * Reads bytes from flash data. Handles the single byte / even bytes reads. | 225 | * Reads bytes from flash data. Handles the single byte / even bytes reads. |
@@ -218,8 +240,10 @@ static void doc_read_data_area(struct docg3 *docg3, void *buf, int len, | |||
218 | dst16 = buf; | 240 | dst16 = buf; |
219 | for (i = 0; i < len4; i += 2) { | 241 | for (i = 0; i < len4; i += 2) { |
220 | data16 = doc_readw(docg3, DOC_IOSPACE_DATA); | 242 | data16 = doc_readw(docg3, DOC_IOSPACE_DATA); |
221 | *dst16 = data16; | 243 | if (dst16) { |
222 | dst16++; | 244 | *dst16 = data16; |
245 | dst16++; | ||
246 | } | ||
223 | } | 247 | } |
224 | 248 | ||
225 | if (cdr) { | 249 | if (cdr) { |
@@ -229,26 +253,84 @@ static void doc_read_data_area(struct docg3 *docg3, void *buf, int len, | |||
229 | dst8 = (u8 *)dst16; | 253 | dst8 = (u8 *)dst16; |
230 | for (i = 0; i < cdr; i++) { | 254 | for (i = 0; i < cdr; i++) { |
231 | data8 = doc_readb(docg3, DOC_IOSPACE_DATA); | 255 | data8 = doc_readb(docg3, DOC_IOSPACE_DATA); |
232 | *dst8 = data8; | 256 | if (dst8) { |
233 | dst8++; | 257 | *dst8 = data8; |
258 | dst8++; | ||
259 | } | ||
234 | } | 260 | } |
235 | } | 261 | } |
236 | } | 262 | } |
237 | 263 | ||
238 | /** | 264 | /** |
239 | * doc_set_data_mode - Sets the flash to reliable data mode | 265 | * doc_write_data_area - Write data into data area |
266 | * @docg3: the device | ||
267 | * @buf: the buffer to get input bytes from | ||
268 | * @len: the length to write | ||
269 | * | ||
270 | * Writes bytes into flash data. Handles the single byte / even bytes writes. | ||
271 | */ | ||
272 | static void doc_write_data_area(struct docg3 *docg3, const void *buf, int len) | ||
273 | { | ||
274 | int i, cdr, len4; | ||
275 | u16 *src16; | ||
276 | u8 *src8; | ||
277 | |||
278 | doc_dbg("doc_write_data_area(buf=%p, len=%d)\n", buf, len); | ||
279 | cdr = len & 0x3; | ||
280 | len4 = len - cdr; | ||
281 | |||
282 | doc_writew(docg3, DOC_IOSPACE_DATA, DOC_READADDRESS); | ||
283 | src16 = (u16 *)buf; | ||
284 | for (i = 0; i < len4; i += 2) { | ||
285 | doc_writew(docg3, *src16, DOC_IOSPACE_DATA); | ||
286 | src16++; | ||
287 | } | ||
288 | |||
289 | src8 = (u8 *)src16; | ||
290 | for (i = 0; i < cdr; i++) { | ||
291 | doc_writew(docg3, DOC_IOSPACE_DATA | DOC_READADDR_ONE_BYTE, | ||
292 | DOC_READADDRESS); | ||
293 | doc_writeb(docg3, *src8, DOC_IOSPACE_DATA); | ||
294 | src8++; | ||
295 | } | ||
296 | } | ||
297 | |||
298 | /** | ||
299 | * doc_set_data_mode - Sets the flash to normal or reliable data mode | ||
240 | * @docg3: the device | 300 | * @docg3: the device |
241 | * | 301 | * |
242 | * The reliable data mode is a bit slower than the fast mode, but less errors | 302 | * The reliable data mode is a bit slower than the fast mode, but less errors |
243 | * occur. Entering the reliable mode cannot be done without entering the fast | 303 | * occur. Entering the reliable mode cannot be done without entering the fast |
244 | * mode first. | 304 | * mode first. |
305 | * | ||
306 | * In reliable mode, pages 2*n and 2*n+1 are clones. Writing to page 0 of blocks | ||
307 | * (4,5) make the hardware write also to page 1 of blocks blocks(4,5). Reading | ||
308 | * from page 0 of blocks (4,5) or from page 1 of blocks (4,5) gives the same | ||
309 | * result, which is a logical and between bytes from page 0 and page 1 (which is | ||
310 | * consistent with the fact that writing to a page is _clearing_ bits of that | ||
311 | * page). | ||
245 | */ | 312 | */ |
246 | static void doc_set_reliable_mode(struct docg3 *docg3) | 313 | static void doc_set_reliable_mode(struct docg3 *docg3) |
247 | { | 314 | { |
248 | doc_dbg("doc_set_reliable_mode()\n"); | 315 | static char *strmode[] = { "normal", "fast", "reliable", "invalid" }; |
249 | doc_flash_sequence(docg3, DOC_SEQ_SET_MODE); | 316 | |
250 | doc_flash_command(docg3, DOC_CMD_FAST_MODE); | 317 | doc_dbg("doc_set_reliable_mode(%s)\n", strmode[docg3->reliable]); |
251 | doc_flash_command(docg3, DOC_CMD_RELIABLE_MODE); | 318 | switch (docg3->reliable) { |
319 | case 0: | ||
320 | break; | ||
321 | case 1: | ||
322 | doc_flash_sequence(docg3, DOC_SEQ_SET_FASTMODE); | ||
323 | doc_flash_command(docg3, DOC_CMD_FAST_MODE); | ||
324 | break; | ||
325 | case 2: | ||
326 | doc_flash_sequence(docg3, DOC_SEQ_SET_RELIABLEMODE); | ||
327 | doc_flash_command(docg3, DOC_CMD_FAST_MODE); | ||
328 | doc_flash_command(docg3, DOC_CMD_RELIABLE_MODE); | ||
329 | break; | ||
330 | default: | ||
331 | doc_err("doc_set_reliable_mode(): invalid mode\n"); | ||
332 | break; | ||
333 | } | ||
252 | doc_delay(docg3, 2); | 334 | doc_delay(docg3, 2); |
253 | } | 335 | } |
254 | 336 | ||
@@ -325,6 +407,37 @@ static int doc_set_extra_page_mode(struct docg3 *docg3) | |||
325 | } | 407 | } |
326 | 408 | ||
327 | /** | 409 | /** |
410 | * doc_setup_addr_sector - Setup blocks/page/ofs address for one plane | ||
411 | * @docg3: the device | ||
412 | * @sector: the sector | ||
413 | */ | ||
414 | static void doc_setup_addr_sector(struct docg3 *docg3, int sector) | ||
415 | { | ||
416 | doc_delay(docg3, 1); | ||
417 | doc_flash_address(docg3, sector & 0xff); | ||
418 | doc_flash_address(docg3, (sector >> 8) & 0xff); | ||
419 | doc_flash_address(docg3, (sector >> 16) & 0xff); | ||
420 | doc_delay(docg3, 1); | ||
421 | } | ||
422 | |||
423 | /** | ||
424 | * doc_setup_writeaddr_sector - Setup blocks/page/ofs address for one plane | ||
425 | * @docg3: the device | ||
426 | * @sector: the sector | ||
427 | * @ofs: the offset in the page, between 0 and (512 + 16 + 512) | ||
428 | */ | ||
429 | static void doc_setup_writeaddr_sector(struct docg3 *docg3, int sector, int ofs) | ||
430 | { | ||
431 | ofs = ofs >> 2; | ||
432 | doc_delay(docg3, 1); | ||
433 | doc_flash_address(docg3, ofs & 0xff); | ||
434 | doc_flash_address(docg3, sector & 0xff); | ||
435 | doc_flash_address(docg3, (sector >> 8) & 0xff); | ||
436 | doc_flash_address(docg3, (sector >> 16) & 0xff); | ||
437 | doc_delay(docg3, 1); | ||
438 | } | ||
439 | |||
440 | /** | ||
328 | * doc_seek - Set both flash planes to the specified block, page for reading | 441 | * doc_seek - Set both flash planes to the specified block, page for reading |
329 | * @docg3: the device | 442 | * @docg3: the device |
330 | * @block0: the first plane block index | 443 | * @block0: the first plane block index |
@@ -360,34 +473,80 @@ static int doc_read_seek(struct docg3 *docg3, int block0, int block1, int page, | |||
360 | if (ret) | 473 | if (ret) |
361 | goto out; | 474 | goto out; |
362 | 475 | ||
363 | sector = (block0 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK); | ||
364 | doc_flash_sequence(docg3, DOC_SEQ_READ); | 476 | doc_flash_sequence(docg3, DOC_SEQ_READ); |
477 | sector = (block0 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK); | ||
365 | doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR); | 478 | doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR); |
366 | doc_delay(docg3, 1); | 479 | doc_setup_addr_sector(docg3, sector); |
367 | doc_flash_address(docg3, sector & 0xff); | ||
368 | doc_flash_address(docg3, (sector >> 8) & 0xff); | ||
369 | doc_flash_address(docg3, (sector >> 16) & 0xff); | ||
370 | doc_delay(docg3, 1); | ||
371 | 480 | ||
372 | sector = (block1 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK); | 481 | sector = (block1 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK); |
373 | doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR); | 482 | doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR); |
483 | doc_setup_addr_sector(docg3, sector); | ||
374 | doc_delay(docg3, 1); | 484 | doc_delay(docg3, 1); |
375 | doc_flash_address(docg3, sector & 0xff); | 485 | |
376 | doc_flash_address(docg3, (sector >> 8) & 0xff); | 486 | out: |
377 | doc_flash_address(docg3, (sector >> 16) & 0xff); | 487 | return ret; |
488 | } | ||
489 | |||
490 | /** | ||
491 | * doc_write_seek - Set both flash planes to the specified block, page for writing | ||
492 | * @docg3: the device | ||
493 | * @block0: the first plane block index | ||
494 | * @block1: the second plane block index | ||
495 | * @page: the page index within the block | ||
496 | * @ofs: offset in page to write | ||
497 | * | ||
498 | * Programs the flash even and odd planes to the specific block and page. | ||
499 | * Alternatively, programs the flash to the wear area of the specified page. | ||
500 | */ | ||
501 | static int doc_write_seek(struct docg3 *docg3, int block0, int block1, int page, | ||
502 | int ofs) | ||
503 | { | ||
504 | int ret = 0, sector; | ||
505 | |||
506 | doc_dbg("doc_write_seek(blocks=(%d,%d), page=%d, ofs=%d)\n", | ||
507 | block0, block1, page, ofs); | ||
508 | |||
509 | doc_set_reliable_mode(docg3); | ||
510 | |||
511 | if (ofs < 2 * DOC_LAYOUT_PAGE_SIZE) { | ||
512 | doc_flash_sequence(docg3, DOC_SEQ_SET_PLANE1); | ||
513 | doc_flash_command(docg3, DOC_CMD_READ_PLANE1); | ||
514 | doc_delay(docg3, 2); | ||
515 | } else { | ||
516 | doc_flash_sequence(docg3, DOC_SEQ_SET_PLANE2); | ||
517 | doc_flash_command(docg3, DOC_CMD_READ_PLANE2); | ||
518 | doc_delay(docg3, 2); | ||
519 | } | ||
520 | |||
521 | doc_flash_sequence(docg3, DOC_SEQ_PAGE_SETUP); | ||
522 | doc_flash_command(docg3, DOC_CMD_PROG_CYCLE1); | ||
523 | |||
524 | sector = (block0 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK); | ||
525 | doc_setup_writeaddr_sector(docg3, sector, ofs); | ||
526 | |||
527 | doc_flash_command(docg3, DOC_CMD_PROG_CYCLE3); | ||
378 | doc_delay(docg3, 2); | 528 | doc_delay(docg3, 2); |
529 | ret = doc_wait_ready(docg3); | ||
530 | if (ret) | ||
531 | goto out; | ||
532 | |||
533 | doc_flash_command(docg3, DOC_CMD_PROG_CYCLE1); | ||
534 | sector = (block1 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK); | ||
535 | doc_setup_writeaddr_sector(docg3, sector, ofs); | ||
536 | doc_delay(docg3, 1); | ||
379 | 537 | ||
380 | out: | 538 | out: |
381 | return ret; | 539 | return ret; |
382 | } | 540 | } |
383 | 541 | ||
542 | |||
384 | /** | 543 | /** |
385 | * doc_read_page_ecc_init - Initialize hardware ECC engine | 544 | * doc_read_page_ecc_init - Initialize hardware ECC engine |
386 | * @docg3: the device | 545 | * @docg3: the device |
387 | * @len: the number of bytes covered by the ECC (BCH covered) | 546 | * @len: the number of bytes covered by the ECC (BCH covered) |
388 | * | 547 | * |
389 | * The function does initialize the hardware ECC engine to compute the Hamming | 548 | * The function does initialize the hardware ECC engine to compute the Hamming |
390 | * ECC (on 1 byte) and the BCH Syndroms (on 7 bytes). | 549 | * ECC (on 1 byte) and the BCH hardware ECC (on 7 bytes). |
391 | * | 550 | * |
392 | * Return 0 if succeeded, -EIO on error | 551 | * Return 0 if succeeded, -EIO on error |
393 | */ | 552 | */ |
@@ -403,6 +562,106 @@ static int doc_read_page_ecc_init(struct docg3 *docg3, int len) | |||
403 | } | 562 | } |
404 | 563 | ||
405 | /** | 564 | /** |
565 | * doc_write_page_ecc_init - Initialize hardware BCH ECC engine | ||
566 | * @docg3: the device | ||
567 | * @len: the number of bytes covered by the ECC (BCH covered) | ||
568 | * | ||
569 | * The function does initialize the hardware ECC engine to compute the Hamming | ||
570 | * ECC (on 1 byte) and the BCH hardware ECC (on 7 bytes). | ||
571 | * | ||
572 | * Return 0 if succeeded, -EIO on error | ||
573 | */ | ||
574 | static int doc_write_page_ecc_init(struct docg3 *docg3, int len) | ||
575 | { | ||
576 | doc_writew(docg3, DOC_ECCCONF0_WRITE_MODE | ||
577 | | DOC_ECCCONF0_BCH_ENABLE | DOC_ECCCONF0_HAMMING_ENABLE | ||
578 | | (len & DOC_ECCCONF0_DATA_BYTES_MASK), | ||
579 | DOC_ECCCONF0); | ||
580 | doc_delay(docg3, 4); | ||
581 | doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
582 | return doc_wait_ready(docg3); | ||
583 | } | ||
584 | |||
585 | /** | ||
586 | * doc_ecc_disable - Disable Hamming and BCH ECC hardware calculator | ||
587 | * @docg3: the device | ||
588 | * | ||
589 | * Disables the hardware ECC generator and checker, for unchecked reads (as when | ||
590 | * reading OOB only or write status byte). | ||
591 | */ | ||
592 | static void doc_ecc_disable(struct docg3 *docg3) | ||
593 | { | ||
594 | doc_writew(docg3, DOC_ECCCONF0_READ_MODE, DOC_ECCCONF0); | ||
595 | doc_delay(docg3, 4); | ||
596 | } | ||
597 | |||
598 | /** | ||
599 | * doc_hamming_ecc_init - Initialize hardware Hamming ECC engine | ||
600 | * @docg3: the device | ||
601 | * @nb_bytes: the number of bytes covered by the ECC (Hamming covered) | ||
602 | * | ||
603 | * This function programs the ECC hardware to compute the hamming code on the | ||
604 | * last provided N bytes to the hardware generator. | ||
605 | */ | ||
606 | static void doc_hamming_ecc_init(struct docg3 *docg3, int nb_bytes) | ||
607 | { | ||
608 | u8 ecc_conf1; | ||
609 | |||
610 | ecc_conf1 = doc_register_readb(docg3, DOC_ECCCONF1); | ||
611 | ecc_conf1 &= ~DOC_ECCCONF1_HAMMING_BITS_MASK; | ||
612 | ecc_conf1 |= (nb_bytes & DOC_ECCCONF1_HAMMING_BITS_MASK); | ||
613 | doc_writeb(docg3, ecc_conf1, DOC_ECCCONF1); | ||
614 | } | ||
615 | |||
616 | /** | ||
617 | * doc_ecc_bch_fix_data - Fix if need be read data from flash | ||
618 | * @docg3: the device | ||
619 | * @buf: the buffer of read data (512 + 7 + 1 bytes) | ||
620 | * @hwecc: the hardware calculated ECC. | ||
621 | * It's in fact recv_ecc ^ calc_ecc, where recv_ecc was read from OOB | ||
622 | * area data, and calc_ecc the ECC calculated by the hardware generator. | ||
623 | * | ||
624 | * Checks if the received data matches the ECC, and if an error is detected, | ||
625 | * tries to fix the bit flips (at most 4) in the buffer buf. As the docg3 | ||
626 | * understands the (data, ecc, syndroms) in an inverted order in comparison to | ||
627 | * the BCH library, the function reverses the order of bits (ie. bit7 and bit0, | ||
628 | * bit6 and bit 1, ...) for all ECC data. | ||
629 | * | ||
630 | * The hardware ecc unit produces oob_ecc ^ calc_ecc. The kernel's bch | ||
631 | * algorithm is used to decode this. However the hw operates on page | ||
632 | * data in a bit order that is the reverse of that of the bch alg, | ||
633 | * requiring that the bits be reversed on the result. Thanks to Ivan | ||
634 | * Djelic for his analysis. | ||
635 | * | ||
636 | * Returns number of fixed bits (0, 1, 2, 3, 4) or -EBADMSG if too many bit | ||
637 | * errors were detected and cannot be fixed. | ||
638 | */ | ||
639 | static int doc_ecc_bch_fix_data(struct docg3 *docg3, void *buf, u8 *hwecc) | ||
640 | { | ||
641 | u8 ecc[DOC_ECC_BCH_SIZE]; | ||
642 | int errorpos[DOC_ECC_BCH_T], i, numerrs; | ||
643 | |||
644 | for (i = 0; i < DOC_ECC_BCH_SIZE; i++) | ||
645 | ecc[i] = bitrev8(hwecc[i]); | ||
646 | numerrs = decode_bch(docg3_bch, NULL, DOC_ECC_BCH_COVERED_BYTES, | ||
647 | NULL, ecc, NULL, errorpos); | ||
648 | BUG_ON(numerrs == -EINVAL); | ||
649 | if (numerrs < 0) | ||
650 | goto out; | ||
651 | |||
652 | for (i = 0; i < numerrs; i++) | ||
653 | errorpos[i] = (errorpos[i] & ~7) | (7 - (errorpos[i] & 7)); | ||
654 | for (i = 0; i < numerrs; i++) | ||
655 | if (errorpos[i] < DOC_ECC_BCH_COVERED_BYTES*8) | ||
656 | /* error is located in data, correct it */ | ||
657 | change_bit(errorpos[i], buf); | ||
658 | out: | ||
659 | doc_dbg("doc_ecc_bch_fix_data: flipped %d bits\n", numerrs); | ||
660 | return numerrs; | ||
661 | } | ||
662 | |||
663 | |||
664 | /** | ||
406 | * doc_read_page_prepare - Prepares reading data from a flash page | 665 | * doc_read_page_prepare - Prepares reading data from a flash page |
407 | * @docg3: the device | 666 | * @docg3: the device |
408 | * @block0: the first plane block index on flash memory | 667 | * @block0: the first plane block index on flash memory |
@@ -488,16 +747,40 @@ static int doc_read_page_getbytes(struct docg3 *docg3, int len, u_char *buf, | |||
488 | } | 747 | } |
489 | 748 | ||
490 | /** | 749 | /** |
491 | * doc_get_hw_bch_syndroms - Get hardware calculated BCH syndroms | 750 | * doc_write_page_putbytes - Writes bytes into a prepared page |
751 | * @docg3: the device | ||
752 | * @len: the number of bytes to be written | ||
753 | * @buf: the buffer of input bytes | ||
754 | * | ||
755 | */ | ||
756 | static void doc_write_page_putbytes(struct docg3 *docg3, int len, | ||
757 | const u_char *buf) | ||
758 | { | ||
759 | doc_write_data_area(docg3, buf, len); | ||
760 | doc_delay(docg3, 2); | ||
761 | } | ||
762 | |||
763 | /** | ||
764 | * doc_get_bch_hw_ecc - Get hardware calculated BCH ECC | ||
492 | * @docg3: the device | 765 | * @docg3: the device |
493 | * @syns: the array of 7 integers where the syndroms will be stored | 766 | * @hwecc: the array of 7 integers where the hardware ecc will be stored |
494 | */ | 767 | */ |
495 | static void doc_get_hw_bch_syndroms(struct docg3 *docg3, int *syns) | 768 | static void doc_get_bch_hw_ecc(struct docg3 *docg3, u8 *hwecc) |
496 | { | 769 | { |
497 | int i; | 770 | int i; |
498 | 771 | ||
499 | for (i = 0; i < DOC_ECC_BCH_SIZE; i++) | 772 | for (i = 0; i < DOC_ECC_BCH_SIZE; i++) |
500 | syns[i] = doc_register_readb(docg3, DOC_BCH_SYNDROM(i)); | 773 | hwecc[i] = doc_register_readb(docg3, DOC_BCH_HW_ECC(i)); |
774 | } | ||
775 | |||
776 | /** | ||
777 | * doc_page_finish - Ends reading/writing of a flash page | ||
778 | * @docg3: the device | ||
779 | */ | ||
780 | static void doc_page_finish(struct docg3 *docg3) | ||
781 | { | ||
782 | doc_writeb(docg3, 0, DOC_DATAEND); | ||
783 | doc_delay(docg3, 2); | ||
501 | } | 784 | } |
502 | 785 | ||
503 | /** | 786 | /** |
@@ -510,8 +793,7 @@ static void doc_get_hw_bch_syndroms(struct docg3 *docg3, int *syns) | |||
510 | */ | 793 | */ |
511 | static void doc_read_page_finish(struct docg3 *docg3) | 794 | static void doc_read_page_finish(struct docg3 *docg3) |
512 | { | 795 | { |
513 | doc_writeb(docg3, 0, DOC_DATAEND); | 796 | doc_page_finish(docg3); |
514 | doc_delay(docg3, 2); | ||
515 | doc_set_device_id(docg3, 0); | 797 | doc_set_device_id(docg3, 0); |
516 | } | 798 | } |
517 | 799 | ||
@@ -523,18 +805,29 @@ static void doc_read_page_finish(struct docg3 *docg3) | |||
523 | * @block1: second plane block index calculated | 805 | * @block1: second plane block index calculated |
524 | * @page: page calculated | 806 | * @page: page calculated |
525 | * @ofs: offset in page | 807 | * @ofs: offset in page |
808 | * @reliable: 0 if docg3 in normal mode, 1 if docg3 in fast mode, 2 if docg3 in | ||
809 | * reliable mode. | ||
810 | * | ||
811 | * The calculation is based on the reliable/normal mode. In normal mode, the 64 | ||
812 | * pages of a block are available. In reliable mode, as pages 2*n and 2*n+1 are | ||
813 | * clones, only 32 pages per block are available. | ||
526 | */ | 814 | */ |
527 | static void calc_block_sector(loff_t from, int *block0, int *block1, int *page, | 815 | static void calc_block_sector(loff_t from, int *block0, int *block1, int *page, |
528 | int *ofs) | 816 | int *ofs, int reliable) |
529 | { | 817 | { |
530 | uint sector; | 818 | uint sector, pages_biblock; |
819 | |||
820 | pages_biblock = DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES; | ||
821 | if (reliable == 1 || reliable == 2) | ||
822 | pages_biblock /= 2; | ||
531 | 823 | ||
532 | sector = from / DOC_LAYOUT_PAGE_SIZE; | 824 | sector = from / DOC_LAYOUT_PAGE_SIZE; |
533 | *block0 = sector / (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES) | 825 | *block0 = sector / pages_biblock * DOC_LAYOUT_NBPLANES; |
534 | * DOC_LAYOUT_NBPLANES; | ||
535 | *block1 = *block0 + 1; | 826 | *block1 = *block0 + 1; |
536 | *page = sector % (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES); | 827 | *page = sector % pages_biblock; |
537 | *page /= DOC_LAYOUT_NBPLANES; | 828 | *page /= DOC_LAYOUT_NBPLANES; |
829 | if (reliable == 1 || reliable == 2) | ||
830 | *page *= 2; | ||
538 | if (sector % 2) | 831 | if (sector % 2) |
539 | *ofs = DOC_LAYOUT_PAGE_OOB_SIZE; | 832 | *ofs = DOC_LAYOUT_PAGE_OOB_SIZE; |
540 | else | 833 | else |
@@ -542,99 +835,124 @@ static void calc_block_sector(loff_t from, int *block0, int *block1, int *page, | |||
542 | } | 835 | } |
543 | 836 | ||
544 | /** | 837 | /** |
545 | * doc_read - Read bytes from flash | 838 | * doc_read_oob - Read out of band bytes from flash |
546 | * @mtd: the device | 839 | * @mtd: the device |
547 | * @from: the offset from first block and first page, in bytes, aligned on page | 840 | * @from: the offset from first block and first page, in bytes, aligned on page |
548 | * size | 841 | * size |
549 | * @len: the number of bytes to read (must be a multiple of 4) | 842 | * @ops: the mtd oob structure |
550 | * @retlen: the number of bytes actually read | ||
551 | * @buf: the filled in buffer | ||
552 | * | 843 | * |
553 | * Reads flash memory pages. This function does not read the OOB chunk, but only | 844 | * Reads flash memory OOB area of pages. |
554 | * the page data. | ||
555 | * | 845 | * |
556 | * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured | 846 | * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured |
557 | */ | 847 | */ |
558 | static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, | 848 | static int doc_read_oob(struct mtd_info *mtd, loff_t from, |
559 | size_t *retlen, u_char *buf) | 849 | struct mtd_oob_ops *ops) |
560 | { | 850 | { |
561 | struct docg3 *docg3 = mtd->priv; | 851 | struct docg3 *docg3 = mtd->priv; |
562 | int block0, block1, page, readlen, ret, ofs = 0; | 852 | int block0, block1, page, ret, ofs = 0; |
563 | int syn[DOC_ECC_BCH_SIZE], eccconf1; | 853 | u8 *oobbuf = ops->oobbuf; |
564 | u8 oob[DOC_LAYOUT_OOB_SIZE]; | 854 | u8 *buf = ops->datbuf; |
855 | size_t len, ooblen, nbdata, nboob; | ||
856 | u8 hwecc[DOC_ECC_BCH_SIZE], eccconf1; | ||
857 | |||
858 | if (buf) | ||
859 | len = ops->len; | ||
860 | else | ||
861 | len = 0; | ||
862 | if (oobbuf) | ||
863 | ooblen = ops->ooblen; | ||
864 | else | ||
865 | ooblen = 0; | ||
866 | |||
867 | if (oobbuf && ops->mode == MTD_OPS_PLACE_OOB) | ||
868 | oobbuf += ops->ooboffs; | ||
869 | |||
870 | doc_dbg("doc_read_oob(from=%lld, mode=%d, data=(%p:%zu), oob=(%p:%zu))\n", | ||
871 | from, ops->mode, buf, len, oobbuf, ooblen); | ||
872 | if ((len % DOC_LAYOUT_PAGE_SIZE) || (ooblen % DOC_LAYOUT_OOB_SIZE) || | ||
873 | (from % DOC_LAYOUT_PAGE_SIZE)) | ||
874 | return -EINVAL; | ||
565 | 875 | ||
566 | ret = -EINVAL; | 876 | ret = -EINVAL; |
567 | doc_dbg("doc_read(from=%lld, len=%zu, buf=%p)\n", from, len, buf); | 877 | calc_block_sector(from + len, &block0, &block1, &page, &ofs, |
568 | if (from % DOC_LAYOUT_PAGE_SIZE) | 878 | docg3->reliable); |
569 | goto err; | ||
570 | if (len % 4) | ||
571 | goto err; | ||
572 | calc_block_sector(from, &block0, &block1, &page, &ofs); | ||
573 | if (block1 > docg3->max_block) | 879 | if (block1 > docg3->max_block) |
574 | goto err; | 880 | goto err; |
575 | 881 | ||
576 | *retlen = 0; | 882 | ops->oobretlen = 0; |
883 | ops->retlen = 0; | ||
577 | ret = 0; | 884 | ret = 0; |
578 | readlen = min_t(size_t, len, (size_t)DOC_LAYOUT_PAGE_SIZE); | 885 | while (!ret && (len > 0 || ooblen > 0)) { |
579 | while (!ret && len > 0) { | 886 | calc_block_sector(from, &block0, &block1, &page, &ofs, |
580 | readlen = min_t(size_t, len, (size_t)DOC_LAYOUT_PAGE_SIZE); | 887 | docg3->reliable); |
888 | nbdata = min_t(size_t, len, (size_t)DOC_LAYOUT_PAGE_SIZE); | ||
889 | nboob = min_t(size_t, ooblen, (size_t)DOC_LAYOUT_OOB_SIZE); | ||
581 | ret = doc_read_page_prepare(docg3, block0, block1, page, ofs); | 890 | ret = doc_read_page_prepare(docg3, block0, block1, page, ofs); |
582 | if (ret < 0) | 891 | if (ret < 0) |
583 | goto err; | 892 | goto err; |
584 | ret = doc_read_page_ecc_init(docg3, DOC_ECC_BCH_COVERED_BYTES); | 893 | ret = doc_read_page_ecc_init(docg3, DOC_ECC_BCH_TOTAL_BYTES); |
585 | if (ret < 0) | 894 | if (ret < 0) |
586 | goto err_in_read; | 895 | goto err_in_read; |
587 | ret = doc_read_page_getbytes(docg3, readlen, buf, 1); | 896 | ret = doc_read_page_getbytes(docg3, nbdata, buf, 1); |
588 | if (ret < readlen) | 897 | if (ret < nbdata) |
589 | goto err_in_read; | 898 | goto err_in_read; |
590 | ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE, | 899 | doc_read_page_getbytes(docg3, DOC_LAYOUT_PAGE_SIZE - nbdata, |
591 | oob, 0); | 900 | NULL, 0); |
592 | if (ret < DOC_LAYOUT_OOB_SIZE) | 901 | ret = doc_read_page_getbytes(docg3, nboob, oobbuf, 0); |
902 | if (ret < nboob) | ||
593 | goto err_in_read; | 903 | goto err_in_read; |
904 | doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE - nboob, | ||
905 | NULL, 0); | ||
594 | 906 | ||
595 | *retlen += readlen; | 907 | doc_get_bch_hw_ecc(docg3, hwecc); |
596 | buf += readlen; | ||
597 | len -= readlen; | ||
598 | |||
599 | ofs ^= DOC_LAYOUT_PAGE_OOB_SIZE; | ||
600 | if (ofs == 0) | ||
601 | page += 2; | ||
602 | if (page > DOC_ADDR_PAGE_MASK) { | ||
603 | page = 0; | ||
604 | block0 += 2; | ||
605 | block1 += 2; | ||
606 | } | ||
607 | |||
608 | /* | ||
609 | * There should be a BCH bitstream fixing algorithm here ... | ||
610 | * By now, a page read failure is triggered by BCH error | ||
611 | */ | ||
612 | doc_get_hw_bch_syndroms(docg3, syn); | ||
613 | eccconf1 = doc_register_readb(docg3, DOC_ECCCONF1); | 908 | eccconf1 = doc_register_readb(docg3, DOC_ECCCONF1); |
614 | 909 | ||
615 | doc_dbg("OOB - INFO: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | 910 | if (nboob >= DOC_LAYOUT_OOB_SIZE) { |
616 | oob[0], oob[1], oob[2], oob[3], oob[4], | 911 | doc_dbg("OOB - INFO: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n", |
617 | oob[5], oob[6]); | 912 | oobbuf[0], oobbuf[1], oobbuf[2], oobbuf[3], |
618 | doc_dbg("OOB - HAMMING: %02x\n", oob[7]); | 913 | oobbuf[4], oobbuf[5], oobbuf[6]); |
619 | doc_dbg("OOB - BCH_ECC: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | 914 | doc_dbg("OOB - HAMMING: %02x\n", oobbuf[7]); |
620 | oob[8], oob[9], oob[10], oob[11], oob[12], | 915 | doc_dbg("OOB - BCH_ECC: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n", |
621 | oob[13], oob[14]); | 916 | oobbuf[8], oobbuf[9], oobbuf[10], oobbuf[11], |
622 | doc_dbg("OOB - UNUSED: %02x\n", oob[15]); | 917 | oobbuf[12], oobbuf[13], oobbuf[14]); |
918 | doc_dbg("OOB - UNUSED: %02x\n", oobbuf[15]); | ||
919 | } | ||
623 | doc_dbg("ECC checks: ECCConf1=%x\n", eccconf1); | 920 | doc_dbg("ECC checks: ECCConf1=%x\n", eccconf1); |
624 | doc_dbg("ECC BCH syndrom: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | 921 | doc_dbg("ECC HW_ECC: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n", |
625 | syn[0], syn[1], syn[2], syn[3], syn[4], syn[5], syn[6]); | 922 | hwecc[0], hwecc[1], hwecc[2], hwecc[3], hwecc[4], |
626 | 923 | hwecc[5], hwecc[6]); | |
627 | ret = -EBADMSG; | 924 | |
628 | if (block0 >= DOC_LAYOUT_BLOCK_FIRST_DATA) { | 925 | ret = -EIO; |
629 | if (eccconf1 & DOC_ECCCONF1_BCH_SYNDROM_ERR) | 926 | if (is_prot_seq_error(docg3)) |
630 | goto err_in_read; | 927 | goto err_in_read; |
631 | if (is_prot_seq_error(docg3)) | 928 | ret = 0; |
632 | goto err_in_read; | 929 | if ((block0 >= DOC_LAYOUT_BLOCK_FIRST_DATA) && |
930 | (eccconf1 & DOC_ECCCONF1_BCH_SYNDROM_ERR) && | ||
931 | (eccconf1 & DOC_ECCCONF1_PAGE_IS_WRITTEN) && | ||
932 | (ops->mode != MTD_OPS_RAW) && | ||
933 | (nbdata == DOC_LAYOUT_PAGE_SIZE)) { | ||
934 | ret = doc_ecc_bch_fix_data(docg3, buf, hwecc); | ||
935 | if (ret < 0) { | ||
936 | mtd->ecc_stats.failed++; | ||
937 | ret = -EBADMSG; | ||
938 | } | ||
939 | if (ret > 0) { | ||
940 | mtd->ecc_stats.corrected += ret; | ||
941 | ret = -EUCLEAN; | ||
942 | } | ||
633 | } | 943 | } |
944 | |||
634 | doc_read_page_finish(docg3); | 945 | doc_read_page_finish(docg3); |
946 | ops->retlen += nbdata; | ||
947 | ops->oobretlen += nboob; | ||
948 | buf += nbdata; | ||
949 | oobbuf += nboob; | ||
950 | len -= nbdata; | ||
951 | ooblen -= nboob; | ||
952 | from += DOC_LAYOUT_PAGE_SIZE; | ||
635 | } | 953 | } |
636 | 954 | ||
637 | return 0; | 955 | return ret; |
638 | err_in_read: | 956 | err_in_read: |
639 | doc_read_page_finish(docg3); | 957 | doc_read_page_finish(docg3); |
640 | err: | 958 | err: |
@@ -642,54 +960,33 @@ err: | |||
642 | } | 960 | } |
643 | 961 | ||
644 | /** | 962 | /** |
645 | * doc_read_oob - Read out of band bytes from flash | 963 | * doc_read - Read bytes from flash |
646 | * @mtd: the device | 964 | * @mtd: the device |
647 | * @from: the offset from first block and first page, in bytes, aligned on page | 965 | * @from: the offset from first block and first page, in bytes, aligned on page |
648 | * size | 966 | * size |
649 | * @ops: the mtd oob structure | 967 | * @len: the number of bytes to read (must be a multiple of 4) |
968 | * @retlen: the number of bytes actually read | ||
969 | * @buf: the filled in buffer | ||
650 | * | 970 | * |
651 | * Reads flash memory OOB area of pages. | 971 | * Reads flash memory pages. This function does not read the OOB chunk, but only |
972 | * the page data. | ||
652 | * | 973 | * |
653 | * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured | 974 | * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured |
654 | */ | 975 | */ |
655 | static int doc_read_oob(struct mtd_info *mtd, loff_t from, | 976 | static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, |
656 | struct mtd_oob_ops *ops) | 977 | size_t *retlen, u_char *buf) |
657 | { | 978 | { |
658 | struct docg3 *docg3 = mtd->priv; | 979 | struct mtd_oob_ops ops; |
659 | int block0, block1, page, ofs, ret; | 980 | size_t ret; |
660 | u8 *buf = ops->oobbuf; | ||
661 | size_t len = ops->ooblen; | ||
662 | |||
663 | doc_dbg("doc_read_oob(from=%lld, buf=%p, len=%zu)\n", from, buf, len); | ||
664 | if (len != DOC_LAYOUT_OOB_SIZE) | ||
665 | return -EINVAL; | ||
666 | |||
667 | switch (ops->mode) { | ||
668 | case MTD_OPS_PLACE_OOB: | ||
669 | buf += ops->ooboffs; | ||
670 | break; | ||
671 | default: | ||
672 | break; | ||
673 | } | ||
674 | 981 | ||
675 | calc_block_sector(from, &block0, &block1, &page, &ofs); | 982 | memset(&ops, 0, sizeof(ops)); |
676 | if (block1 > docg3->max_block) | 983 | ops.datbuf = buf; |
677 | return -EINVAL; | 984 | ops.len = len; |
678 | 985 | ops.mode = MTD_OPS_AUTO_OOB; | |
679 | ret = doc_read_page_prepare(docg3, block0, block1, page, | ||
680 | ofs + DOC_LAYOUT_PAGE_SIZE); | ||
681 | if (!ret) | ||
682 | ret = doc_read_page_ecc_init(docg3, DOC_LAYOUT_OOB_SIZE); | ||
683 | if (!ret) | ||
684 | ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE, | ||
685 | buf, 1); | ||
686 | doc_read_page_finish(docg3); | ||
687 | 986 | ||
688 | if (ret > 0) | 987 | ret = doc_read_oob(mtd, from, &ops); |
689 | ops->oobretlen = ret; | 988 | *retlen = ops.retlen; |
690 | else | 989 | return ret; |
691 | ops->oobretlen = 0; | ||
692 | return (ret > 0) ? 0 : ret; | ||
693 | } | 990 | } |
694 | 991 | ||
695 | static int doc_reload_bbt(struct docg3 *docg3) | 992 | static int doc_reload_bbt(struct docg3 *docg3) |
@@ -726,7 +1023,8 @@ static int doc_block_isbad(struct mtd_info *mtd, loff_t from) | |||
726 | struct docg3 *docg3 = mtd->priv; | 1023 | struct docg3 *docg3 = mtd->priv; |
727 | int block0, block1, page, ofs, is_good; | 1024 | int block0, block1, page, ofs, is_good; |
728 | 1025 | ||
729 | calc_block_sector(from, &block0, &block1, &page, &ofs); | 1026 | calc_block_sector(from, &block0, &block1, &page, &ofs, |
1027 | docg3->reliable); | ||
730 | doc_dbg("doc_block_isbad(from=%lld) => block=(%d,%d), page=%d, ofs=%d\n", | 1028 | doc_dbg("doc_block_isbad(from=%lld) => block=(%d,%d), page=%d, ofs=%d\n", |
731 | from, block0, block1, page, ofs); | 1029 | from, block0, block1, page, ofs); |
732 | 1030 | ||
@@ -739,6 +1037,7 @@ static int doc_block_isbad(struct mtd_info *mtd, loff_t from) | |||
739 | return !is_good; | 1037 | return !is_good; |
740 | } | 1038 | } |
741 | 1039 | ||
1040 | #if 0 | ||
742 | /** | 1041 | /** |
743 | * doc_get_erase_count - Get block erase count | 1042 | * doc_get_erase_count - Get block erase count |
744 | * @docg3: the device | 1043 | * @docg3: the device |
@@ -758,7 +1057,7 @@ static int doc_get_erase_count(struct docg3 *docg3, loff_t from) | |||
758 | doc_dbg("doc_get_erase_count(from=%lld, buf=%p)\n", from, buf); | 1057 | doc_dbg("doc_get_erase_count(from=%lld, buf=%p)\n", from, buf); |
759 | if (from % DOC_LAYOUT_PAGE_SIZE) | 1058 | if (from % DOC_LAYOUT_PAGE_SIZE) |
760 | return -EINVAL; | 1059 | return -EINVAL; |
761 | calc_block_sector(from, &block0, &block1, &page, &ofs); | 1060 | calc_block_sector(from, &block0, &block1, &page, &ofs, docg3->reliable); |
762 | if (block1 > docg3->max_block) | 1061 | if (block1 > docg3->max_block) |
763 | return -EINVAL; | 1062 | return -EINVAL; |
764 | 1063 | ||
@@ -780,6 +1079,558 @@ static int doc_get_erase_count(struct docg3 *docg3, loff_t from) | |||
780 | 1079 | ||
781 | return max(plane1_erase_count, plane2_erase_count); | 1080 | return max(plane1_erase_count, plane2_erase_count); |
782 | } | 1081 | } |
1082 | #endif | ||
1083 | |||
1084 | /** | ||
1085 | * doc_get_op_status - get erase/write operation status | ||
1086 | * @docg3: the device | ||
1087 | * | ||
1088 | * Queries the status from the chip, and returns it | ||
1089 | * | ||
1090 | * Returns the status (bits DOC_PLANES_STATUS_*) | ||
1091 | */ | ||
1092 | static int doc_get_op_status(struct docg3 *docg3) | ||
1093 | { | ||
1094 | u8 status; | ||
1095 | |||
1096 | doc_flash_sequence(docg3, DOC_SEQ_PLANES_STATUS); | ||
1097 | doc_flash_command(docg3, DOC_CMD_PLANES_STATUS); | ||
1098 | doc_delay(docg3, 5); | ||
1099 | |||
1100 | doc_ecc_disable(docg3); | ||
1101 | doc_read_data_area(docg3, &status, 1, 1); | ||
1102 | return status; | ||
1103 | } | ||
1104 | |||
1105 | /** | ||
1106 | * doc_write_erase_wait_status - wait for write or erase completion | ||
1107 | * @docg3: the device | ||
1108 | * | ||
1109 | * Wait for the chip to be ready again after erase or write operation, and check | ||
1110 | * erase/write status. | ||
1111 | * | ||
1112 | * Returns 0 if erase successfull, -EIO if erase/write issue, -ETIMEOUT if | ||
1113 | * timeout | ||
1114 | */ | ||
1115 | static int doc_write_erase_wait_status(struct docg3 *docg3) | ||
1116 | { | ||
1117 | int status, ret = 0; | ||
1118 | |||
1119 | if (!doc_is_ready(docg3)) | ||
1120 | usleep_range(3000, 3000); | ||
1121 | if (!doc_is_ready(docg3)) { | ||
1122 | doc_dbg("Timeout reached and the chip is still not ready\n"); | ||
1123 | ret = -EAGAIN; | ||
1124 | goto out; | ||
1125 | } | ||
1126 | |||
1127 | status = doc_get_op_status(docg3); | ||
1128 | if (status & DOC_PLANES_STATUS_FAIL) { | ||
1129 | doc_dbg("Erase/Write failed on (a) plane(s), status = %x\n", | ||
1130 | status); | ||
1131 | ret = -EIO; | ||
1132 | } | ||
1133 | |||
1134 | out: | ||
1135 | doc_page_finish(docg3); | ||
1136 | return ret; | ||
1137 | } | ||
1138 | |||
1139 | /** | ||
1140 | * doc_erase_block - Erase a couple of blocks | ||
1141 | * @docg3: the device | ||
1142 | * @block0: the first block to erase (leftmost plane) | ||
1143 | * @block1: the second block to erase (rightmost plane) | ||
1144 | * | ||
1145 | * Erase both blocks, and return operation status | ||
1146 | * | ||
1147 | * Returns 0 if erase successful, -EIO if erase issue, -ETIMEOUT if chip not | ||
1148 | * ready for too long | ||
1149 | */ | ||
1150 | static int doc_erase_block(struct docg3 *docg3, int block0, int block1) | ||
1151 | { | ||
1152 | int ret, sector; | ||
1153 | |||
1154 | doc_dbg("doc_erase_block(blocks=(%d,%d))\n", block0, block1); | ||
1155 | ret = doc_reset_seq(docg3); | ||
1156 | if (ret) | ||
1157 | return -EIO; | ||
1158 | |||
1159 | doc_set_reliable_mode(docg3); | ||
1160 | doc_flash_sequence(docg3, DOC_SEQ_ERASE); | ||
1161 | |||
1162 | sector = block0 << DOC_ADDR_BLOCK_SHIFT; | ||
1163 | doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR); | ||
1164 | doc_setup_addr_sector(docg3, sector); | ||
1165 | sector = block1 << DOC_ADDR_BLOCK_SHIFT; | ||
1166 | doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR); | ||
1167 | doc_setup_addr_sector(docg3, sector); | ||
1168 | doc_delay(docg3, 1); | ||
1169 | |||
1170 | doc_flash_command(docg3, DOC_CMD_ERASECYCLE2); | ||
1171 | doc_delay(docg3, 2); | ||
1172 | |||
1173 | if (is_prot_seq_error(docg3)) { | ||
1174 | doc_err("Erase blocks %d,%d error\n", block0, block1); | ||
1175 | return -EIO; | ||
1176 | } | ||
1177 | |||
1178 | return doc_write_erase_wait_status(docg3); | ||
1179 | } | ||
1180 | |||
1181 | /** | ||
1182 | * doc_erase - Erase a portion of the chip | ||
1183 | * @mtd: the device | ||
1184 | * @info: the erase info | ||
1185 | * | ||
1186 | * Erase a bunch of contiguous blocks, by pairs, as a "mtd" page of 1024 is | ||
1187 | * split into 2 pages of 512 bytes on 2 contiguous blocks. | ||
1188 | * | ||
1189 | * Returns 0 if erase successful, -EINVAL if adressing error, -EIO if erase | ||
1190 | * issue | ||
1191 | */ | ||
1192 | static int doc_erase(struct mtd_info *mtd, struct erase_info *info) | ||
1193 | { | ||
1194 | struct docg3 *docg3 = mtd->priv; | ||
1195 | uint64_t len; | ||
1196 | int block0, block1, page, ret, ofs = 0; | ||
1197 | |||
1198 | doc_dbg("doc_erase(from=%lld, len=%lld\n", info->addr, info->len); | ||
1199 | doc_set_device_id(docg3, docg3->device_id); | ||
1200 | |||
1201 | info->state = MTD_ERASE_PENDING; | ||
1202 | calc_block_sector(info->addr + info->len, &block0, &block1, &page, | ||
1203 | &ofs, docg3->reliable); | ||
1204 | ret = -EINVAL; | ||
1205 | if (block1 > docg3->max_block || page || ofs) | ||
1206 | goto reset_err; | ||
1207 | |||
1208 | ret = 0; | ||
1209 | calc_block_sector(info->addr, &block0, &block1, &page, &ofs, | ||
1210 | docg3->reliable); | ||
1211 | doc_set_reliable_mode(docg3); | ||
1212 | for (len = info->len; !ret && len > 0; len -= mtd->erasesize) { | ||
1213 | info->state = MTD_ERASING; | ||
1214 | ret = doc_erase_block(docg3, block0, block1); | ||
1215 | block0 += 2; | ||
1216 | block1 += 2; | ||
1217 | } | ||
1218 | |||
1219 | if (ret) | ||
1220 | goto reset_err; | ||
1221 | |||
1222 | info->state = MTD_ERASE_DONE; | ||
1223 | return 0; | ||
1224 | |||
1225 | reset_err: | ||
1226 | info->state = MTD_ERASE_FAILED; | ||
1227 | return ret; | ||
1228 | } | ||
1229 | |||
1230 | /** | ||
1231 | * doc_write_page - Write a single page to the chip | ||
1232 | * @docg3: the device | ||
1233 | * @to: the offset from first block and first page, in bytes, aligned on page | ||
1234 | * size | ||
1235 | * @buf: buffer to get bytes from | ||
1236 | * @oob: buffer to get out of band bytes from (can be NULL if no OOB should be | ||
1237 | * written) | ||
1238 | * @autoecc: if 0, all 16 bytes from OOB are taken, regardless of HW Hamming or | ||
1239 | * BCH computations. If 1, only bytes 0-7 and byte 15 are taken, | ||
1240 | * remaining ones are filled with hardware Hamming and BCH | ||
1241 | * computations. Its value is not meaningfull is oob == NULL. | ||
1242 | * | ||
1243 | * Write one full page (ie. 1 page split on two planes), of 512 bytes, with the | ||
1244 | * OOB data. The OOB ECC is automatically computed by the hardware Hamming and | ||
1245 | * BCH generator if autoecc is not null. | ||
1246 | * | ||
1247 | * Returns 0 if write successful, -EIO if write error, -EAGAIN if timeout | ||
1248 | */ | ||
1249 | static int doc_write_page(struct docg3 *docg3, loff_t to, const u_char *buf, | ||
1250 | const u_char *oob, int autoecc) | ||
1251 | { | ||
1252 | int block0, block1, page, ret, ofs = 0; | ||
1253 | u8 hwecc[DOC_ECC_BCH_SIZE], hamming; | ||
1254 | |||
1255 | doc_dbg("doc_write_page(to=%lld)\n", to); | ||
1256 | calc_block_sector(to, &block0, &block1, &page, &ofs, docg3->reliable); | ||
1257 | |||
1258 | doc_set_device_id(docg3, docg3->device_id); | ||
1259 | ret = doc_reset_seq(docg3); | ||
1260 | if (ret) | ||
1261 | goto err; | ||
1262 | |||
1263 | /* Program the flash address block and page */ | ||
1264 | ret = doc_write_seek(docg3, block0, block1, page, ofs); | ||
1265 | if (ret) | ||
1266 | goto err; | ||
1267 | |||
1268 | doc_write_page_ecc_init(docg3, DOC_ECC_BCH_TOTAL_BYTES); | ||
1269 | doc_delay(docg3, 2); | ||
1270 | doc_write_page_putbytes(docg3, DOC_LAYOUT_PAGE_SIZE, buf); | ||
1271 | |||
1272 | if (oob && autoecc) { | ||
1273 | doc_write_page_putbytes(docg3, DOC_LAYOUT_OOB_PAGEINFO_SZ, oob); | ||
1274 | doc_delay(docg3, 2); | ||
1275 | oob += DOC_LAYOUT_OOB_UNUSED_OFS; | ||
1276 | |||
1277 | hamming = doc_register_readb(docg3, DOC_HAMMINGPARITY); | ||
1278 | doc_delay(docg3, 2); | ||
1279 | doc_write_page_putbytes(docg3, DOC_LAYOUT_OOB_HAMMING_SZ, | ||
1280 | &hamming); | ||
1281 | doc_delay(docg3, 2); | ||
1282 | |||
1283 | doc_get_bch_hw_ecc(docg3, hwecc); | ||
1284 | doc_write_page_putbytes(docg3, DOC_LAYOUT_OOB_BCH_SZ, hwecc); | ||
1285 | doc_delay(docg3, 2); | ||
1286 | |||
1287 | doc_write_page_putbytes(docg3, DOC_LAYOUT_OOB_UNUSED_SZ, oob); | ||
1288 | } | ||
1289 | if (oob && !autoecc) | ||
1290 | doc_write_page_putbytes(docg3, DOC_LAYOUT_OOB_SIZE, oob); | ||
1291 | |||
1292 | doc_delay(docg3, 2); | ||
1293 | doc_page_finish(docg3); | ||
1294 | doc_delay(docg3, 2); | ||
1295 | doc_flash_command(docg3, DOC_CMD_PROG_CYCLE2); | ||
1296 | doc_delay(docg3, 2); | ||
1297 | |||
1298 | /* | ||
1299 | * The wait status will perform another doc_page_finish() call, but that | ||
1300 | * seems to please the docg3, so leave it. | ||
1301 | */ | ||
1302 | ret = doc_write_erase_wait_status(docg3); | ||
1303 | return ret; | ||
1304 | err: | ||
1305 | doc_read_page_finish(docg3); | ||
1306 | return ret; | ||
1307 | } | ||
1308 | |||
1309 | /** | ||
1310 | * doc_guess_autoecc - Guess autoecc mode from mbd_oob_ops | ||
1311 | * @ops: the oob operations | ||
1312 | * | ||
1313 | * Returns 0 or 1 if success, -EINVAL if invalid oob mode | ||
1314 | */ | ||
1315 | static int doc_guess_autoecc(struct mtd_oob_ops *ops) | ||
1316 | { | ||
1317 | int autoecc; | ||
1318 | |||
1319 | switch (ops->mode) { | ||
1320 | case MTD_OPS_PLACE_OOB: | ||
1321 | case MTD_OPS_AUTO_OOB: | ||
1322 | autoecc = 1; | ||
1323 | break; | ||
1324 | case MTD_OPS_RAW: | ||
1325 | autoecc = 0; | ||
1326 | break; | ||
1327 | default: | ||
1328 | autoecc = -EINVAL; | ||
1329 | } | ||
1330 | return autoecc; | ||
1331 | } | ||
1332 | |||
1333 | /** | ||
1334 | * doc_fill_autooob - Fill a 16 bytes OOB from 8 non-ECC bytes | ||
1335 | * @dst: the target 16 bytes OOB buffer | ||
1336 | * @oobsrc: the source 8 bytes non-ECC OOB buffer | ||
1337 | * | ||
1338 | */ | ||
1339 | static void doc_fill_autooob(u8 *dst, u8 *oobsrc) | ||
1340 | { | ||
1341 | memcpy(dst, oobsrc, DOC_LAYOUT_OOB_PAGEINFO_SZ); | ||
1342 | dst[DOC_LAYOUT_OOB_UNUSED_OFS] = oobsrc[DOC_LAYOUT_OOB_PAGEINFO_SZ]; | ||
1343 | } | ||
1344 | |||
1345 | /** | ||
1346 | * doc_backup_oob - Backup OOB into docg3 structure | ||
1347 | * @docg3: the device | ||
1348 | * @to: the page offset in the chip | ||
1349 | * @ops: the OOB size and buffer | ||
1350 | * | ||
1351 | * As the docg3 should write a page with its OOB in one pass, and some userland | ||
1352 | * applications do write_oob() to setup the OOB and then write(), store the OOB | ||
1353 | * into a temporary storage. This is very dangerous, as 2 concurrent | ||
1354 | * applications could store an OOB, and then write their pages (which will | ||
1355 | * result into one having its OOB corrupted). | ||
1356 | * | ||
1357 | * The only reliable way would be for userland to call doc_write_oob() with both | ||
1358 | * the page data _and_ the OOB area. | ||
1359 | * | ||
1360 | * Returns 0 if success, -EINVAL if ops content invalid | ||
1361 | */ | ||
1362 | static int doc_backup_oob(struct docg3 *docg3, loff_t to, | ||
1363 | struct mtd_oob_ops *ops) | ||
1364 | { | ||
1365 | int ooblen = ops->ooblen, autoecc; | ||
1366 | |||
1367 | if (ooblen != DOC_LAYOUT_OOB_SIZE) | ||
1368 | return -EINVAL; | ||
1369 | autoecc = doc_guess_autoecc(ops); | ||
1370 | if (autoecc < 0) | ||
1371 | return autoecc; | ||
1372 | |||
1373 | docg3->oob_write_ofs = to; | ||
1374 | docg3->oob_autoecc = autoecc; | ||
1375 | if (ops->mode == MTD_OPS_AUTO_OOB) { | ||
1376 | doc_fill_autooob(docg3->oob_write_buf, ops->oobbuf); | ||
1377 | ops->oobretlen = 8; | ||
1378 | } else { | ||
1379 | memcpy(docg3->oob_write_buf, ops->oobbuf, DOC_LAYOUT_OOB_SIZE); | ||
1380 | ops->oobretlen = DOC_LAYOUT_OOB_SIZE; | ||
1381 | } | ||
1382 | return 0; | ||
1383 | } | ||
1384 | |||
1385 | /** | ||
1386 | * doc_write_oob - Write out of band bytes to flash | ||
1387 | * @mtd: the device | ||
1388 | * @ofs: the offset from first block and first page, in bytes, aligned on page | ||
1389 | * size | ||
1390 | * @ops: the mtd oob structure | ||
1391 | * | ||
1392 | * Either write OOB data into a temporary buffer, for the subsequent write | ||
1393 | * page. The provided OOB should be 16 bytes long. If a data buffer is provided | ||
1394 | * as well, issue the page write. | ||
1395 | * Or provide data without OOB, and then a all zeroed OOB will be used (ECC will | ||
1396 | * still be filled in if asked for). | ||
1397 | * | ||
1398 | * Returns 0 is successfull, EINVAL if length is not 14 bytes | ||
1399 | */ | ||
1400 | static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, | ||
1401 | struct mtd_oob_ops *ops) | ||
1402 | { | ||
1403 | struct docg3 *docg3 = mtd->priv; | ||
1404 | int block0, block1, page, ret, pofs = 0, autoecc, oobdelta; | ||
1405 | u8 *oobbuf = ops->oobbuf; | ||
1406 | u8 *buf = ops->datbuf; | ||
1407 | size_t len, ooblen; | ||
1408 | u8 oob[DOC_LAYOUT_OOB_SIZE]; | ||
1409 | |||
1410 | if (buf) | ||
1411 | len = ops->len; | ||
1412 | else | ||
1413 | len = 0; | ||
1414 | if (oobbuf) | ||
1415 | ooblen = ops->ooblen; | ||
1416 | else | ||
1417 | ooblen = 0; | ||
1418 | |||
1419 | if (oobbuf && ops->mode == MTD_OPS_PLACE_OOB) | ||
1420 | oobbuf += ops->ooboffs; | ||
1421 | |||
1422 | doc_dbg("doc_write_oob(from=%lld, mode=%d, data=(%p:%zu), oob=(%p:%zu))\n", | ||
1423 | ofs, ops->mode, buf, len, oobbuf, ooblen); | ||
1424 | switch (ops->mode) { | ||
1425 | case MTD_OPS_PLACE_OOB: | ||
1426 | case MTD_OPS_RAW: | ||
1427 | oobdelta = mtd->oobsize; | ||
1428 | break; | ||
1429 | case MTD_OPS_AUTO_OOB: | ||
1430 | oobdelta = mtd->ecclayout->oobavail; | ||
1431 | break; | ||
1432 | default: | ||
1433 | oobdelta = 0; | ||
1434 | } | ||
1435 | if ((len % DOC_LAYOUT_PAGE_SIZE) || (ooblen % oobdelta) || | ||
1436 | (ofs % DOC_LAYOUT_PAGE_SIZE)) | ||
1437 | return -EINVAL; | ||
1438 | if (len && ooblen && | ||
1439 | (len / DOC_LAYOUT_PAGE_SIZE) != (ooblen / oobdelta)) | ||
1440 | return -EINVAL; | ||
1441 | |||
1442 | ret = -EINVAL; | ||
1443 | calc_block_sector(ofs + len, &block0, &block1, &page, &pofs, | ||
1444 | docg3->reliable); | ||
1445 | if (block1 > docg3->max_block) | ||
1446 | goto err; | ||
1447 | |||
1448 | ops->oobretlen = 0; | ||
1449 | ops->retlen = 0; | ||
1450 | ret = 0; | ||
1451 | if (len == 0 && ooblen == 0) | ||
1452 | return -EINVAL; | ||
1453 | if (len == 0 && ooblen > 0) | ||
1454 | return doc_backup_oob(docg3, ofs, ops); | ||
1455 | |||
1456 | autoecc = doc_guess_autoecc(ops); | ||
1457 | if (autoecc < 0) | ||
1458 | return autoecc; | ||
1459 | |||
1460 | while (!ret && len > 0) { | ||
1461 | memset(oob, 0, sizeof(oob)); | ||
1462 | if (ofs == docg3->oob_write_ofs) | ||
1463 | memcpy(oob, docg3->oob_write_buf, DOC_LAYOUT_OOB_SIZE); | ||
1464 | else if (ooblen > 0 && ops->mode == MTD_OPS_AUTO_OOB) | ||
1465 | doc_fill_autooob(oob, oobbuf); | ||
1466 | else if (ooblen > 0) | ||
1467 | memcpy(oob, oobbuf, DOC_LAYOUT_OOB_SIZE); | ||
1468 | ret = doc_write_page(docg3, ofs, buf, oob, autoecc); | ||
1469 | |||
1470 | ofs += DOC_LAYOUT_PAGE_SIZE; | ||
1471 | len -= DOC_LAYOUT_PAGE_SIZE; | ||
1472 | buf += DOC_LAYOUT_PAGE_SIZE; | ||
1473 | if (ooblen) { | ||
1474 | oobbuf += oobdelta; | ||
1475 | ooblen -= oobdelta; | ||
1476 | ops->oobretlen += oobdelta; | ||
1477 | } | ||
1478 | ops->retlen += DOC_LAYOUT_PAGE_SIZE; | ||
1479 | } | ||
1480 | err: | ||
1481 | doc_set_device_id(docg3, 0); | ||
1482 | return ret; | ||
1483 | } | ||
1484 | |||
1485 | /** | ||
1486 | * doc_write - Write a buffer to the chip | ||
1487 | * @mtd: the device | ||
1488 | * @to: the offset from first block and first page, in bytes, aligned on page | ||
1489 | * size | ||
1490 | * @len: the number of bytes to write (must be a full page size, ie. 512) | ||
1491 | * @retlen: the number of bytes actually written (0 or 512) | ||
1492 | * @buf: the buffer to get bytes from | ||
1493 | * | ||
1494 | * Writes data to the chip. | ||
1495 | * | ||
1496 | * Returns 0 if write successful, -EIO if write error | ||
1497 | */ | ||
1498 | static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, | ||
1499 | size_t *retlen, const u_char *buf) | ||
1500 | { | ||
1501 | struct docg3 *docg3 = mtd->priv; | ||
1502 | int ret; | ||
1503 | struct mtd_oob_ops ops; | ||
1504 | |||
1505 | doc_dbg("doc_write(to=%lld, len=%zu)\n", to, len); | ||
1506 | ops.datbuf = (char *)buf; | ||
1507 | ops.len = len; | ||
1508 | ops.mode = MTD_OPS_PLACE_OOB; | ||
1509 | ops.oobbuf = NULL; | ||
1510 | ops.ooblen = 0; | ||
1511 | ops.ooboffs = 0; | ||
1512 | |||
1513 | ret = doc_write_oob(mtd, to, &ops); | ||
1514 | *retlen = ops.retlen; | ||
1515 | return ret; | ||
1516 | } | ||
1517 | |||
1518 | static struct docg3 *sysfs_dev2docg3(struct device *dev, | ||
1519 | struct device_attribute *attr) | ||
1520 | { | ||
1521 | int floor; | ||
1522 | struct platform_device *pdev = to_platform_device(dev); | ||
1523 | struct mtd_info **docg3_floors = platform_get_drvdata(pdev); | ||
1524 | |||
1525 | floor = attr->attr.name[1] - '0'; | ||
1526 | if (floor < 0 || floor >= DOC_MAX_NBFLOORS) | ||
1527 | return NULL; | ||
1528 | else | ||
1529 | return docg3_floors[floor]->priv; | ||
1530 | } | ||
1531 | |||
1532 | static ssize_t dps0_is_key_locked(struct device *dev, | ||
1533 | struct device_attribute *attr, char *buf) | ||
1534 | { | ||
1535 | struct docg3 *docg3 = sysfs_dev2docg3(dev, attr); | ||
1536 | int dps0; | ||
1537 | |||
1538 | doc_set_device_id(docg3, docg3->device_id); | ||
1539 | dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS); | ||
1540 | doc_set_device_id(docg3, 0); | ||
1541 | |||
1542 | return sprintf(buf, "%d\n", !(dps0 & DOC_DPS_KEY_OK)); | ||
1543 | } | ||
1544 | |||
1545 | static ssize_t dps1_is_key_locked(struct device *dev, | ||
1546 | struct device_attribute *attr, char *buf) | ||
1547 | { | ||
1548 | struct docg3 *docg3 = sysfs_dev2docg3(dev, attr); | ||
1549 | int dps1; | ||
1550 | |||
1551 | doc_set_device_id(docg3, docg3->device_id); | ||
1552 | dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS); | ||
1553 | doc_set_device_id(docg3, 0); | ||
1554 | |||
1555 | return sprintf(buf, "%d\n", !(dps1 & DOC_DPS_KEY_OK)); | ||
1556 | } | ||
1557 | |||
1558 | static ssize_t dps0_insert_key(struct device *dev, | ||
1559 | struct device_attribute *attr, | ||
1560 | const char *buf, size_t count) | ||
1561 | { | ||
1562 | struct docg3 *docg3 = sysfs_dev2docg3(dev, attr); | ||
1563 | int i; | ||
1564 | |||
1565 | if (count != DOC_LAYOUT_DPS_KEY_LENGTH) | ||
1566 | return -EINVAL; | ||
1567 | |||
1568 | doc_set_device_id(docg3, docg3->device_id); | ||
1569 | for (i = 0; i < DOC_LAYOUT_DPS_KEY_LENGTH; i++) | ||
1570 | doc_writeb(docg3, buf[i], DOC_DPS0_KEY); | ||
1571 | doc_set_device_id(docg3, 0); | ||
1572 | return count; | ||
1573 | } | ||
1574 | |||
1575 | static ssize_t dps1_insert_key(struct device *dev, | ||
1576 | struct device_attribute *attr, | ||
1577 | const char *buf, size_t count) | ||
1578 | { | ||
1579 | struct docg3 *docg3 = sysfs_dev2docg3(dev, attr); | ||
1580 | int i; | ||
1581 | |||
1582 | if (count != DOC_LAYOUT_DPS_KEY_LENGTH) | ||
1583 | return -EINVAL; | ||
1584 | |||
1585 | doc_set_device_id(docg3, docg3->device_id); | ||
1586 | for (i = 0; i < DOC_LAYOUT_DPS_KEY_LENGTH; i++) | ||
1587 | doc_writeb(docg3, buf[i], DOC_DPS1_KEY); | ||
1588 | doc_set_device_id(docg3, 0); | ||
1589 | return count; | ||
1590 | } | ||
1591 | |||
1592 | #define FLOOR_SYSFS(id) { \ | ||
1593 | __ATTR(f##id##_dps0_is_keylocked, S_IRUGO, dps0_is_key_locked, NULL), \ | ||
1594 | __ATTR(f##id##_dps1_is_keylocked, S_IRUGO, dps1_is_key_locked, NULL), \ | ||
1595 | __ATTR(f##id##_dps0_protection_key, S_IWUGO, NULL, dps0_insert_key), \ | ||
1596 | __ATTR(f##id##_dps1_protection_key, S_IWUGO, NULL, dps1_insert_key), \ | ||
1597 | } | ||
1598 | |||
1599 | static struct device_attribute doc_sys_attrs[DOC_MAX_NBFLOORS][4] = { | ||
1600 | FLOOR_SYSFS(0), FLOOR_SYSFS(1), FLOOR_SYSFS(2), FLOOR_SYSFS(3) | ||
1601 | }; | ||
1602 | |||
1603 | static int doc_register_sysfs(struct platform_device *pdev, | ||
1604 | struct mtd_info **floors) | ||
1605 | { | ||
1606 | int ret = 0, floor, i = 0; | ||
1607 | struct device *dev = &pdev->dev; | ||
1608 | |||
1609 | for (floor = 0; !ret && floor < DOC_MAX_NBFLOORS && floors[floor]; | ||
1610 | floor++) | ||
1611 | for (i = 0; !ret && i < 4; i++) | ||
1612 | ret = device_create_file(dev, &doc_sys_attrs[floor][i]); | ||
1613 | if (!ret) | ||
1614 | return 0; | ||
1615 | do { | ||
1616 | while (--i >= 0) | ||
1617 | device_remove_file(dev, &doc_sys_attrs[floor][i]); | ||
1618 | i = 4; | ||
1619 | } while (--floor >= 0); | ||
1620 | return ret; | ||
1621 | } | ||
1622 | |||
1623 | static void doc_unregister_sysfs(struct platform_device *pdev, | ||
1624 | struct mtd_info **floors) | ||
1625 | { | ||
1626 | struct device *dev = &pdev->dev; | ||
1627 | int floor, i; | ||
1628 | |||
1629 | for (floor = 0; floor < DOC_MAX_NBFLOORS && floors[floor]; | ||
1630 | floor++) | ||
1631 | for (i = 0; i < 4; i++) | ||
1632 | device_remove_file(dev, &doc_sys_attrs[floor][i]); | ||
1633 | } | ||
783 | 1634 | ||
784 | /* | 1635 | /* |
785 | * Debug sysfs entries | 1636 | * Debug sysfs entries |
@@ -852,13 +1703,15 @@ static int dbg_protection_show(struct seq_file *s, void *p) | |||
852 | { | 1703 | { |
853 | struct docg3 *docg3 = (struct docg3 *)s->private; | 1704 | struct docg3 *docg3 = (struct docg3 *)s->private; |
854 | int pos = 0; | 1705 | int pos = 0; |
855 | int protect = doc_register_readb(docg3, DOC_PROTECTION); | 1706 | int protect, dps0, dps0_low, dps0_high, dps1, dps1_low, dps1_high; |
856 | int dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS); | 1707 | |
857 | int dps0_low = doc_register_readb(docg3, DOC_DPS0_ADDRLOW); | 1708 | protect = doc_register_readb(docg3, DOC_PROTECTION); |
858 | int dps0_high = doc_register_readb(docg3, DOC_DPS0_ADDRHIGH); | 1709 | dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS); |
859 | int dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS); | 1710 | dps0_low = doc_register_readw(docg3, DOC_DPS0_ADDRLOW); |
860 | int dps1_low = doc_register_readb(docg3, DOC_DPS1_ADDRLOW); | 1711 | dps0_high = doc_register_readw(docg3, DOC_DPS0_ADDRHIGH); |
861 | int dps1_high = doc_register_readb(docg3, DOC_DPS1_ADDRHIGH); | 1712 | dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS); |
1713 | dps1_low = doc_register_readw(docg3, DOC_DPS1_ADDRLOW); | ||
1714 | dps1_high = doc_register_readw(docg3, DOC_DPS1_ADDRHIGH); | ||
862 | 1715 | ||
863 | pos += seq_printf(s, "Protection = 0x%02x (", | 1716 | pos += seq_printf(s, "Protection = 0x%02x (", |
864 | protect); | 1717 | protect); |
@@ -947,52 +1800,54 @@ static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd) | |||
947 | 1800 | ||
948 | cfg = doc_register_readb(docg3, DOC_CONFIGURATION); | 1801 | cfg = doc_register_readb(docg3, DOC_CONFIGURATION); |
949 | docg3->if_cfg = (cfg & DOC_CONF_IF_CFG ? 1 : 0); | 1802 | docg3->if_cfg = (cfg & DOC_CONF_IF_CFG ? 1 : 0); |
1803 | docg3->reliable = reliable_mode; | ||
950 | 1804 | ||
951 | switch (chip_id) { | 1805 | switch (chip_id) { |
952 | case DOC_CHIPID_G3: | 1806 | case DOC_CHIPID_G3: |
953 | mtd->name = "DiskOnChip G3"; | 1807 | mtd->name = kasprintf(GFP_KERNEL, "DiskOnChip G3 floor %d", |
1808 | docg3->device_id); | ||
954 | docg3->max_block = 2047; | 1809 | docg3->max_block = 2047; |
955 | break; | 1810 | break; |
956 | } | 1811 | } |
957 | mtd->type = MTD_NANDFLASH; | 1812 | mtd->type = MTD_NANDFLASH; |
958 | /* | 1813 | mtd->flags = MTD_CAP_NANDFLASH; |
959 | * Once write methods are added, the correct flags will be set. | ||
960 | * mtd->flags = MTD_CAP_NANDFLASH; | ||
961 | */ | ||
962 | mtd->flags = MTD_CAP_ROM; | ||
963 | mtd->size = (docg3->max_block + 1) * DOC_LAYOUT_BLOCK_SIZE; | 1814 | mtd->size = (docg3->max_block + 1) * DOC_LAYOUT_BLOCK_SIZE; |
1815 | if (docg3->reliable == 2) | ||
1816 | mtd->size /= 2; | ||
964 | mtd->erasesize = DOC_LAYOUT_BLOCK_SIZE * DOC_LAYOUT_NBPLANES; | 1817 | mtd->erasesize = DOC_LAYOUT_BLOCK_SIZE * DOC_LAYOUT_NBPLANES; |
1818 | if (docg3->reliable == 2) | ||
1819 | mtd->erasesize /= 2; | ||
965 | mtd->writesize = DOC_LAYOUT_PAGE_SIZE; | 1820 | mtd->writesize = DOC_LAYOUT_PAGE_SIZE; |
966 | mtd->oobsize = DOC_LAYOUT_OOB_SIZE; | 1821 | mtd->oobsize = DOC_LAYOUT_OOB_SIZE; |
967 | mtd->owner = THIS_MODULE; | 1822 | mtd->owner = THIS_MODULE; |
968 | mtd->erase = NULL; | 1823 | mtd->erase = doc_erase; |
969 | mtd->point = NULL; | ||
970 | mtd->unpoint = NULL; | ||
971 | mtd->read = doc_read; | 1824 | mtd->read = doc_read; |
972 | mtd->write = NULL; | 1825 | mtd->write = doc_write; |
973 | mtd->read_oob = doc_read_oob; | 1826 | mtd->read_oob = doc_read_oob; |
974 | mtd->write_oob = NULL; | 1827 | mtd->write_oob = doc_write_oob; |
975 | mtd->sync = NULL; | ||
976 | mtd->block_isbad = doc_block_isbad; | 1828 | mtd->block_isbad = doc_block_isbad; |
1829 | mtd->ecclayout = &docg3_oobinfo; | ||
977 | } | 1830 | } |
978 | 1831 | ||
979 | /** | 1832 | /** |
980 | * doc_probe - Probe the IO space for a DiskOnChip G3 chip | 1833 | * doc_probe_device - Check if a device is available |
981 | * @pdev: platform device | 1834 | * @base: the io space where the device is probed |
1835 | * @floor: the floor of the probed device | ||
1836 | * @dev: the device | ||
982 | * | 1837 | * |
983 | * Probes for a G3 chip at the specified IO space in the platform data | 1838 | * Checks whether a device at the specified IO range, and floor is available. |
984 | * ressources. | ||
985 | * | 1839 | * |
986 | * Returns 0 on success, -ENOMEM, -ENXIO on error | 1840 | * Returns a mtd_info struct if there is a device, ENODEV if none found, ENOMEM |
1841 | * if a memory allocation failed. If floor 0 is checked, a reset of the ASIC is | ||
1842 | * launched. | ||
987 | */ | 1843 | */ |
988 | static int __init docg3_probe(struct platform_device *pdev) | 1844 | static struct mtd_info *doc_probe_device(void __iomem *base, int floor, |
1845 | struct device *dev) | ||
989 | { | 1846 | { |
990 | struct device *dev = &pdev->dev; | ||
991 | struct docg3 *docg3; | ||
992 | struct mtd_info *mtd; | ||
993 | struct resource *ress; | ||
994 | int ret, bbt_nbpages; | 1847 | int ret, bbt_nbpages; |
995 | u16 chip_id, chip_id_inv; | 1848 | u16 chip_id, chip_id_inv; |
1849 | struct docg3 *docg3; | ||
1850 | struct mtd_info *mtd; | ||
996 | 1851 | ||
997 | ret = -ENOMEM; | 1852 | ret = -ENOMEM; |
998 | docg3 = kzalloc(sizeof(struct docg3), GFP_KERNEL); | 1853 | docg3 = kzalloc(sizeof(struct docg3), GFP_KERNEL); |
@@ -1002,69 +1857,218 @@ static int __init docg3_probe(struct platform_device *pdev) | |||
1002 | if (!mtd) | 1857 | if (!mtd) |
1003 | goto nomem2; | 1858 | goto nomem2; |
1004 | mtd->priv = docg3; | 1859 | mtd->priv = docg3; |
1860 | bbt_nbpages = DIV_ROUND_UP(docg3->max_block + 1, | ||
1861 | 8 * DOC_LAYOUT_PAGE_SIZE); | ||
1862 | docg3->bbt = kzalloc(bbt_nbpages * DOC_LAYOUT_PAGE_SIZE, GFP_KERNEL); | ||
1863 | if (!docg3->bbt) | ||
1864 | goto nomem3; | ||
1005 | 1865 | ||
1006 | ret = -ENXIO; | 1866 | docg3->dev = dev; |
1007 | ress = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1867 | docg3->device_id = floor; |
1008 | if (!ress) { | 1868 | docg3->base = base; |
1009 | dev_err(dev, "No I/O memory resource defined\n"); | ||
1010 | goto noress; | ||
1011 | } | ||
1012 | docg3->base = ioremap(ress->start, DOC_IOSPACE_SIZE); | ||
1013 | |||
1014 | docg3->dev = &pdev->dev; | ||
1015 | docg3->device_id = 0; | ||
1016 | doc_set_device_id(docg3, docg3->device_id); | 1869 | doc_set_device_id(docg3, docg3->device_id); |
1017 | doc_set_asic_mode(docg3, DOC_ASICMODE_RESET); | 1870 | if (!floor) |
1871 | doc_set_asic_mode(docg3, DOC_ASICMODE_RESET); | ||
1018 | doc_set_asic_mode(docg3, DOC_ASICMODE_NORMAL); | 1872 | doc_set_asic_mode(docg3, DOC_ASICMODE_NORMAL); |
1019 | 1873 | ||
1020 | chip_id = doc_register_readw(docg3, DOC_CHIPID); | 1874 | chip_id = doc_register_readw(docg3, DOC_CHIPID); |
1021 | chip_id_inv = doc_register_readw(docg3, DOC_CHIPID_INV); | 1875 | chip_id_inv = doc_register_readw(docg3, DOC_CHIPID_INV); |
1022 | 1876 | ||
1023 | ret = -ENODEV; | 1877 | ret = 0; |
1024 | if (chip_id != (u16)(~chip_id_inv)) { | 1878 | if (chip_id != (u16)(~chip_id_inv)) { |
1025 | doc_info("No device found at IO addr %p\n", | 1879 | goto nomem3; |
1026 | (void *)ress->start); | ||
1027 | goto nochipfound; | ||
1028 | } | 1880 | } |
1029 | 1881 | ||
1030 | switch (chip_id) { | 1882 | switch (chip_id) { |
1031 | case DOC_CHIPID_G3: | 1883 | case DOC_CHIPID_G3: |
1032 | doc_info("Found a G3 DiskOnChip at addr %p\n", | 1884 | doc_info("Found a G3 DiskOnChip at addr %p, floor %d\n", |
1033 | (void *)ress->start); | 1885 | base, floor); |
1034 | break; | 1886 | break; |
1035 | default: | 1887 | default: |
1036 | doc_err("Chip id %04x is not a DiskOnChip G3 chip\n", chip_id); | 1888 | doc_err("Chip id %04x is not a DiskOnChip G3 chip\n", chip_id); |
1037 | goto nochipfound; | 1889 | goto nomem3; |
1038 | } | 1890 | } |
1039 | 1891 | ||
1040 | doc_set_driver_info(chip_id, mtd); | 1892 | doc_set_driver_info(chip_id, mtd); |
1041 | platform_set_drvdata(pdev, mtd); | ||
1042 | 1893 | ||
1043 | ret = -ENOMEM; | 1894 | doc_hamming_ecc_init(docg3, DOC_LAYOUT_OOB_PAGEINFO_SZ); |
1044 | bbt_nbpages = DIV_ROUND_UP(docg3->max_block + 1, | ||
1045 | 8 * DOC_LAYOUT_PAGE_SIZE); | ||
1046 | docg3->bbt = kzalloc(bbt_nbpages * DOC_LAYOUT_PAGE_SIZE, GFP_KERNEL); | ||
1047 | if (!docg3->bbt) | ||
1048 | goto nochipfound; | ||
1049 | doc_reload_bbt(docg3); | 1895 | doc_reload_bbt(docg3); |
1896 | return mtd; | ||
1050 | 1897 | ||
1051 | ret = mtd_device_parse_register(mtd, part_probes, | 1898 | nomem3: |
1052 | NULL, NULL, 0); | 1899 | kfree(mtd); |
1053 | if (ret) | 1900 | nomem2: |
1054 | goto register_error; | 1901 | kfree(docg3); |
1902 | nomem1: | ||
1903 | return ERR_PTR(ret); | ||
1904 | } | ||
1055 | 1905 | ||
1056 | doc_dbg_register(docg3); | 1906 | /** |
1057 | return 0; | 1907 | * doc_release_device - Release a docg3 floor |
1908 | * @mtd: the device | ||
1909 | */ | ||
1910 | static void doc_release_device(struct mtd_info *mtd) | ||
1911 | { | ||
1912 | struct docg3 *docg3 = mtd->priv; | ||
1058 | 1913 | ||
1059 | register_error: | 1914 | mtd_device_unregister(mtd); |
1060 | kfree(docg3->bbt); | 1915 | kfree(docg3->bbt); |
1061 | nochipfound: | 1916 | kfree(docg3); |
1062 | iounmap(docg3->base); | 1917 | kfree(mtd->name); |
1063 | noress: | ||
1064 | kfree(mtd); | 1918 | kfree(mtd); |
1919 | } | ||
1920 | |||
1921 | /** | ||
1922 | * docg3_resume - Awakens docg3 floor | ||
1923 | * @pdev: platfrom device | ||
1924 | * | ||
1925 | * Returns 0 (always successfull) | ||
1926 | */ | ||
1927 | static int docg3_resume(struct platform_device *pdev) | ||
1928 | { | ||
1929 | int i; | ||
1930 | struct mtd_info **docg3_floors, *mtd; | ||
1931 | struct docg3 *docg3; | ||
1932 | |||
1933 | docg3_floors = platform_get_drvdata(pdev); | ||
1934 | mtd = docg3_floors[0]; | ||
1935 | docg3 = mtd->priv; | ||
1936 | |||
1937 | doc_dbg("docg3_resume()\n"); | ||
1938 | for (i = 0; i < 12; i++) | ||
1939 | doc_readb(docg3, DOC_IOSPACE_IPL); | ||
1940 | return 0; | ||
1941 | } | ||
1942 | |||
1943 | /** | ||
1944 | * docg3_suspend - Put in low power mode the docg3 floor | ||
1945 | * @pdev: platform device | ||
1946 | * @state: power state | ||
1947 | * | ||
1948 | * Shuts off most of docg3 circuitery to lower power consumption. | ||
1949 | * | ||
1950 | * Returns 0 if suspend succeeded, -EIO if chip refused suspend | ||
1951 | */ | ||
1952 | static int docg3_suspend(struct platform_device *pdev, pm_message_t state) | ||
1953 | { | ||
1954 | int floor, i; | ||
1955 | struct mtd_info **docg3_floors, *mtd; | ||
1956 | struct docg3 *docg3; | ||
1957 | u8 ctrl, pwr_down; | ||
1958 | |||
1959 | docg3_floors = platform_get_drvdata(pdev); | ||
1960 | for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) { | ||
1961 | mtd = docg3_floors[floor]; | ||
1962 | if (!mtd) | ||
1963 | continue; | ||
1964 | docg3 = mtd->priv; | ||
1965 | |||
1966 | doc_writeb(docg3, floor, DOC_DEVICESELECT); | ||
1967 | ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
1968 | ctrl &= ~DOC_CTRL_VIOLATION & ~DOC_CTRL_CE; | ||
1969 | doc_writeb(docg3, ctrl, DOC_FLASHCONTROL); | ||
1970 | |||
1971 | for (i = 0; i < 10; i++) { | ||
1972 | usleep_range(3000, 4000); | ||
1973 | pwr_down = doc_register_readb(docg3, DOC_POWERMODE); | ||
1974 | if (pwr_down & DOC_POWERDOWN_READY) | ||
1975 | break; | ||
1976 | } | ||
1977 | if (pwr_down & DOC_POWERDOWN_READY) { | ||
1978 | doc_dbg("docg3_suspend(): floor %d powerdown ok\n", | ||
1979 | floor); | ||
1980 | } else { | ||
1981 | doc_err("docg3_suspend(): floor %d powerdown failed\n", | ||
1982 | floor); | ||
1983 | return -EIO; | ||
1984 | } | ||
1985 | } | ||
1986 | |||
1987 | mtd = docg3_floors[0]; | ||
1988 | docg3 = mtd->priv; | ||
1989 | doc_set_asic_mode(docg3, DOC_ASICMODE_POWERDOWN); | ||
1990 | return 0; | ||
1991 | } | ||
1992 | |||
1993 | /** | ||
1994 | * doc_probe - Probe the IO space for a DiskOnChip G3 chip | ||
1995 | * @pdev: platform device | ||
1996 | * | ||
1997 | * Probes for a G3 chip at the specified IO space in the platform data | ||
1998 | * ressources. The floor 0 must be available. | ||
1999 | * | ||
2000 | * Returns 0 on success, -ENOMEM, -ENXIO on error | ||
2001 | */ | ||
2002 | static int __init docg3_probe(struct platform_device *pdev) | ||
2003 | { | ||
2004 | struct device *dev = &pdev->dev; | ||
2005 | struct mtd_info *mtd; | ||
2006 | struct resource *ress; | ||
2007 | void __iomem *base; | ||
2008 | int ret, floor, found = 0; | ||
2009 | struct mtd_info **docg3_floors; | ||
2010 | |||
2011 | ret = -ENXIO; | ||
2012 | ress = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
2013 | if (!ress) { | ||
2014 | dev_err(dev, "No I/O memory resource defined\n"); | ||
2015 | goto noress; | ||
2016 | } | ||
2017 | base = ioremap(ress->start, DOC_IOSPACE_SIZE); | ||
2018 | |||
2019 | ret = -ENOMEM; | ||
2020 | docg3_floors = kzalloc(sizeof(*docg3_floors) * DOC_MAX_NBFLOORS, | ||
2021 | GFP_KERNEL); | ||
2022 | if (!docg3_floors) | ||
2023 | goto nomem1; | ||
2024 | docg3_bch = init_bch(DOC_ECC_BCH_M, DOC_ECC_BCH_T, | ||
2025 | DOC_ECC_BCH_PRIMPOLY); | ||
2026 | if (!docg3_bch) | ||
2027 | goto nomem2; | ||
2028 | |||
2029 | for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) { | ||
2030 | mtd = doc_probe_device(base, floor, dev); | ||
2031 | if (IS_ERR(mtd)) { | ||
2032 | ret = PTR_ERR(mtd); | ||
2033 | goto err_probe; | ||
2034 | } | ||
2035 | if (!mtd) { | ||
2036 | if (floor == 0) | ||
2037 | goto notfound; | ||
2038 | else | ||
2039 | continue; | ||
2040 | } | ||
2041 | docg3_floors[floor] = mtd; | ||
2042 | ret = mtd_device_parse_register(mtd, part_probes, NULL, NULL, | ||
2043 | 0); | ||
2044 | if (ret) | ||
2045 | goto err_probe; | ||
2046 | found++; | ||
2047 | } | ||
2048 | |||
2049 | ret = doc_register_sysfs(pdev, docg3_floors); | ||
2050 | if (ret) | ||
2051 | goto err_probe; | ||
2052 | if (!found) | ||
2053 | goto notfound; | ||
2054 | |||
2055 | platform_set_drvdata(pdev, docg3_floors); | ||
2056 | doc_dbg_register(docg3_floors[0]->priv); | ||
2057 | return 0; | ||
2058 | |||
2059 | notfound: | ||
2060 | ret = -ENODEV; | ||
2061 | dev_info(dev, "No supported DiskOnChip found\n"); | ||
2062 | err_probe: | ||
2063 | free_bch(docg3_bch); | ||
2064 | for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) | ||
2065 | if (docg3_floors[floor]) | ||
2066 | doc_release_device(docg3_floors[floor]); | ||
1065 | nomem2: | 2067 | nomem2: |
1066 | kfree(docg3); | 2068 | kfree(docg3_floors); |
1067 | nomem1: | 2069 | nomem1: |
2070 | iounmap(base); | ||
2071 | noress: | ||
1068 | return ret; | 2072 | return ret; |
1069 | } | 2073 | } |
1070 | 2074 | ||
@@ -1076,15 +2080,20 @@ nomem1: | |||
1076 | */ | 2080 | */ |
1077 | static int __exit docg3_release(struct platform_device *pdev) | 2081 | static int __exit docg3_release(struct platform_device *pdev) |
1078 | { | 2082 | { |
1079 | struct mtd_info *mtd = platform_get_drvdata(pdev); | 2083 | struct mtd_info **docg3_floors = platform_get_drvdata(pdev); |
1080 | struct docg3 *docg3 = mtd->priv; | 2084 | struct docg3 *docg3 = docg3_floors[0]->priv; |
2085 | void __iomem *base = docg3->base; | ||
2086 | int floor; | ||
1081 | 2087 | ||
2088 | doc_unregister_sysfs(pdev, docg3_floors); | ||
1082 | doc_dbg_unregister(docg3); | 2089 | doc_dbg_unregister(docg3); |
1083 | mtd_device_unregister(mtd); | 2090 | for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) |
1084 | iounmap(docg3->base); | 2091 | if (docg3_floors[floor]) |
1085 | kfree(docg3->bbt); | 2092 | doc_release_device(docg3_floors[floor]); |
1086 | kfree(docg3); | 2093 | |
1087 | kfree(mtd); | 2094 | kfree(docg3_floors); |
2095 | free_bch(docg3_bch); | ||
2096 | iounmap(base); | ||
1088 | return 0; | 2097 | return 0; |
1089 | } | 2098 | } |
1090 | 2099 | ||
@@ -1093,6 +2102,8 @@ static struct platform_driver g3_driver = { | |||
1093 | .name = "docg3", | 2102 | .name = "docg3", |
1094 | .owner = THIS_MODULE, | 2103 | .owner = THIS_MODULE, |
1095 | }, | 2104 | }, |
2105 | .suspend = docg3_suspend, | ||
2106 | .resume = docg3_resume, | ||
1096 | .remove = __exit_p(docg3_release), | 2107 | .remove = __exit_p(docg3_release), |
1097 | }; | 2108 | }; |
1098 | 2109 | ||
diff --git a/drivers/mtd/devices/docg3.h b/drivers/mtd/devices/docg3.h index 0d407be24594..db0da436b493 100644 --- a/drivers/mtd/devices/docg3.h +++ b/drivers/mtd/devices/docg3.h | |||
@@ -51,10 +51,19 @@ | |||
51 | #define DOC_LAYOUT_WEAR_OFFSET (DOC_LAYOUT_PAGE_OOB_SIZE * 2) | 51 | #define DOC_LAYOUT_WEAR_OFFSET (DOC_LAYOUT_PAGE_OOB_SIZE * 2) |
52 | #define DOC_LAYOUT_BLOCK_SIZE \ | 52 | #define DOC_LAYOUT_BLOCK_SIZE \ |
53 | (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_PAGE_SIZE) | 53 | (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_PAGE_SIZE) |
54 | |||
55 | /* | ||
56 | * ECC related constants | ||
57 | */ | ||
58 | #define DOC_ECC_BCH_M 14 | ||
59 | #define DOC_ECC_BCH_T 4 | ||
60 | #define DOC_ECC_BCH_PRIMPOLY 0x4443 | ||
54 | #define DOC_ECC_BCH_SIZE 7 | 61 | #define DOC_ECC_BCH_SIZE 7 |
55 | #define DOC_ECC_BCH_COVERED_BYTES \ | 62 | #define DOC_ECC_BCH_COVERED_BYTES \ |
56 | (DOC_LAYOUT_PAGE_SIZE + DOC_LAYOUT_OOB_PAGEINFO_SZ + \ | 63 | (DOC_LAYOUT_PAGE_SIZE + DOC_LAYOUT_OOB_PAGEINFO_SZ + \ |
57 | DOC_LAYOUT_OOB_HAMMING_SZ + DOC_LAYOUT_OOB_BCH_SZ) | 64 | DOC_LAYOUT_OOB_HAMMING_SZ) |
65 | #define DOC_ECC_BCH_TOTAL_BYTES \ | ||
66 | (DOC_ECC_BCH_COVERED_BYTES + DOC_LAYOUT_OOB_BCH_SZ) | ||
58 | 67 | ||
59 | /* | 68 | /* |
60 | * Blocks distribution | 69 | * Blocks distribution |
@@ -80,6 +89,7 @@ | |||
80 | 89 | ||
81 | #define DOC_CHIPID_G3 0x200 | 90 | #define DOC_CHIPID_G3 0x200 |
82 | #define DOC_ERASE_MARK 0xaa | 91 | #define DOC_ERASE_MARK 0xaa |
92 | #define DOC_MAX_NBFLOORS 4 | ||
83 | /* | 93 | /* |
84 | * Flash registers | 94 | * Flash registers |
85 | */ | 95 | */ |
@@ -105,9 +115,11 @@ | |||
105 | #define DOC_ECCCONF1 0x1042 | 115 | #define DOC_ECCCONF1 0x1042 |
106 | #define DOC_ECCPRESET 0x1044 | 116 | #define DOC_ECCPRESET 0x1044 |
107 | #define DOC_HAMMINGPARITY 0x1046 | 117 | #define DOC_HAMMINGPARITY 0x1046 |
108 | #define DOC_BCH_SYNDROM(idx) (0x1048 + (idx << 1)) | 118 | #define DOC_BCH_HW_ECC(idx) (0x1048 + idx) |
109 | 119 | ||
110 | #define DOC_PROTECTION 0x1056 | 120 | #define DOC_PROTECTION 0x1056 |
121 | #define DOC_DPS0_KEY 0x105c | ||
122 | #define DOC_DPS1_KEY 0x105e | ||
111 | #define DOC_DPS0_ADDRLOW 0x1060 | 123 | #define DOC_DPS0_ADDRLOW 0x1060 |
112 | #define DOC_DPS0_ADDRHIGH 0x1062 | 124 | #define DOC_DPS0_ADDRHIGH 0x1062 |
113 | #define DOC_DPS1_ADDRLOW 0x1064 | 125 | #define DOC_DPS1_ADDRLOW 0x1064 |
@@ -117,6 +129,7 @@ | |||
117 | 129 | ||
118 | #define DOC_ASICMODECONFIRM 0x1072 | 130 | #define DOC_ASICMODECONFIRM 0x1072 |
119 | #define DOC_CHIPID_INV 0x1074 | 131 | #define DOC_CHIPID_INV 0x1074 |
132 | #define DOC_POWERMODE 0x107c | ||
120 | 133 | ||
121 | /* | 134 | /* |
122 | * Flash sequences | 135 | * Flash sequences |
@@ -124,11 +137,14 @@ | |||
124 | */ | 137 | */ |
125 | #define DOC_SEQ_RESET 0x00 | 138 | #define DOC_SEQ_RESET 0x00 |
126 | #define DOC_SEQ_PAGE_SIZE_532 0x03 | 139 | #define DOC_SEQ_PAGE_SIZE_532 0x03 |
127 | #define DOC_SEQ_SET_MODE 0x09 | 140 | #define DOC_SEQ_SET_FASTMODE 0x05 |
141 | #define DOC_SEQ_SET_RELIABLEMODE 0x09 | ||
128 | #define DOC_SEQ_READ 0x12 | 142 | #define DOC_SEQ_READ 0x12 |
129 | #define DOC_SEQ_SET_PLANE1 0x0e | 143 | #define DOC_SEQ_SET_PLANE1 0x0e |
130 | #define DOC_SEQ_SET_PLANE2 0x10 | 144 | #define DOC_SEQ_SET_PLANE2 0x10 |
131 | #define DOC_SEQ_PAGE_SETUP 0x1d | 145 | #define DOC_SEQ_PAGE_SETUP 0x1d |
146 | #define DOC_SEQ_ERASE 0x27 | ||
147 | #define DOC_SEQ_PLANES_STATUS 0x31 | ||
132 | 148 | ||
133 | /* | 149 | /* |
134 | * Flash commands | 150 | * Flash commands |
@@ -143,7 +159,10 @@ | |||
143 | #define DOC_CMD_PROG_BLOCK_ADDR 0x60 | 159 | #define DOC_CMD_PROG_BLOCK_ADDR 0x60 |
144 | #define DOC_CMD_PROG_CYCLE1 0x80 | 160 | #define DOC_CMD_PROG_CYCLE1 0x80 |
145 | #define DOC_CMD_PROG_CYCLE2 0x10 | 161 | #define DOC_CMD_PROG_CYCLE2 0x10 |
162 | #define DOC_CMD_PROG_CYCLE3 0x11 | ||
146 | #define DOC_CMD_ERASECYCLE2 0xd0 | 163 | #define DOC_CMD_ERASECYCLE2 0xd0 |
164 | #define DOC_CMD_READ_STATUS 0x70 | ||
165 | #define DOC_CMD_PLANES_STATUS 0x71 | ||
147 | 166 | ||
148 | #define DOC_CMD_RELIABLE_MODE 0x22 | 167 | #define DOC_CMD_RELIABLE_MODE 0x22 |
149 | #define DOC_CMD_FAST_MODE 0xa2 | 168 | #define DOC_CMD_FAST_MODE 0xa2 |
@@ -174,6 +193,7 @@ | |||
174 | /* | 193 | /* |
175 | * Flash register : DOC_ECCCONF0 | 194 | * Flash register : DOC_ECCCONF0 |
176 | */ | 195 | */ |
196 | #define DOC_ECCCONF0_WRITE_MODE 0x0000 | ||
177 | #define DOC_ECCCONF0_READ_MODE 0x8000 | 197 | #define DOC_ECCCONF0_READ_MODE 0x8000 |
178 | #define DOC_ECCCONF0_AUTO_ECC_ENABLE 0x4000 | 198 | #define DOC_ECCCONF0_AUTO_ECC_ENABLE 0x4000 |
179 | #define DOC_ECCCONF0_HAMMING_ENABLE 0x1000 | 199 | #define DOC_ECCCONF0_HAMMING_ENABLE 0x1000 |
@@ -185,7 +205,7 @@ | |||
185 | */ | 205 | */ |
186 | #define DOC_ECCCONF1_BCH_SYNDROM_ERR 0x80 | 206 | #define DOC_ECCCONF1_BCH_SYNDROM_ERR 0x80 |
187 | #define DOC_ECCCONF1_UNKOWN1 0x40 | 207 | #define DOC_ECCCONF1_UNKOWN1 0x40 |
188 | #define DOC_ECCCONF1_UNKOWN2 0x20 | 208 | #define DOC_ECCCONF1_PAGE_IS_WRITTEN 0x20 |
189 | #define DOC_ECCCONF1_UNKOWN3 0x10 | 209 | #define DOC_ECCCONF1_UNKOWN3 0x10 |
190 | #define DOC_ECCCONF1_HAMMING_BITS_MASK 0x0f | 210 | #define DOC_ECCCONF1_HAMMING_BITS_MASK 0x0f |
191 | 211 | ||
@@ -223,13 +243,46 @@ | |||
223 | #define DOC_READADDR_ONE_BYTE 0x4000 | 243 | #define DOC_READADDR_ONE_BYTE 0x4000 |
224 | #define DOC_READADDR_ADDR_MASK 0x1fff | 244 | #define DOC_READADDR_ADDR_MASK 0x1fff |
225 | 245 | ||
246 | /* | ||
247 | * Flash register : DOC_POWERMODE | ||
248 | */ | ||
249 | #define DOC_POWERDOWN_READY 0x80 | ||
250 | |||
251 | /* | ||
252 | * Status of erase and write operation | ||
253 | */ | ||
254 | #define DOC_PLANES_STATUS_FAIL 0x01 | ||
255 | #define DOC_PLANES_STATUS_PLANE0_KO 0x02 | ||
256 | #define DOC_PLANES_STATUS_PLANE1_KO 0x04 | ||
257 | |||
258 | /* | ||
259 | * DPS key management | ||
260 | * | ||
261 | * Each floor of docg3 has 2 protection areas: DPS0 and DPS1. These areas span | ||
262 | * across block boundaries, and define whether these blocks can be read or | ||
263 | * written. | ||
264 | * The definition is dynamically stored in page 0 of blocks (2,3) for DPS0, and | ||
265 | * page 0 of blocks (4,5) for DPS1. | ||
266 | */ | ||
267 | #define DOC_LAYOUT_DPS_KEY_LENGTH 8 | ||
268 | |||
226 | /** | 269 | /** |
227 | * struct docg3 - DiskOnChip driver private data | 270 | * struct docg3 - DiskOnChip driver private data |
228 | * @dev: the device currently under control | 271 | * @dev: the device currently under control |
229 | * @base: mapped IO space | 272 | * @base: mapped IO space |
230 | * @device_id: number of the cascaded DoCG3 device (0, 1, 2 or 3) | 273 | * @device_id: number of the cascaded DoCG3 device (0, 1, 2 or 3) |
231 | * @if_cfg: if true, reads are on 16bits, else reads are on 8bits | 274 | * @if_cfg: if true, reads are on 16bits, else reads are on 8bits |
275 | |||
276 | * @reliable: if 0, docg3 in normal mode, if 1 docg3 in fast mode, if 2 in | ||
277 | * reliable mode | ||
278 | * Fast mode implies more errors than normal mode. | ||
279 | * Reliable mode implies that page 2*n and 2*n+1 are clones. | ||
232 | * @bbt: bad block table cache | 280 | * @bbt: bad block table cache |
281 | * @oob_write_ofs: offset of the MTD where this OOB should belong (ie. in next | ||
282 | * page_write) | ||
283 | * @oob_autoecc: if 1, use only bytes 0-7, 15, and fill the others with HW ECC | ||
284 | * if 0, use all the 16 bytes. | ||
285 | * @oob_write_buf: prepared OOB for next page_write | ||
233 | * @debugfs_root: debugfs root node | 286 | * @debugfs_root: debugfs root node |
234 | */ | 287 | */ |
235 | struct docg3 { | 288 | struct docg3 { |
@@ -237,8 +290,12 @@ struct docg3 { | |||
237 | void __iomem *base; | 290 | void __iomem *base; |
238 | unsigned int device_id:4; | 291 | unsigned int device_id:4; |
239 | unsigned int if_cfg:1; | 292 | unsigned int if_cfg:1; |
293 | unsigned int reliable:2; | ||
240 | int max_block; | 294 | int max_block; |
241 | u8 *bbt; | 295 | u8 *bbt; |
296 | loff_t oob_write_ofs; | ||
297 | int oob_autoecc; | ||
298 | u8 oob_write_buf[DOC_LAYOUT_OOB_SIZE]; | ||
242 | struct dentry *debugfs_root; | 299 | struct dentry *debugfs_root; |
243 | }; | 300 | }; |
244 | 301 | ||
diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c index 45116bb30297..706b847b46b3 100644 --- a/drivers/mtd/devices/docprobe.c +++ b/drivers/mtd/devices/docprobe.c | |||
@@ -241,8 +241,7 @@ static void __init DoC_Probe(unsigned long physadr) | |||
241 | return; | 241 | return; |
242 | } | 242 | } |
243 | docfound = 1; | 243 | docfound = 1; |
244 | mtd = kmalloc(sizeof(struct DiskOnChip) + sizeof(struct mtd_info), GFP_KERNEL); | 244 | mtd = kzalloc(sizeof(struct DiskOnChip) + sizeof(struct mtd_info), GFP_KERNEL); |
245 | |||
246 | if (!mtd) { | 245 | if (!mtd) { |
247 | printk(KERN_WARNING "Cannot allocate memory for data structures. Dropping.\n"); | 246 | printk(KERN_WARNING "Cannot allocate memory for data structures. Dropping.\n"); |
248 | iounmap(docptr); | 247 | iounmap(docptr); |
@@ -250,10 +249,6 @@ static void __init DoC_Probe(unsigned long physadr) | |||
250 | } | 249 | } |
251 | 250 | ||
252 | this = (struct DiskOnChip *)(&mtd[1]); | 251 | this = (struct DiskOnChip *)(&mtd[1]); |
253 | |||
254 | memset((char *)mtd,0, sizeof(struct mtd_info)); | ||
255 | memset((char *)this, 0, sizeof(struct DiskOnChip)); | ||
256 | |||
257 | mtd->priv = this; | 252 | mtd->priv = this; |
258 | this->virtadr = docptr; | 253 | this->virtadr = docptr; |
259 | this->physadr = physadr; | 254 | this->physadr = physadr; |
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 884904d3f9d2..7c60dddbefc0 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -992,7 +992,6 @@ static int __devexit m25p_remove(struct spi_device *spi) | |||
992 | static struct spi_driver m25p80_driver = { | 992 | static struct spi_driver m25p80_driver = { |
993 | .driver = { | 993 | .driver = { |
994 | .name = "m25p80", | 994 | .name = "m25p80", |
995 | .bus = &spi_bus_type, | ||
996 | .owner = THIS_MODULE, | 995 | .owner = THIS_MODULE, |
997 | }, | 996 | }, |
998 | .id_table = m25p_ids, | 997 | .id_table = m25p_ids, |
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index d75c7af18a63..236057ead0d2 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c | |||
@@ -936,7 +936,6 @@ static int __devexit dataflash_remove(struct spi_device *spi) | |||
936 | static struct spi_driver dataflash_driver = { | 936 | static struct spi_driver dataflash_driver = { |
937 | .driver = { | 937 | .driver = { |
938 | .name = "mtd_dataflash", | 938 | .name = "mtd_dataflash", |
939 | .bus = &spi_bus_type, | ||
940 | .owner = THIS_MODULE, | 939 | .owner = THIS_MODULE, |
941 | .of_match_table = dataflash_dt_ids, | 940 | .of_match_table = dataflash_dt_ids, |
942 | }, | 941 | }, |
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c index d38ef3bffe8d..5fc198350b94 100644 --- a/drivers/mtd/devices/sst25l.c +++ b/drivers/mtd/devices/sst25l.c | |||
@@ -378,7 +378,7 @@ static int __devinit sst25l_probe(struct spi_device *spi) | |||
378 | struct flash_info *flash_info; | 378 | struct flash_info *flash_info; |
379 | struct sst25l_flash *flash; | 379 | struct sst25l_flash *flash; |
380 | struct flash_platform_data *data; | 380 | struct flash_platform_data *data; |
381 | int ret, i; | 381 | int ret; |
382 | 382 | ||
383 | flash_info = sst25l_match_device(spi); | 383 | flash_info = sst25l_match_device(spi); |
384 | if (!flash_info) | 384 | if (!flash_info) |
@@ -444,7 +444,6 @@ static int __devexit sst25l_remove(struct spi_device *spi) | |||
444 | static struct spi_driver sst25l_driver = { | 444 | static struct spi_driver sst25l_driver = { |
445 | .driver = { | 445 | .driver = { |
446 | .name = "sst25l", | 446 | .name = "sst25l", |
447 | .bus = &spi_bus_type, | ||
448 | .owner = THIS_MODULE, | 447 | .owner = THIS_MODULE, |
449 | }, | 448 | }, |
450 | .probe = sst25l_probe, | 449 | .probe = sst25l_probe, |