diff options
Diffstat (limited to 'drivers/mtd/devices')
-rw-r--r-- | drivers/mtd/devices/Kconfig | 13 | ||||
-rw-r--r-- | drivers/mtd/devices/Makefile | 3 | ||||
-rw-r--r-- | drivers/mtd/devices/doc2000.c | 17 | ||||
-rw-r--r-- | drivers/mtd/devices/doc2001.c | 11 | ||||
-rw-r--r-- | drivers/mtd/devices/doc2001plus.c | 11 | ||||
-rw-r--r-- | drivers/mtd/devices/docecc.c | 2 | ||||
-rw-r--r-- | drivers/mtd/devices/docg3.c | 1114 | ||||
-rw-r--r-- | drivers/mtd/devices/docg3.h | 297 | ||||
-rw-r--r-- | drivers/mtd/devices/docprobe.c | 5 | ||||
-rw-r--r-- | drivers/mtd/devices/lart.c | 18 | ||||
-rw-r--r-- | drivers/mtd/devices/m25p80.c | 92 | ||||
-rw-r--r-- | drivers/mtd/devices/mtd_dataflash.c | 91 | ||||
-rw-r--r-- | drivers/mtd/devices/sst25l.c | 42 |
13 files changed, 1521 insertions, 195 deletions
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 35081ce77fbd..283d887f7825 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig | |||
@@ -249,6 +249,16 @@ config MTD_DOC2001PLUS | |||
249 | under "NAND Flash Device Drivers" (currently that driver does not | 249 | under "NAND Flash Device Drivers" (currently that driver does not |
250 | support all Millennium Plus devices). | 250 | support all Millennium Plus devices). |
251 | 251 | ||
252 | config MTD_DOCG3 | ||
253 | tristate "M-Systems Disk-On-Chip G3" | ||
254 | ---help--- | ||
255 | This provides an MTD device driver for the M-Systems DiskOnChip | ||
256 | G3 devices. | ||
257 | |||
258 | The driver provides access to G3 DiskOnChip, distributed by | ||
259 | M-Systems and now Sandisk. The support is very experimental, | ||
260 | and doesn't give access to any write operations. | ||
261 | |||
252 | config MTD_DOCPROBE | 262 | config MTD_DOCPROBE |
253 | tristate | 263 | tristate |
254 | select MTD_DOCECC | 264 | select MTD_DOCECC |
@@ -268,8 +278,7 @@ config MTD_DOCPROBE_ADVANCED | |||
268 | config MTD_DOCPROBE_ADDRESS | 278 | config MTD_DOCPROBE_ADDRESS |
269 | hex "Physical address of DiskOnChip" if MTD_DOCPROBE_ADVANCED | 279 | hex "Physical address of DiskOnChip" if MTD_DOCPROBE_ADVANCED |
270 | depends on MTD_DOCPROBE | 280 | depends on MTD_DOCPROBE |
271 | default "0x0000" if MTD_DOCPROBE_ADVANCED | 281 | default "0x0" |
272 | default "0" if !MTD_DOCPROBE_ADVANCED | ||
273 | ---help--- | 282 | ---help--- |
274 | By default, the probe for DiskOnChip devices will look for a | 283 | By default, the probe for DiskOnChip devices will look for a |
275 | DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000. | 284 | DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000. |
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index f3226b1d38fc..56c7cd462f11 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile | |||
@@ -5,6 +5,7 @@ | |||
5 | obj-$(CONFIG_MTD_DOC2000) += doc2000.o | 5 | obj-$(CONFIG_MTD_DOC2000) += doc2000.o |
6 | obj-$(CONFIG_MTD_DOC2001) += doc2001.o | 6 | obj-$(CONFIG_MTD_DOC2001) += doc2001.o |
7 | obj-$(CONFIG_MTD_DOC2001PLUS) += doc2001plus.o | 7 | obj-$(CONFIG_MTD_DOC2001PLUS) += doc2001plus.o |
8 | obj-$(CONFIG_MTD_DOCG3) += docg3.o | ||
8 | obj-$(CONFIG_MTD_DOCPROBE) += docprobe.o | 9 | obj-$(CONFIG_MTD_DOCPROBE) += docprobe.o |
9 | obj-$(CONFIG_MTD_DOCECC) += docecc.o | 10 | obj-$(CONFIG_MTD_DOCECC) += docecc.o |
10 | obj-$(CONFIG_MTD_SLRAM) += slram.o | 11 | obj-$(CONFIG_MTD_SLRAM) += slram.o |
@@ -17,3 +18,5 @@ obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o | |||
17 | obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o | 18 | obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o |
18 | obj-$(CONFIG_MTD_M25P80) += m25p80.o | 19 | obj-$(CONFIG_MTD_M25P80) += m25p80.o |
19 | obj-$(CONFIG_MTD_SST25L) += sst25l.o | 20 | obj-$(CONFIG_MTD_SST25L) += sst25l.o |
21 | |||
22 | CFLAGS_docg3.o += -I$(src) \ No newline at end of file | ||
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index f7fbf6025ef2..e9fad9151219 100644 --- a/drivers/mtd/devices/doc2000.c +++ b/drivers/mtd/devices/doc2000.c | |||
@@ -82,8 +82,7 @@ static int _DoC_WaitReady(struct DiskOnChip *doc) | |||
82 | void __iomem *docptr = doc->virtadr; | 82 | void __iomem *docptr = doc->virtadr; |
83 | unsigned long timeo = jiffies + (HZ * 10); | 83 | unsigned long timeo = jiffies + (HZ * 10); |
84 | 84 | ||
85 | DEBUG(MTD_DEBUG_LEVEL3, | 85 | pr_debug("_DoC_WaitReady called for out-of-line wait\n"); |
86 | "_DoC_WaitReady called for out-of-line wait\n"); | ||
87 | 86 | ||
88 | /* Out-of-line routine to wait for chip response */ | 87 | /* Out-of-line routine to wait for chip response */ |
89 | while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) { | 88 | while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) { |
@@ -92,7 +91,7 @@ static int _DoC_WaitReady(struct DiskOnChip *doc) | |||
92 | DoC_Delay(doc, 2); | 91 | DoC_Delay(doc, 2); |
93 | 92 | ||
94 | if (time_after(jiffies, timeo)) { | 93 | if (time_after(jiffies, timeo)) { |
95 | DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n"); | 94 | pr_debug("_DoC_WaitReady timed out.\n"); |
96 | return -EIO; | 95 | return -EIO; |
97 | } | 96 | } |
98 | udelay(1); | 97 | udelay(1); |
@@ -323,8 +322,7 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) | |||
323 | 322 | ||
324 | /* Reset the chip */ | 323 | /* Reset the chip */ |
325 | if (DoC_Command(doc, NAND_CMD_RESET, CDSN_CTRL_WP)) { | 324 | if (DoC_Command(doc, NAND_CMD_RESET, CDSN_CTRL_WP)) { |
326 | DEBUG(MTD_DEBUG_LEVEL2, | 325 | pr_debug("DoC_Command (reset) for %d,%d returned true\n", |
327 | "DoC_Command (reset) for %d,%d returned true\n", | ||
328 | floor, chip); | 326 | floor, chip); |
329 | return 0; | 327 | return 0; |
330 | } | 328 | } |
@@ -332,8 +330,7 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) | |||
332 | 330 | ||
333 | /* Read the NAND chip ID: 1. Send ReadID command */ | 331 | /* Read the NAND chip ID: 1. Send ReadID command */ |
334 | if (DoC_Command(doc, NAND_CMD_READID, CDSN_CTRL_WP)) { | 332 | if (DoC_Command(doc, NAND_CMD_READID, CDSN_CTRL_WP)) { |
335 | DEBUG(MTD_DEBUG_LEVEL2, | 333 | pr_debug("DoC_Command (ReadID) for %d,%d returned true\n", |
336 | "DoC_Command (ReadID) for %d,%d returned true\n", | ||
337 | floor, chip); | 334 | floor, chip); |
338 | return 0; | 335 | return 0; |
339 | } | 336 | } |
@@ -699,7 +696,7 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
699 | #ifdef ECC_DEBUG | 696 | #ifdef ECC_DEBUG |
700 | printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from); | 697 | printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from); |
701 | #endif | 698 | #endif |
702 | /* Read the ECC syndrom through the DiskOnChip ECC | 699 | /* Read the ECC syndrome through the DiskOnChip ECC |
703 | logic. These syndrome will be all ZERO when there | 700 | logic. These syndrome will be all ZERO when there |
704 | is no error */ | 701 | is no error */ |
705 | for (i = 0; i < 6; i++) { | 702 | for (i = 0; i < 6; i++) { |
@@ -930,7 +927,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, | |||
930 | uint8_t *buf = ops->oobbuf; | 927 | uint8_t *buf = ops->oobbuf; |
931 | size_t len = ops->len; | 928 | size_t len = ops->len; |
932 | 929 | ||
933 | BUG_ON(ops->mode != MTD_OOB_PLACE); | 930 | BUG_ON(ops->mode != MTD_OPS_PLACE_OOB); |
934 | 931 | ||
935 | ofs += ops->ooboffs; | 932 | ofs += ops->ooboffs; |
936 | 933 | ||
@@ -1094,7 +1091,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, | |||
1094 | struct DiskOnChip *this = mtd->priv; | 1091 | struct DiskOnChip *this = mtd->priv; |
1095 | int ret; | 1092 | int ret; |
1096 | 1093 | ||
1097 | BUG_ON(ops->mode != MTD_OOB_PLACE); | 1094 | BUG_ON(ops->mode != MTD_OPS_PLACE_OOB); |
1098 | 1095 | ||
1099 | mutex_lock(&this->lock); | 1096 | mutex_lock(&this->lock); |
1100 | ret = doc_write_oob_nolock(mtd, ofs + ops->ooboffs, ops->len, | 1097 | ret = doc_write_oob_nolock(mtd, ofs + ops->ooboffs, ops->len, |
diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c index 241192f05bc8..a3f7a27499be 100644 --- a/drivers/mtd/devices/doc2001.c +++ b/drivers/mtd/devices/doc2001.c | |||
@@ -55,15 +55,14 @@ static int _DoC_WaitReady(void __iomem * docptr) | |||
55 | { | 55 | { |
56 | unsigned short c = 0xffff; | 56 | unsigned short c = 0xffff; |
57 | 57 | ||
58 | DEBUG(MTD_DEBUG_LEVEL3, | 58 | pr_debug("_DoC_WaitReady called for out-of-line wait\n"); |
59 | "_DoC_WaitReady called for out-of-line wait\n"); | ||
60 | 59 | ||
61 | /* Out-of-line routine to wait for chip response */ | 60 | /* Out-of-line routine to wait for chip response */ |
62 | while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c) | 61 | while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c) |
63 | ; | 62 | ; |
64 | 63 | ||
65 | if (c == 0) | 64 | if (c == 0) |
66 | DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n"); | 65 | pr_debug("_DoC_WaitReady timed out.\n"); |
67 | 66 | ||
68 | return (c == 0); | 67 | return (c == 0); |
69 | } | 68 | } |
@@ -464,7 +463,7 @@ static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, | |||
464 | #ifdef ECC_DEBUG | 463 | #ifdef ECC_DEBUG |
465 | printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); | 464 | printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); |
466 | #endif | 465 | #endif |
467 | /* Read the ECC syndrom through the DiskOnChip ECC logic. | 466 | /* Read the ECC syndrome through the DiskOnChip ECC logic. |
468 | These syndrome will be all ZERO when there is no error */ | 467 | These syndrome will be all ZERO when there is no error */ |
469 | for (i = 0; i < 6; i++) { | 468 | for (i = 0; i < 6; i++) { |
470 | syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i); | 469 | syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i); |
@@ -632,7 +631,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, | |||
632 | uint8_t *buf = ops->oobbuf; | 631 | uint8_t *buf = ops->oobbuf; |
633 | size_t len = ops->len; | 632 | size_t len = ops->len; |
634 | 633 | ||
635 | BUG_ON(ops->mode != MTD_OOB_PLACE); | 634 | BUG_ON(ops->mode != MTD_OPS_PLACE_OOB); |
636 | 635 | ||
637 | ofs += ops->ooboffs; | 636 | ofs += ops->ooboffs; |
638 | 637 | ||
@@ -690,7 +689,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, | |||
690 | uint8_t *buf = ops->oobbuf; | 689 | uint8_t *buf = ops->oobbuf; |
691 | size_t len = ops->len; | 690 | size_t len = ops->len; |
692 | 691 | ||
693 | BUG_ON(ops->mode != MTD_OOB_PLACE); | 692 | BUG_ON(ops->mode != MTD_OPS_PLACE_OOB); |
694 | 693 | ||
695 | ofs += ops->ooboffs; | 694 | ofs += ops->ooboffs; |
696 | 695 | ||
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c index 09ae0adc3ad0..99351bc3e0ed 100644 --- a/drivers/mtd/devices/doc2001plus.c +++ b/drivers/mtd/devices/doc2001plus.c | |||
@@ -61,15 +61,14 @@ static int _DoC_WaitReady(void __iomem * docptr) | |||
61 | { | 61 | { |
62 | unsigned int c = 0xffff; | 62 | unsigned int c = 0xffff; |
63 | 63 | ||
64 | DEBUG(MTD_DEBUG_LEVEL3, | 64 | pr_debug("_DoC_WaitReady called for out-of-line wait\n"); |
65 | "_DoC_WaitReady called for out-of-line wait\n"); | ||
66 | 65 | ||
67 | /* Out-of-line routine to wait for chip response */ | 66 | /* Out-of-line routine to wait for chip response */ |
68 | while (((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) && --c) | 67 | while (((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) && --c) |
69 | ; | 68 | ; |
70 | 69 | ||
71 | if (c == 0) | 70 | if (c == 0) |
72 | DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n"); | 71 | pr_debug("_DoC_WaitReady timed out.\n"); |
73 | 72 | ||
74 | return (c == 0); | 73 | return (c == 0); |
75 | } | 74 | } |
@@ -655,7 +654,7 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
655 | #ifdef ECC_DEBUG | 654 | #ifdef ECC_DEBUG |
656 | printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); | 655 | printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); |
657 | #endif | 656 | #endif |
658 | /* Read the ECC syndrom through the DiskOnChip ECC logic. | 657 | /* Read the ECC syndrome through the DiskOnChip ECC logic. |
659 | These syndrome will be all ZERO when there is no error */ | 658 | These syndrome will be all ZERO when there is no error */ |
660 | for (i = 0; i < 6; i++) | 659 | for (i = 0; i < 6; i++) |
661 | syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i); | 660 | syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i); |
@@ -835,7 +834,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, | |||
835 | uint8_t *buf = ops->oobbuf; | 834 | uint8_t *buf = ops->oobbuf; |
836 | size_t len = ops->len; | 835 | size_t len = ops->len; |
837 | 836 | ||
838 | BUG_ON(ops->mode != MTD_OOB_PLACE); | 837 | BUG_ON(ops->mode != MTD_OPS_PLACE_OOB); |
839 | 838 | ||
840 | ofs += ops->ooboffs; | 839 | ofs += ops->ooboffs; |
841 | 840 | ||
@@ -920,7 +919,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, | |||
920 | uint8_t *buf = ops->oobbuf; | 919 | uint8_t *buf = ops->oobbuf; |
921 | size_t len = ops->len; | 920 | size_t len = ops->len; |
922 | 921 | ||
923 | BUG_ON(ops->mode != MTD_OOB_PLACE); | 922 | BUG_ON(ops->mode != MTD_OPS_PLACE_OOB); |
924 | 923 | ||
925 | ofs += ops->ooboffs; | 924 | ofs += ops->ooboffs; |
926 | 925 | ||
diff --git a/drivers/mtd/devices/docecc.c b/drivers/mtd/devices/docecc.c index 37ef29a73ee4..4a1c39b6f37d 100644 --- a/drivers/mtd/devices/docecc.c +++ b/drivers/mtd/devices/docecc.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * ECC algorithm for M-systems disk on chip. We use the excellent Reed | 2 | * ECC algorithm for M-systems disk on chip. We use the excellent Reed |
3 | * Solmon code of Phil Karn (karn@ka9q.ampr.org) available under the | 3 | * Solmon code of Phil Karn (karn@ka9q.ampr.org) available under the |
4 | * GNU GPL License. The rest is simply to convert the disk on chip | 4 | * GNU GPL License. The rest is simply to convert the disk on chip |
5 | * syndrom into a standard syndom. | 5 | * syndrome into a standard syndome. |
6 | * | 6 | * |
7 | * Author: Fabrice Bellard (fabrice.bellard@netgem.com) | 7 | * Author: Fabrice Bellard (fabrice.bellard@netgem.com) |
8 | * Copyright (C) 2000 Netgem S.A. | 8 | * Copyright (C) 2000 Netgem S.A. |
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c new file mode 100644 index 000000000000..bdcf5df982e8 --- /dev/null +++ b/drivers/mtd/devices/docg3.c | |||
@@ -0,0 +1,1114 @@ | |||
1 | /* | ||
2 | * Handles the M-Systems DiskOnChip G3 chip | ||
3 | * | ||
4 | * Copyright (C) 2011 Robert Jarzmik | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/string.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/io.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/mtd/mtd.h> | ||
31 | #include <linux/mtd/partitions.h> | ||
32 | |||
33 | #include <linux/debugfs.h> | ||
34 | #include <linux/seq_file.h> | ||
35 | |||
36 | #define CREATE_TRACE_POINTS | ||
37 | #include "docg3.h" | ||
38 | |||
39 | /* | ||
40 | * This driver handles the DiskOnChip G3 flash memory. | ||
41 | * | ||
42 | * As no specification is available from M-Systems/Sandisk, this drivers lacks | ||
43 | * several functions available on the chip, as : | ||
44 | * - block erase | ||
45 | * - page write | ||
46 | * - IPL write | ||
47 | * - ECC fixing (lack of BCH algorith understanding) | ||
48 | * - powerdown / powerup | ||
49 | * | ||
50 | * The bus data width (8bits versus 16bits) is not handled (if_cfg flag), and | ||
51 | * the driver assumes a 16bits data bus. | ||
52 | * | ||
53 | * DocG3 relies on 2 ECC algorithms, which are handled in hardware : | ||
54 | * - 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 | ||
56 | * The BCH part is only used for check purpose, no correction is available as | ||
57 | * some information is missing. What is known is that : | ||
58 | * - BCH is in GF(2^14) | ||
59 | * - BCH is over data of 520 bytes (512 page + 7 page_info bytes | ||
60 | * + 1 hamming byte) | ||
61 | * - BCH can correct up to 4 bits (t = 4) | ||
62 | * - BCH syndroms are calculated in hardware, and checked in hardware as well | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | static inline u8 doc_readb(struct docg3 *docg3, u16 reg) | ||
67 | { | ||
68 | u8 val = readb(docg3->base + reg); | ||
69 | |||
70 | trace_docg3_io(0, 8, reg, (int)val); | ||
71 | return val; | ||
72 | } | ||
73 | |||
74 | static inline u16 doc_readw(struct docg3 *docg3, u16 reg) | ||
75 | { | ||
76 | u16 val = readw(docg3->base + reg); | ||
77 | |||
78 | trace_docg3_io(0, 16, reg, (int)val); | ||
79 | return val; | ||
80 | } | ||
81 | |||
82 | static inline void doc_writeb(struct docg3 *docg3, u8 val, u16 reg) | ||
83 | { | ||
84 | writeb(val, docg3->base + reg); | ||
85 | trace_docg3_io(1, 16, reg, val); | ||
86 | } | ||
87 | |||
88 | static inline void doc_writew(struct docg3 *docg3, u16 val, u16 reg) | ||
89 | { | ||
90 | writew(val, docg3->base + reg); | ||
91 | trace_docg3_io(1, 16, reg, val); | ||
92 | } | ||
93 | |||
94 | static inline void doc_flash_command(struct docg3 *docg3, u8 cmd) | ||
95 | { | ||
96 | doc_writeb(docg3, cmd, DOC_FLASHCOMMAND); | ||
97 | } | ||
98 | |||
99 | static inline void doc_flash_sequence(struct docg3 *docg3, u8 seq) | ||
100 | { | ||
101 | doc_writeb(docg3, seq, DOC_FLASHSEQUENCE); | ||
102 | } | ||
103 | |||
104 | static inline void doc_flash_address(struct docg3 *docg3, u8 addr) | ||
105 | { | ||
106 | doc_writeb(docg3, addr, DOC_FLASHADDRESS); | ||
107 | } | ||
108 | |||
109 | static char const *part_probes[] = { "cmdlinepart", "saftlpart", NULL }; | ||
110 | |||
111 | static int doc_register_readb(struct docg3 *docg3, int reg) | ||
112 | { | ||
113 | u8 val; | ||
114 | |||
115 | doc_writew(docg3, reg, DOC_READADDRESS); | ||
116 | val = doc_readb(docg3, reg); | ||
117 | doc_vdbg("Read register %04x : %02x\n", reg, val); | ||
118 | return val; | ||
119 | } | ||
120 | |||
121 | static int doc_register_readw(struct docg3 *docg3, int reg) | ||
122 | { | ||
123 | u16 val; | ||
124 | |||
125 | doc_writew(docg3, reg, DOC_READADDRESS); | ||
126 | val = doc_readw(docg3, reg); | ||
127 | doc_vdbg("Read register %04x : %04x\n", reg, val); | ||
128 | return val; | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * doc_delay - delay docg3 operations | ||
133 | * @docg3: the device | ||
134 | * @nbNOPs: the number of NOPs to issue | ||
135 | * | ||
136 | * As no specification is available, the right timings between chip commands are | ||
137 | * unknown. The only available piece of information are the observed nops on a | ||
138 | * working docg3 chip. | ||
139 | * Therefore, doc_delay relies on a busy loop of NOPs, instead of scheduler | ||
140 | * friendlier msleep() functions or blocking mdelay(). | ||
141 | */ | ||
142 | static void doc_delay(struct docg3 *docg3, int nbNOPs) | ||
143 | { | ||
144 | int i; | ||
145 | |||
146 | doc_dbg("NOP x %d\n", nbNOPs); | ||
147 | for (i = 0; i < nbNOPs; i++) | ||
148 | doc_writeb(docg3, 0, DOC_NOP); | ||
149 | } | ||
150 | |||
151 | static int is_prot_seq_error(struct docg3 *docg3) | ||
152 | { | ||
153 | int ctrl; | ||
154 | |||
155 | ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
156 | return ctrl & (DOC_CTRL_PROTECTION_ERROR | DOC_CTRL_SEQUENCE_ERROR); | ||
157 | } | ||
158 | |||
159 | static int doc_is_ready(struct docg3 *docg3) | ||
160 | { | ||
161 | int ctrl; | ||
162 | |||
163 | ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
164 | return ctrl & DOC_CTRL_FLASHREADY; | ||
165 | } | ||
166 | |||
167 | static int doc_wait_ready(struct docg3 *docg3) | ||
168 | { | ||
169 | int maxWaitCycles = 100; | ||
170 | |||
171 | do { | ||
172 | doc_delay(docg3, 4); | ||
173 | cpu_relax(); | ||
174 | } while (!doc_is_ready(docg3) && maxWaitCycles--); | ||
175 | doc_delay(docg3, 2); | ||
176 | if (maxWaitCycles > 0) | ||
177 | return 0; | ||
178 | else | ||
179 | return -EIO; | ||
180 | } | ||
181 | |||
182 | static int doc_reset_seq(struct docg3 *docg3) | ||
183 | { | ||
184 | int ret; | ||
185 | |||
186 | doc_writeb(docg3, 0x10, DOC_FLASHCONTROL); | ||
187 | doc_flash_sequence(docg3, DOC_SEQ_RESET); | ||
188 | doc_flash_command(docg3, DOC_CMD_RESET); | ||
189 | doc_delay(docg3, 2); | ||
190 | ret = doc_wait_ready(docg3); | ||
191 | |||
192 | doc_dbg("doc_reset_seq() -> isReady=%s\n", ret ? "false" : "true"); | ||
193 | return ret; | ||
194 | } | ||
195 | |||
196 | /** | ||
197 | * doc_read_data_area - Read data from data area | ||
198 | * @docg3: the device | ||
199 | * @buf: the buffer to fill in | ||
200 | * @len: the lenght to read | ||
201 | * @first: first time read, DOC_READADDRESS should be set | ||
202 | * | ||
203 | * Reads bytes from flash data. Handles the single byte / even bytes reads. | ||
204 | */ | ||
205 | static void doc_read_data_area(struct docg3 *docg3, void *buf, int len, | ||
206 | int first) | ||
207 | { | ||
208 | int i, cdr, len4; | ||
209 | u16 data16, *dst16; | ||
210 | u8 data8, *dst8; | ||
211 | |||
212 | doc_dbg("doc_read_data_area(buf=%p, len=%d)\n", buf, len); | ||
213 | cdr = len & 0x3; | ||
214 | len4 = len - cdr; | ||
215 | |||
216 | if (first) | ||
217 | doc_writew(docg3, DOC_IOSPACE_DATA, DOC_READADDRESS); | ||
218 | dst16 = buf; | ||
219 | for (i = 0; i < len4; i += 2) { | ||
220 | data16 = doc_readw(docg3, DOC_IOSPACE_DATA); | ||
221 | *dst16 = data16; | ||
222 | dst16++; | ||
223 | } | ||
224 | |||
225 | if (cdr) { | ||
226 | doc_writew(docg3, DOC_IOSPACE_DATA | DOC_READADDR_ONE_BYTE, | ||
227 | DOC_READADDRESS); | ||
228 | doc_delay(docg3, 1); | ||
229 | dst8 = (u8 *)dst16; | ||
230 | for (i = 0; i < cdr; i++) { | ||
231 | data8 = doc_readb(docg3, DOC_IOSPACE_DATA); | ||
232 | *dst8 = data8; | ||
233 | dst8++; | ||
234 | } | ||
235 | } | ||
236 | } | ||
237 | |||
238 | /** | ||
239 | * doc_set_data_mode - Sets the flash to reliable data mode | ||
240 | * @docg3: the device | ||
241 | * | ||
242 | * 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 | ||
244 | * mode first. | ||
245 | */ | ||
246 | static void doc_set_reliable_mode(struct docg3 *docg3) | ||
247 | { | ||
248 | doc_dbg("doc_set_reliable_mode()\n"); | ||
249 | doc_flash_sequence(docg3, DOC_SEQ_SET_MODE); | ||
250 | doc_flash_command(docg3, DOC_CMD_FAST_MODE); | ||
251 | doc_flash_command(docg3, DOC_CMD_RELIABLE_MODE); | ||
252 | doc_delay(docg3, 2); | ||
253 | } | ||
254 | |||
255 | /** | ||
256 | * doc_set_asic_mode - Set the ASIC mode | ||
257 | * @docg3: the device | ||
258 | * @mode: the mode | ||
259 | * | ||
260 | * The ASIC can work in 3 modes : | ||
261 | * - RESET: all registers are zeroed | ||
262 | * - NORMAL: receives and handles commands | ||
263 | * - POWERDOWN: minimal poweruse, flash parts shut off | ||
264 | */ | ||
265 | static void doc_set_asic_mode(struct docg3 *docg3, u8 mode) | ||
266 | { | ||
267 | int i; | ||
268 | |||
269 | for (i = 0; i < 12; i++) | ||
270 | doc_readb(docg3, DOC_IOSPACE_IPL); | ||
271 | |||
272 | mode |= DOC_ASICMODE_MDWREN; | ||
273 | doc_dbg("doc_set_asic_mode(%02x)\n", mode); | ||
274 | doc_writeb(docg3, mode, DOC_ASICMODE); | ||
275 | doc_writeb(docg3, ~mode, DOC_ASICMODECONFIRM); | ||
276 | doc_delay(docg3, 1); | ||
277 | } | ||
278 | |||
279 | /** | ||
280 | * doc_set_device_id - Sets the devices id for cascaded G3 chips | ||
281 | * @docg3: the device | ||
282 | * @id: the chip to select (amongst 0, 1, 2, 3) | ||
283 | * | ||
284 | * There can be 4 cascaded G3 chips. This function selects the one which will | ||
285 | * should be the active one. | ||
286 | */ | ||
287 | static void doc_set_device_id(struct docg3 *docg3, int id) | ||
288 | { | ||
289 | u8 ctrl; | ||
290 | |||
291 | doc_dbg("doc_set_device_id(%d)\n", id); | ||
292 | doc_writeb(docg3, id, DOC_DEVICESELECT); | ||
293 | ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
294 | |||
295 | ctrl &= ~DOC_CTRL_VIOLATION; | ||
296 | ctrl |= DOC_CTRL_CE; | ||
297 | doc_writeb(docg3, ctrl, DOC_FLASHCONTROL); | ||
298 | } | ||
299 | |||
300 | /** | ||
301 | * doc_set_extra_page_mode - Change flash page layout | ||
302 | * @docg3: the device | ||
303 | * | ||
304 | * Normally, the flash page is split into the data (512 bytes) and the out of | ||
305 | * band data (16 bytes). For each, 4 more bytes can be accessed, where the wear | ||
306 | * leveling counters are stored. To access this last area of 4 bytes, a special | ||
307 | * mode must be input to the flash ASIC. | ||
308 | * | ||
309 | * Returns 0 if no error occured, -EIO else. | ||
310 | */ | ||
311 | static int doc_set_extra_page_mode(struct docg3 *docg3) | ||
312 | { | ||
313 | int fctrl; | ||
314 | |||
315 | doc_dbg("doc_set_extra_page_mode()\n"); | ||
316 | doc_flash_sequence(docg3, DOC_SEQ_PAGE_SIZE_532); | ||
317 | doc_flash_command(docg3, DOC_CMD_PAGE_SIZE_532); | ||
318 | doc_delay(docg3, 2); | ||
319 | |||
320 | fctrl = doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
321 | if (fctrl & (DOC_CTRL_PROTECTION_ERROR | DOC_CTRL_SEQUENCE_ERROR)) | ||
322 | return -EIO; | ||
323 | else | ||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | /** | ||
328 | * doc_seek - Set both flash planes to the specified block, page for reading | ||
329 | * @docg3: the device | ||
330 | * @block0: the first plane block index | ||
331 | * @block1: the second plane block index | ||
332 | * @page: the page index within the block | ||
333 | * @wear: if true, read will occur on the 4 extra bytes of the wear area | ||
334 | * @ofs: offset in page to read | ||
335 | * | ||
336 | * Programs the flash even and odd planes to the specific block and page. | ||
337 | * Alternatively, programs the flash to the wear area of the specified page. | ||
338 | */ | ||
339 | static int doc_read_seek(struct docg3 *docg3, int block0, int block1, int page, | ||
340 | int wear, int ofs) | ||
341 | { | ||
342 | int sector, ret = 0; | ||
343 | |||
344 | doc_dbg("doc_seek(blocks=(%d,%d), page=%d, ofs=%d, wear=%d)\n", | ||
345 | block0, block1, page, ofs, wear); | ||
346 | |||
347 | if (!wear && (ofs < 2 * DOC_LAYOUT_PAGE_SIZE)) { | ||
348 | doc_flash_sequence(docg3, DOC_SEQ_SET_PLANE1); | ||
349 | doc_flash_command(docg3, DOC_CMD_READ_PLANE1); | ||
350 | doc_delay(docg3, 2); | ||
351 | } else { | ||
352 | doc_flash_sequence(docg3, DOC_SEQ_SET_PLANE2); | ||
353 | doc_flash_command(docg3, DOC_CMD_READ_PLANE2); | ||
354 | doc_delay(docg3, 2); | ||
355 | } | ||
356 | |||
357 | doc_set_reliable_mode(docg3); | ||
358 | if (wear) | ||
359 | ret = doc_set_extra_page_mode(docg3); | ||
360 | if (ret) | ||
361 | goto out; | ||
362 | |||
363 | sector = (block0 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK); | ||
364 | doc_flash_sequence(docg3, DOC_SEQ_READ); | ||
365 | doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR); | ||
366 | doc_delay(docg3, 1); | ||
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 | |||
372 | sector = (block1 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK); | ||
373 | doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR); | ||
374 | doc_delay(docg3, 1); | ||
375 | doc_flash_address(docg3, sector & 0xff); | ||
376 | doc_flash_address(docg3, (sector >> 8) & 0xff); | ||
377 | doc_flash_address(docg3, (sector >> 16) & 0xff); | ||
378 | doc_delay(docg3, 2); | ||
379 | |||
380 | out: | ||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | /** | ||
385 | * doc_read_page_ecc_init - Initialize hardware ECC engine | ||
386 | * @docg3: the device | ||
387 | * @len: the number of bytes covered by the ECC (BCH covered) | ||
388 | * | ||
389 | * The function does initialize the hardware ECC engine to compute the Hamming | ||
390 | * ECC (on 1 byte) and the BCH Syndroms (on 7 bytes). | ||
391 | * | ||
392 | * Return 0 if succeeded, -EIO on error | ||
393 | */ | ||
394 | static int doc_read_page_ecc_init(struct docg3 *docg3, int len) | ||
395 | { | ||
396 | doc_writew(docg3, DOC_ECCCONF0_READ_MODE | ||
397 | | DOC_ECCCONF0_BCH_ENABLE | DOC_ECCCONF0_HAMMING_ENABLE | ||
398 | | (len & DOC_ECCCONF0_DATA_BYTES_MASK), | ||
399 | DOC_ECCCONF0); | ||
400 | doc_delay(docg3, 4); | ||
401 | doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
402 | return doc_wait_ready(docg3); | ||
403 | } | ||
404 | |||
405 | /** | ||
406 | * doc_read_page_prepare - Prepares reading data from a flash page | ||
407 | * @docg3: the device | ||
408 | * @block0: the first plane block index on flash memory | ||
409 | * @block1: the second plane block index on flash memory | ||
410 | * @page: the page index in the block | ||
411 | * @offset: the offset in the page (must be a multiple of 4) | ||
412 | * | ||
413 | * Prepares the page to be read in the flash memory : | ||
414 | * - tell ASIC to map the flash pages | ||
415 | * - tell ASIC to be in read mode | ||
416 | * | ||
417 | * After a call to this method, a call to doc_read_page_finish is mandatory, | ||
418 | * to end the read cycle of the flash. | ||
419 | * | ||
420 | * Read data from a flash page. The length to be read must be between 0 and | ||
421 | * (page_size + oob_size + wear_size), ie. 532, and a multiple of 4 (because | ||
422 | * the extra bytes reading is not implemented). | ||
423 | * | ||
424 | * As pages are grouped by 2 (in 2 planes), reading from a page must be done | ||
425 | * in two steps: | ||
426 | * - one read of 512 bytes at offset 0 | ||
427 | * - one read of 512 bytes at offset 512 + 16 | ||
428 | * | ||
429 | * Returns 0 if successful, -EIO if a read error occured. | ||
430 | */ | ||
431 | static int doc_read_page_prepare(struct docg3 *docg3, int block0, int block1, | ||
432 | int page, int offset) | ||
433 | { | ||
434 | int wear_area = 0, ret = 0; | ||
435 | |||
436 | doc_dbg("doc_read_page_prepare(blocks=(%d,%d), page=%d, ofsInPage=%d)\n", | ||
437 | block0, block1, page, offset); | ||
438 | if (offset >= DOC_LAYOUT_WEAR_OFFSET) | ||
439 | wear_area = 1; | ||
440 | if (!wear_area && offset > (DOC_LAYOUT_PAGE_OOB_SIZE * 2)) | ||
441 | return -EINVAL; | ||
442 | |||
443 | doc_set_device_id(docg3, docg3->device_id); | ||
444 | ret = doc_reset_seq(docg3); | ||
445 | if (ret) | ||
446 | goto err; | ||
447 | |||
448 | /* Program the flash address block and page */ | ||
449 | ret = doc_read_seek(docg3, block0, block1, page, wear_area, offset); | ||
450 | if (ret) | ||
451 | goto err; | ||
452 | |||
453 | doc_flash_command(docg3, DOC_CMD_READ_ALL_PLANES); | ||
454 | doc_delay(docg3, 2); | ||
455 | doc_wait_ready(docg3); | ||
456 | |||
457 | doc_flash_command(docg3, DOC_CMD_SET_ADDR_READ); | ||
458 | doc_delay(docg3, 1); | ||
459 | if (offset >= DOC_LAYOUT_PAGE_SIZE * 2) | ||
460 | offset -= 2 * DOC_LAYOUT_PAGE_SIZE; | ||
461 | doc_flash_address(docg3, offset >> 2); | ||
462 | doc_delay(docg3, 1); | ||
463 | doc_wait_ready(docg3); | ||
464 | |||
465 | doc_flash_command(docg3, DOC_CMD_READ_FLASH); | ||
466 | |||
467 | return 0; | ||
468 | err: | ||
469 | doc_writeb(docg3, 0, DOC_DATAEND); | ||
470 | doc_delay(docg3, 2); | ||
471 | return -EIO; | ||
472 | } | ||
473 | |||
474 | /** | ||
475 | * doc_read_page_getbytes - Reads bytes from a prepared page | ||
476 | * @docg3: the device | ||
477 | * @len: the number of bytes to be read (must be a multiple of 4) | ||
478 | * @buf: the buffer to be filled in | ||
479 | * @first: 1 if first time read, DOC_READADDRESS should be set | ||
480 | * | ||
481 | */ | ||
482 | static int doc_read_page_getbytes(struct docg3 *docg3, int len, u_char *buf, | ||
483 | int first) | ||
484 | { | ||
485 | doc_read_data_area(docg3, buf, len, first); | ||
486 | doc_delay(docg3, 2); | ||
487 | return len; | ||
488 | } | ||
489 | |||
490 | /** | ||
491 | * doc_get_hw_bch_syndroms - Get hardware calculated BCH syndroms | ||
492 | * @docg3: the device | ||
493 | * @syns: the array of 7 integers where the syndroms will be stored | ||
494 | */ | ||
495 | static void doc_get_hw_bch_syndroms(struct docg3 *docg3, int *syns) | ||
496 | { | ||
497 | int i; | ||
498 | |||
499 | for (i = 0; i < DOC_ECC_BCH_SIZE; i++) | ||
500 | syns[i] = doc_register_readb(docg3, DOC_BCH_SYNDROM(i)); | ||
501 | } | ||
502 | |||
503 | /** | ||
504 | * doc_read_page_finish - Ends reading of a flash page | ||
505 | * @docg3: the device | ||
506 | * | ||
507 | * As a side effect, resets the chip selector to 0. This ensures that after each | ||
508 | * read operation, the floor 0 is selected. Therefore, if the systems halts, the | ||
509 | * reboot will boot on floor 0, where the IPL is. | ||
510 | */ | ||
511 | static void doc_read_page_finish(struct docg3 *docg3) | ||
512 | { | ||
513 | doc_writeb(docg3, 0, DOC_DATAEND); | ||
514 | doc_delay(docg3, 2); | ||
515 | doc_set_device_id(docg3, 0); | ||
516 | } | ||
517 | |||
518 | /** | ||
519 | * calc_block_sector - Calculate blocks, pages and ofs. | ||
520 | |||
521 | * @from: offset in flash | ||
522 | * @block0: first plane block index calculated | ||
523 | * @block1: second plane block index calculated | ||
524 | * @page: page calculated | ||
525 | * @ofs: offset in page | ||
526 | */ | ||
527 | static void calc_block_sector(loff_t from, int *block0, int *block1, int *page, | ||
528 | int *ofs) | ||
529 | { | ||
530 | uint sector; | ||
531 | |||
532 | sector = from / DOC_LAYOUT_PAGE_SIZE; | ||
533 | *block0 = sector / (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES) | ||
534 | * DOC_LAYOUT_NBPLANES; | ||
535 | *block1 = *block0 + 1; | ||
536 | *page = sector % (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES); | ||
537 | *page /= DOC_LAYOUT_NBPLANES; | ||
538 | if (sector % 2) | ||
539 | *ofs = DOC_LAYOUT_PAGE_OOB_SIZE; | ||
540 | else | ||
541 | *ofs = 0; | ||
542 | } | ||
543 | |||
544 | /** | ||
545 | * doc_read - Read bytes from flash | ||
546 | * @mtd: the device | ||
547 | * @from: the offset from first block and first page, in bytes, aligned on page | ||
548 | * size | ||
549 | * @len: the number of bytes to read (must be a multiple of 4) | ||
550 | * @retlen: the number of bytes actually read | ||
551 | * @buf: the filled in buffer | ||
552 | * | ||
553 | * Reads flash memory pages. This function does not read the OOB chunk, but only | ||
554 | * the page data. | ||
555 | * | ||
556 | * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured | ||
557 | */ | ||
558 | static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, | ||
559 | size_t *retlen, u_char *buf) | ||
560 | { | ||
561 | struct docg3 *docg3 = mtd->priv; | ||
562 | int block0, block1, page, readlen, ret, ofs = 0; | ||
563 | int syn[DOC_ECC_BCH_SIZE], eccconf1; | ||
564 | u8 oob[DOC_LAYOUT_OOB_SIZE]; | ||
565 | |||
566 | ret = -EINVAL; | ||
567 | doc_dbg("doc_read(from=%lld, len=%zu, buf=%p)\n", from, len, buf); | ||
568 | if (from % DOC_LAYOUT_PAGE_SIZE) | ||
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) | ||
574 | goto err; | ||
575 | |||
576 | *retlen = 0; | ||
577 | ret = 0; | ||
578 | readlen = min_t(size_t, len, (size_t)DOC_LAYOUT_PAGE_SIZE); | ||
579 | while (!ret && len > 0) { | ||
580 | readlen = min_t(size_t, len, (size_t)DOC_LAYOUT_PAGE_SIZE); | ||
581 | ret = doc_read_page_prepare(docg3, block0, block1, page, ofs); | ||
582 | if (ret < 0) | ||
583 | goto err; | ||
584 | ret = doc_read_page_ecc_init(docg3, DOC_ECC_BCH_COVERED_BYTES); | ||
585 | if (ret < 0) | ||
586 | goto err_in_read; | ||
587 | ret = doc_read_page_getbytes(docg3, readlen, buf, 1); | ||
588 | if (ret < readlen) | ||
589 | goto err_in_read; | ||
590 | ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE, | ||
591 | oob, 0); | ||
592 | if (ret < DOC_LAYOUT_OOB_SIZE) | ||
593 | goto err_in_read; | ||
594 | |||
595 | *retlen += readlen; | ||
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); | ||
614 | |||
615 | doc_dbg("OOB - INFO: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
616 | oob[0], oob[1], oob[2], oob[3], oob[4], | ||
617 | oob[5], oob[6]); | ||
618 | doc_dbg("OOB - HAMMING: %02x\n", oob[7]); | ||
619 | doc_dbg("OOB - BCH_ECC: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
620 | oob[8], oob[9], oob[10], oob[11], oob[12], | ||
621 | oob[13], oob[14]); | ||
622 | doc_dbg("OOB - UNUSED: %02x\n", oob[15]); | ||
623 | doc_dbg("ECC checks: ECCConf1=%x\n", eccconf1); | ||
624 | doc_dbg("ECC BCH syndrom: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
625 | syn[0], syn[1], syn[2], syn[3], syn[4], syn[5], syn[6]); | ||
626 | |||
627 | ret = -EBADMSG; | ||
628 | if (block0 >= DOC_LAYOUT_BLOCK_FIRST_DATA) { | ||
629 | if (eccconf1 & DOC_ECCCONF1_BCH_SYNDROM_ERR) | ||
630 | goto err_in_read; | ||
631 | if (is_prot_seq_error(docg3)) | ||
632 | goto err_in_read; | ||
633 | } | ||
634 | doc_read_page_finish(docg3); | ||
635 | } | ||
636 | |||
637 | return 0; | ||
638 | err_in_read: | ||
639 | doc_read_page_finish(docg3); | ||
640 | err: | ||
641 | return ret; | ||
642 | } | ||
643 | |||
644 | /** | ||
645 | * doc_read_oob - Read out of band bytes from flash | ||
646 | * @mtd: the device | ||
647 | * @from: the offset from first block and first page, in bytes, aligned on page | ||
648 | * size | ||
649 | * @ops: the mtd oob structure | ||
650 | * | ||
651 | * Reads flash memory OOB area of pages. | ||
652 | * | ||
653 | * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured | ||
654 | */ | ||
655 | static int doc_read_oob(struct mtd_info *mtd, loff_t from, | ||
656 | struct mtd_oob_ops *ops) | ||
657 | { | ||
658 | struct docg3 *docg3 = mtd->priv; | ||
659 | int block0, block1, page, ofs, 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 | |||
675 | calc_block_sector(from, &block0, &block1, &page, &ofs); | ||
676 | if (block1 > docg3->max_block) | ||
677 | return -EINVAL; | ||
678 | |||
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 | |||
688 | if (ret > 0) | ||
689 | ops->oobretlen = ret; | ||
690 | else | ||
691 | ops->oobretlen = 0; | ||
692 | return (ret > 0) ? 0 : ret; | ||
693 | } | ||
694 | |||
695 | static int doc_reload_bbt(struct docg3 *docg3) | ||
696 | { | ||
697 | int block = DOC_LAYOUT_BLOCK_BBT; | ||
698 | int ret = 0, nbpages, page; | ||
699 | u_char *buf = docg3->bbt; | ||
700 | |||
701 | nbpages = DIV_ROUND_UP(docg3->max_block + 1, 8 * DOC_LAYOUT_PAGE_SIZE); | ||
702 | for (page = 0; !ret && (page < nbpages); page++) { | ||
703 | ret = doc_read_page_prepare(docg3, block, block + 1, | ||
704 | page + DOC_LAYOUT_PAGE_BBT, 0); | ||
705 | if (!ret) | ||
706 | ret = doc_read_page_ecc_init(docg3, | ||
707 | DOC_LAYOUT_PAGE_SIZE); | ||
708 | if (!ret) | ||
709 | doc_read_page_getbytes(docg3, DOC_LAYOUT_PAGE_SIZE, | ||
710 | buf, 1); | ||
711 | buf += DOC_LAYOUT_PAGE_SIZE; | ||
712 | } | ||
713 | doc_read_page_finish(docg3); | ||
714 | return ret; | ||
715 | } | ||
716 | |||
717 | /** | ||
718 | * doc_block_isbad - Checks whether a block is good or not | ||
719 | * @mtd: the device | ||
720 | * @from: the offset to find the correct block | ||
721 | * | ||
722 | * Returns 1 if block is bad, 0 if block is good | ||
723 | */ | ||
724 | static int doc_block_isbad(struct mtd_info *mtd, loff_t from) | ||
725 | { | ||
726 | struct docg3 *docg3 = mtd->priv; | ||
727 | int block0, block1, page, ofs, is_good; | ||
728 | |||
729 | calc_block_sector(from, &block0, &block1, &page, &ofs); | ||
730 | doc_dbg("doc_block_isbad(from=%lld) => block=(%d,%d), page=%d, ofs=%d\n", | ||
731 | from, block0, block1, page, ofs); | ||
732 | |||
733 | if (block0 < DOC_LAYOUT_BLOCK_FIRST_DATA) | ||
734 | return 0; | ||
735 | if (block1 > docg3->max_block) | ||
736 | return -EINVAL; | ||
737 | |||
738 | is_good = docg3->bbt[block0 >> 3] & (1 << (block0 & 0x7)); | ||
739 | return !is_good; | ||
740 | } | ||
741 | |||
742 | /** | ||
743 | * doc_get_erase_count - Get block erase count | ||
744 | * @docg3: the device | ||
745 | * @from: the offset in which the block is. | ||
746 | * | ||
747 | * Get the number of times a block was erased. The number is the maximum of | ||
748 | * erase times between first and second plane (which should be equal normally). | ||
749 | * | ||
750 | * Returns The number of erases, or -EINVAL or -EIO on error. | ||
751 | */ | ||
752 | static int doc_get_erase_count(struct docg3 *docg3, loff_t from) | ||
753 | { | ||
754 | u8 buf[DOC_LAYOUT_WEAR_SIZE]; | ||
755 | int ret, plane1_erase_count, plane2_erase_count; | ||
756 | int block0, block1, page, ofs; | ||
757 | |||
758 | doc_dbg("doc_get_erase_count(from=%lld, buf=%p)\n", from, buf); | ||
759 | if (from % DOC_LAYOUT_PAGE_SIZE) | ||
760 | return -EINVAL; | ||
761 | calc_block_sector(from, &block0, &block1, &page, &ofs); | ||
762 | if (block1 > docg3->max_block) | ||
763 | return -EINVAL; | ||
764 | |||
765 | ret = doc_reset_seq(docg3); | ||
766 | if (!ret) | ||
767 | ret = doc_read_page_prepare(docg3, block0, block1, page, | ||
768 | ofs + DOC_LAYOUT_WEAR_OFFSET); | ||
769 | if (!ret) | ||
770 | ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_WEAR_SIZE, | ||
771 | buf, 1); | ||
772 | doc_read_page_finish(docg3); | ||
773 | |||
774 | if (ret || (buf[0] != DOC_ERASE_MARK) || (buf[2] != DOC_ERASE_MARK)) | ||
775 | return -EIO; | ||
776 | plane1_erase_count = (u8)(~buf[1]) | ((u8)(~buf[4]) << 8) | ||
777 | | ((u8)(~buf[5]) << 16); | ||
778 | plane2_erase_count = (u8)(~buf[3]) | ((u8)(~buf[6]) << 8) | ||
779 | | ((u8)(~buf[7]) << 16); | ||
780 | |||
781 | return max(plane1_erase_count, plane2_erase_count); | ||
782 | } | ||
783 | |||
784 | /* | ||
785 | * Debug sysfs entries | ||
786 | */ | ||
787 | static int dbg_flashctrl_show(struct seq_file *s, void *p) | ||
788 | { | ||
789 | struct docg3 *docg3 = (struct docg3 *)s->private; | ||
790 | |||
791 | int pos = 0; | ||
792 | u8 fctrl = doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
793 | |||
794 | pos += seq_printf(s, | ||
795 | "FlashControl : 0x%02x (%s,CE# %s,%s,%s,flash %s)\n", | ||
796 | fctrl, | ||
797 | fctrl & DOC_CTRL_VIOLATION ? "protocol violation" : "-", | ||
798 | fctrl & DOC_CTRL_CE ? "active" : "inactive", | ||
799 | fctrl & DOC_CTRL_PROTECTION_ERROR ? "protection error" : "-", | ||
800 | fctrl & DOC_CTRL_SEQUENCE_ERROR ? "sequence error" : "-", | ||
801 | fctrl & DOC_CTRL_FLASHREADY ? "ready" : "not ready"); | ||
802 | return pos; | ||
803 | } | ||
804 | DEBUGFS_RO_ATTR(flashcontrol, dbg_flashctrl_show); | ||
805 | |||
806 | static int dbg_asicmode_show(struct seq_file *s, void *p) | ||
807 | { | ||
808 | struct docg3 *docg3 = (struct docg3 *)s->private; | ||
809 | |||
810 | int pos = 0; | ||
811 | int pctrl = doc_register_readb(docg3, DOC_ASICMODE); | ||
812 | int mode = pctrl & 0x03; | ||
813 | |||
814 | pos += seq_printf(s, | ||
815 | "%04x : RAM_WE=%d,RSTIN_RESET=%d,BDETCT_RESET=%d,WRITE_ENABLE=%d,POWERDOWN=%d,MODE=%d%d (", | ||
816 | pctrl, | ||
817 | pctrl & DOC_ASICMODE_RAM_WE ? 1 : 0, | ||
818 | pctrl & DOC_ASICMODE_RSTIN_RESET ? 1 : 0, | ||
819 | pctrl & DOC_ASICMODE_BDETCT_RESET ? 1 : 0, | ||
820 | pctrl & DOC_ASICMODE_MDWREN ? 1 : 0, | ||
821 | pctrl & DOC_ASICMODE_POWERDOWN ? 1 : 0, | ||
822 | mode >> 1, mode & 0x1); | ||
823 | |||
824 | switch (mode) { | ||
825 | case DOC_ASICMODE_RESET: | ||
826 | pos += seq_printf(s, "reset"); | ||
827 | break; | ||
828 | case DOC_ASICMODE_NORMAL: | ||
829 | pos += seq_printf(s, "normal"); | ||
830 | break; | ||
831 | case DOC_ASICMODE_POWERDOWN: | ||
832 | pos += seq_printf(s, "powerdown"); | ||
833 | break; | ||
834 | } | ||
835 | pos += seq_printf(s, ")\n"); | ||
836 | return pos; | ||
837 | } | ||
838 | DEBUGFS_RO_ATTR(asic_mode, dbg_asicmode_show); | ||
839 | |||
840 | static int dbg_device_id_show(struct seq_file *s, void *p) | ||
841 | { | ||
842 | struct docg3 *docg3 = (struct docg3 *)s->private; | ||
843 | int pos = 0; | ||
844 | int id = doc_register_readb(docg3, DOC_DEVICESELECT); | ||
845 | |||
846 | pos += seq_printf(s, "DeviceId = %d\n", id); | ||
847 | return pos; | ||
848 | } | ||
849 | DEBUGFS_RO_ATTR(device_id, dbg_device_id_show); | ||
850 | |||
851 | static int dbg_protection_show(struct seq_file *s, void *p) | ||
852 | { | ||
853 | struct docg3 *docg3 = (struct docg3 *)s->private; | ||
854 | int pos = 0; | ||
855 | int protect = doc_register_readb(docg3, DOC_PROTECTION); | ||
856 | int dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS); | ||
857 | int dps0_low = doc_register_readb(docg3, DOC_DPS0_ADDRLOW); | ||
858 | int dps0_high = doc_register_readb(docg3, DOC_DPS0_ADDRHIGH); | ||
859 | int dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS); | ||
860 | int dps1_low = doc_register_readb(docg3, DOC_DPS1_ADDRLOW); | ||
861 | int dps1_high = doc_register_readb(docg3, DOC_DPS1_ADDRHIGH); | ||
862 | |||
863 | pos += seq_printf(s, "Protection = 0x%02x (", | ||
864 | protect); | ||
865 | if (protect & DOC_PROTECT_FOUNDRY_OTP_LOCK) | ||
866 | pos += seq_printf(s, "FOUNDRY_OTP_LOCK,"); | ||
867 | if (protect & DOC_PROTECT_CUSTOMER_OTP_LOCK) | ||
868 | pos += seq_printf(s, "CUSTOMER_OTP_LOCK,"); | ||
869 | if (protect & DOC_PROTECT_LOCK_INPUT) | ||
870 | pos += seq_printf(s, "LOCK_INPUT,"); | ||
871 | if (protect & DOC_PROTECT_STICKY_LOCK) | ||
872 | pos += seq_printf(s, "STICKY_LOCK,"); | ||
873 | if (protect & DOC_PROTECT_PROTECTION_ENABLED) | ||
874 | pos += seq_printf(s, "PROTECTION ON,"); | ||
875 | if (protect & DOC_PROTECT_IPL_DOWNLOAD_LOCK) | ||
876 | pos += seq_printf(s, "IPL_DOWNLOAD_LOCK,"); | ||
877 | if (protect & DOC_PROTECT_PROTECTION_ERROR) | ||
878 | pos += seq_printf(s, "PROTECT_ERR,"); | ||
879 | else | ||
880 | pos += seq_printf(s, "NO_PROTECT_ERR"); | ||
881 | pos += seq_printf(s, ")\n"); | ||
882 | |||
883 | pos += seq_printf(s, "DPS0 = 0x%02x : " | ||
884 | "Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, " | ||
885 | "WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n", | ||
886 | dps0, dps0_low, dps0_high, | ||
887 | !!(dps0 & DOC_DPS_OTP_PROTECTED), | ||
888 | !!(dps0 & DOC_DPS_READ_PROTECTED), | ||
889 | !!(dps0 & DOC_DPS_WRITE_PROTECTED), | ||
890 | !!(dps0 & DOC_DPS_HW_LOCK_ENABLED), | ||
891 | !!(dps0 & DOC_DPS_KEY_OK)); | ||
892 | pos += seq_printf(s, "DPS1 = 0x%02x : " | ||
893 | "Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, " | ||
894 | "WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n", | ||
895 | dps1, dps1_low, dps1_high, | ||
896 | !!(dps1 & DOC_DPS_OTP_PROTECTED), | ||
897 | !!(dps1 & DOC_DPS_READ_PROTECTED), | ||
898 | !!(dps1 & DOC_DPS_WRITE_PROTECTED), | ||
899 | !!(dps1 & DOC_DPS_HW_LOCK_ENABLED), | ||
900 | !!(dps1 & DOC_DPS_KEY_OK)); | ||
901 | return pos; | ||
902 | } | ||
903 | DEBUGFS_RO_ATTR(protection, dbg_protection_show); | ||
904 | |||
905 | static int __init doc_dbg_register(struct docg3 *docg3) | ||
906 | { | ||
907 | struct dentry *root, *entry; | ||
908 | |||
909 | root = debugfs_create_dir("docg3", NULL); | ||
910 | if (!root) | ||
911 | return -ENOMEM; | ||
912 | |||
913 | entry = debugfs_create_file("flashcontrol", S_IRUSR, root, docg3, | ||
914 | &flashcontrol_fops); | ||
915 | if (entry) | ||
916 | entry = debugfs_create_file("asic_mode", S_IRUSR, root, | ||
917 | docg3, &asic_mode_fops); | ||
918 | if (entry) | ||
919 | entry = debugfs_create_file("device_id", S_IRUSR, root, | ||
920 | docg3, &device_id_fops); | ||
921 | if (entry) | ||
922 | entry = debugfs_create_file("protection", S_IRUSR, root, | ||
923 | docg3, &protection_fops); | ||
924 | if (entry) { | ||
925 | docg3->debugfs_root = root; | ||
926 | return 0; | ||
927 | } else { | ||
928 | debugfs_remove_recursive(root); | ||
929 | return -ENOMEM; | ||
930 | } | ||
931 | } | ||
932 | |||
933 | static void __exit doc_dbg_unregister(struct docg3 *docg3) | ||
934 | { | ||
935 | debugfs_remove_recursive(docg3->debugfs_root); | ||
936 | } | ||
937 | |||
938 | /** | ||
939 | * doc_set_driver_info - Fill the mtd_info structure and docg3 structure | ||
940 | * @chip_id: The chip ID of the supported chip | ||
941 | * @mtd: The structure to fill | ||
942 | */ | ||
943 | static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd) | ||
944 | { | ||
945 | struct docg3 *docg3 = mtd->priv; | ||
946 | int cfg; | ||
947 | |||
948 | cfg = doc_register_readb(docg3, DOC_CONFIGURATION); | ||
949 | docg3->if_cfg = (cfg & DOC_CONF_IF_CFG ? 1 : 0); | ||
950 | |||
951 | switch (chip_id) { | ||
952 | case DOC_CHIPID_G3: | ||
953 | mtd->name = "DiskOnChip G3"; | ||
954 | docg3->max_block = 2047; | ||
955 | break; | ||
956 | } | ||
957 | mtd->type = MTD_NANDFLASH; | ||
958 | /* | ||
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; | ||
964 | mtd->erasesize = DOC_LAYOUT_BLOCK_SIZE * DOC_LAYOUT_NBPLANES; | ||
965 | mtd->writesize = DOC_LAYOUT_PAGE_SIZE; | ||
966 | mtd->oobsize = DOC_LAYOUT_OOB_SIZE; | ||
967 | mtd->owner = THIS_MODULE; | ||
968 | mtd->erase = NULL; | ||
969 | mtd->point = NULL; | ||
970 | mtd->unpoint = NULL; | ||
971 | mtd->read = doc_read; | ||
972 | mtd->write = NULL; | ||
973 | mtd->read_oob = doc_read_oob; | ||
974 | mtd->write_oob = NULL; | ||
975 | mtd->sync = NULL; | ||
976 | mtd->block_isbad = doc_block_isbad; | ||
977 | } | ||
978 | |||
979 | /** | ||
980 | * doc_probe - Probe the IO space for a DiskOnChip G3 chip | ||
981 | * @pdev: platform device | ||
982 | * | ||
983 | * Probes for a G3 chip at the specified IO space in the platform data | ||
984 | * ressources. | ||
985 | * | ||
986 | * Returns 0 on success, -ENOMEM, -ENXIO on error | ||
987 | */ | ||
988 | static int __init docg3_probe(struct platform_device *pdev) | ||
989 | { | ||
990 | struct device *dev = &pdev->dev; | ||
991 | struct docg3 *docg3; | ||
992 | struct mtd_info *mtd; | ||
993 | struct resource *ress; | ||
994 | int ret, bbt_nbpages; | ||
995 | u16 chip_id, chip_id_inv; | ||
996 | |||
997 | ret = -ENOMEM; | ||
998 | docg3 = kzalloc(sizeof(struct docg3), GFP_KERNEL); | ||
999 | if (!docg3) | ||
1000 | goto nomem1; | ||
1001 | mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); | ||
1002 | if (!mtd) | ||
1003 | goto nomem2; | ||
1004 | mtd->priv = docg3; | ||
1005 | |||
1006 | ret = -ENXIO; | ||
1007 | ress = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1008 | if (!ress) { | ||
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); | ||
1017 | doc_set_asic_mode(docg3, DOC_ASICMODE_RESET); | ||
1018 | doc_set_asic_mode(docg3, DOC_ASICMODE_NORMAL); | ||
1019 | |||
1020 | chip_id = doc_register_readw(docg3, DOC_CHIPID); | ||
1021 | chip_id_inv = doc_register_readw(docg3, DOC_CHIPID_INV); | ||
1022 | |||
1023 | ret = -ENODEV; | ||
1024 | if (chip_id != (u16)(~chip_id_inv)) { | ||
1025 | doc_info("No device found at IO addr %p\n", | ||
1026 | (void *)ress->start); | ||
1027 | goto nochipfound; | ||
1028 | } | ||
1029 | |||
1030 | switch (chip_id) { | ||
1031 | case DOC_CHIPID_G3: | ||
1032 | doc_info("Found a G3 DiskOnChip at addr %p\n", | ||
1033 | (void *)ress->start); | ||
1034 | break; | ||
1035 | default: | ||
1036 | doc_err("Chip id %04x is not a DiskOnChip G3 chip\n", chip_id); | ||
1037 | goto nochipfound; | ||
1038 | } | ||
1039 | |||
1040 | doc_set_driver_info(chip_id, mtd); | ||
1041 | platform_set_drvdata(pdev, mtd); | ||
1042 | |||
1043 | ret = -ENOMEM; | ||
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); | ||
1050 | |||
1051 | ret = mtd_device_parse_register(mtd, part_probes, | ||
1052 | NULL, NULL, 0); | ||
1053 | if (ret) | ||
1054 | goto register_error; | ||
1055 | |||
1056 | doc_dbg_register(docg3); | ||
1057 | return 0; | ||
1058 | |||
1059 | register_error: | ||
1060 | kfree(docg3->bbt); | ||
1061 | nochipfound: | ||
1062 | iounmap(docg3->base); | ||
1063 | noress: | ||
1064 | kfree(mtd); | ||
1065 | nomem2: | ||
1066 | kfree(docg3); | ||
1067 | nomem1: | ||
1068 | return ret; | ||
1069 | } | ||
1070 | |||
1071 | /** | ||
1072 | * docg3_release - Release the driver | ||
1073 | * @pdev: the platform device | ||
1074 | * | ||
1075 | * Returns 0 | ||
1076 | */ | ||
1077 | static int __exit docg3_release(struct platform_device *pdev) | ||
1078 | { | ||
1079 | struct mtd_info *mtd = platform_get_drvdata(pdev); | ||
1080 | struct docg3 *docg3 = mtd->priv; | ||
1081 | |||
1082 | doc_dbg_unregister(docg3); | ||
1083 | mtd_device_unregister(mtd); | ||
1084 | iounmap(docg3->base); | ||
1085 | kfree(docg3->bbt); | ||
1086 | kfree(docg3); | ||
1087 | kfree(mtd); | ||
1088 | return 0; | ||
1089 | } | ||
1090 | |||
1091 | static struct platform_driver g3_driver = { | ||
1092 | .driver = { | ||
1093 | .name = "docg3", | ||
1094 | .owner = THIS_MODULE, | ||
1095 | }, | ||
1096 | .remove = __exit_p(docg3_release), | ||
1097 | }; | ||
1098 | |||
1099 | static int __init docg3_init(void) | ||
1100 | { | ||
1101 | return platform_driver_probe(&g3_driver, docg3_probe); | ||
1102 | } | ||
1103 | module_init(docg3_init); | ||
1104 | |||
1105 | |||
1106 | static void __exit docg3_exit(void) | ||
1107 | { | ||
1108 | platform_driver_unregister(&g3_driver); | ||
1109 | } | ||
1110 | module_exit(docg3_exit); | ||
1111 | |||
1112 | MODULE_LICENSE("GPL"); | ||
1113 | MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>"); | ||
1114 | MODULE_DESCRIPTION("MTD driver for DiskOnChip G3"); | ||
diff --git a/drivers/mtd/devices/docg3.h b/drivers/mtd/devices/docg3.h new file mode 100644 index 000000000000..0d407be24594 --- /dev/null +++ b/drivers/mtd/devices/docg3.h | |||
@@ -0,0 +1,297 @@ | |||
1 | /* | ||
2 | * Handles the M-Systems DiskOnChip G3 chip | ||
3 | * | ||
4 | * Copyright (C) 2011 Robert Jarzmik | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef _MTD_DOCG3_H | ||
23 | #define _MTD_DOCG3_H | ||
24 | |||
25 | /* | ||
26 | * Flash memory areas : | ||
27 | * - 0x0000 .. 0x07ff : IPL | ||
28 | * - 0x0800 .. 0x0fff : Data area | ||
29 | * - 0x1000 .. 0x17ff : Registers | ||
30 | * - 0x1800 .. 0x1fff : Unknown | ||
31 | */ | ||
32 | #define DOC_IOSPACE_IPL 0x0000 | ||
33 | #define DOC_IOSPACE_DATA 0x0800 | ||
34 | #define DOC_IOSPACE_SIZE 0x2000 | ||
35 | |||
36 | /* | ||
37 | * DOC G3 layout and adressing scheme | ||
38 | * A page address for the block "b", plane "P" and page "p": | ||
39 | * address = [bbbb bPpp pppp] | ||
40 | */ | ||
41 | |||
42 | #define DOC_ADDR_PAGE_MASK 0x3f | ||
43 | #define DOC_ADDR_BLOCK_SHIFT 6 | ||
44 | #define DOC_LAYOUT_NBPLANES 2 | ||
45 | #define DOC_LAYOUT_PAGES_PER_BLOCK 64 | ||
46 | #define DOC_LAYOUT_PAGE_SIZE 512 | ||
47 | #define DOC_LAYOUT_OOB_SIZE 16 | ||
48 | #define DOC_LAYOUT_WEAR_SIZE 8 | ||
49 | #define DOC_LAYOUT_PAGE_OOB_SIZE \ | ||
50 | (DOC_LAYOUT_PAGE_SIZE + DOC_LAYOUT_OOB_SIZE) | ||
51 | #define DOC_LAYOUT_WEAR_OFFSET (DOC_LAYOUT_PAGE_OOB_SIZE * 2) | ||
52 | #define DOC_LAYOUT_BLOCK_SIZE \ | ||
53 | (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_PAGE_SIZE) | ||
54 | #define DOC_ECC_BCH_SIZE 7 | ||
55 | #define DOC_ECC_BCH_COVERED_BYTES \ | ||
56 | (DOC_LAYOUT_PAGE_SIZE + DOC_LAYOUT_OOB_PAGEINFO_SZ + \ | ||
57 | DOC_LAYOUT_OOB_HAMMING_SZ + DOC_LAYOUT_OOB_BCH_SZ) | ||
58 | |||
59 | /* | ||
60 | * Blocks distribution | ||
61 | */ | ||
62 | #define DOC_LAYOUT_BLOCK_BBT 0 | ||
63 | #define DOC_LAYOUT_BLOCK_OTP 0 | ||
64 | #define DOC_LAYOUT_BLOCK_FIRST_DATA 6 | ||
65 | |||
66 | #define DOC_LAYOUT_PAGE_BBT 4 | ||
67 | |||
68 | /* | ||
69 | * Extra page OOB (16 bytes wide) layout | ||
70 | */ | ||
71 | #define DOC_LAYOUT_OOB_PAGEINFO_OFS 0 | ||
72 | #define DOC_LAYOUT_OOB_HAMMING_OFS 7 | ||
73 | #define DOC_LAYOUT_OOB_BCH_OFS 8 | ||
74 | #define DOC_LAYOUT_OOB_UNUSED_OFS 15 | ||
75 | #define DOC_LAYOUT_OOB_PAGEINFO_SZ 7 | ||
76 | #define DOC_LAYOUT_OOB_HAMMING_SZ 1 | ||
77 | #define DOC_LAYOUT_OOB_BCH_SZ 7 | ||
78 | #define DOC_LAYOUT_OOB_UNUSED_SZ 1 | ||
79 | |||
80 | |||
81 | #define DOC_CHIPID_G3 0x200 | ||
82 | #define DOC_ERASE_MARK 0xaa | ||
83 | /* | ||
84 | * Flash registers | ||
85 | */ | ||
86 | #define DOC_CHIPID 0x1000 | ||
87 | #define DOC_TEST 0x1004 | ||
88 | #define DOC_BUSLOCK 0x1006 | ||
89 | #define DOC_ENDIANCONTROL 0x1008 | ||
90 | #define DOC_DEVICESELECT 0x100a | ||
91 | #define DOC_ASICMODE 0x100c | ||
92 | #define DOC_CONFIGURATION 0x100e | ||
93 | #define DOC_INTERRUPTCONTROL 0x1010 | ||
94 | #define DOC_READADDRESS 0x101a | ||
95 | #define DOC_DATAEND 0x101e | ||
96 | #define DOC_INTERRUPTSTATUS 0x1020 | ||
97 | |||
98 | #define DOC_FLASHSEQUENCE 0x1032 | ||
99 | #define DOC_FLASHCOMMAND 0x1034 | ||
100 | #define DOC_FLASHADDRESS 0x1036 | ||
101 | #define DOC_FLASHCONTROL 0x1038 | ||
102 | #define DOC_NOP 0x103e | ||
103 | |||
104 | #define DOC_ECCCONF0 0x1040 | ||
105 | #define DOC_ECCCONF1 0x1042 | ||
106 | #define DOC_ECCPRESET 0x1044 | ||
107 | #define DOC_HAMMINGPARITY 0x1046 | ||
108 | #define DOC_BCH_SYNDROM(idx) (0x1048 + (idx << 1)) | ||
109 | |||
110 | #define DOC_PROTECTION 0x1056 | ||
111 | #define DOC_DPS0_ADDRLOW 0x1060 | ||
112 | #define DOC_DPS0_ADDRHIGH 0x1062 | ||
113 | #define DOC_DPS1_ADDRLOW 0x1064 | ||
114 | #define DOC_DPS1_ADDRHIGH 0x1066 | ||
115 | #define DOC_DPS0_STATUS 0x106c | ||
116 | #define DOC_DPS1_STATUS 0x106e | ||
117 | |||
118 | #define DOC_ASICMODECONFIRM 0x1072 | ||
119 | #define DOC_CHIPID_INV 0x1074 | ||
120 | |||
121 | /* | ||
122 | * Flash sequences | ||
123 | * A sequence is preset before one or more commands are input to the chip. | ||
124 | */ | ||
125 | #define DOC_SEQ_RESET 0x00 | ||
126 | #define DOC_SEQ_PAGE_SIZE_532 0x03 | ||
127 | #define DOC_SEQ_SET_MODE 0x09 | ||
128 | #define DOC_SEQ_READ 0x12 | ||
129 | #define DOC_SEQ_SET_PLANE1 0x0e | ||
130 | #define DOC_SEQ_SET_PLANE2 0x10 | ||
131 | #define DOC_SEQ_PAGE_SETUP 0x1d | ||
132 | |||
133 | /* | ||
134 | * Flash commands | ||
135 | */ | ||
136 | #define DOC_CMD_READ_PLANE1 0x00 | ||
137 | #define DOC_CMD_SET_ADDR_READ 0x05 | ||
138 | #define DOC_CMD_READ_ALL_PLANES 0x30 | ||
139 | #define DOC_CMD_READ_PLANE2 0x50 | ||
140 | #define DOC_CMD_READ_FLASH 0xe0 | ||
141 | #define DOC_CMD_PAGE_SIZE_532 0x3c | ||
142 | |||
143 | #define DOC_CMD_PROG_BLOCK_ADDR 0x60 | ||
144 | #define DOC_CMD_PROG_CYCLE1 0x80 | ||
145 | #define DOC_CMD_PROG_CYCLE2 0x10 | ||
146 | #define DOC_CMD_ERASECYCLE2 0xd0 | ||
147 | |||
148 | #define DOC_CMD_RELIABLE_MODE 0x22 | ||
149 | #define DOC_CMD_FAST_MODE 0xa2 | ||
150 | |||
151 | #define DOC_CMD_RESET 0xff | ||
152 | |||
153 | /* | ||
154 | * Flash register : DOC_FLASHCONTROL | ||
155 | */ | ||
156 | #define DOC_CTRL_VIOLATION 0x20 | ||
157 | #define DOC_CTRL_CE 0x10 | ||
158 | #define DOC_CTRL_UNKNOWN_BITS 0x08 | ||
159 | #define DOC_CTRL_PROTECTION_ERROR 0x04 | ||
160 | #define DOC_CTRL_SEQUENCE_ERROR 0x02 | ||
161 | #define DOC_CTRL_FLASHREADY 0x01 | ||
162 | |||
163 | /* | ||
164 | * Flash register : DOC_ASICMODE | ||
165 | */ | ||
166 | #define DOC_ASICMODE_RESET 0x00 | ||
167 | #define DOC_ASICMODE_NORMAL 0x01 | ||
168 | #define DOC_ASICMODE_POWERDOWN 0x02 | ||
169 | #define DOC_ASICMODE_MDWREN 0x04 | ||
170 | #define DOC_ASICMODE_BDETCT_RESET 0x08 | ||
171 | #define DOC_ASICMODE_RSTIN_RESET 0x10 | ||
172 | #define DOC_ASICMODE_RAM_WE 0x20 | ||
173 | |||
174 | /* | ||
175 | * Flash register : DOC_ECCCONF0 | ||
176 | */ | ||
177 | #define DOC_ECCCONF0_READ_MODE 0x8000 | ||
178 | #define DOC_ECCCONF0_AUTO_ECC_ENABLE 0x4000 | ||
179 | #define DOC_ECCCONF0_HAMMING_ENABLE 0x1000 | ||
180 | #define DOC_ECCCONF0_BCH_ENABLE 0x0800 | ||
181 | #define DOC_ECCCONF0_DATA_BYTES_MASK 0x07ff | ||
182 | |||
183 | /* | ||
184 | * Flash register : DOC_ECCCONF1 | ||
185 | */ | ||
186 | #define DOC_ECCCONF1_BCH_SYNDROM_ERR 0x80 | ||
187 | #define DOC_ECCCONF1_UNKOWN1 0x40 | ||
188 | #define DOC_ECCCONF1_UNKOWN2 0x20 | ||
189 | #define DOC_ECCCONF1_UNKOWN3 0x10 | ||
190 | #define DOC_ECCCONF1_HAMMING_BITS_MASK 0x0f | ||
191 | |||
192 | /* | ||
193 | * Flash register : DOC_PROTECTION | ||
194 | */ | ||
195 | #define DOC_PROTECT_FOUNDRY_OTP_LOCK 0x01 | ||
196 | #define DOC_PROTECT_CUSTOMER_OTP_LOCK 0x02 | ||
197 | #define DOC_PROTECT_LOCK_INPUT 0x04 | ||
198 | #define DOC_PROTECT_STICKY_LOCK 0x08 | ||
199 | #define DOC_PROTECT_PROTECTION_ENABLED 0x10 | ||
200 | #define DOC_PROTECT_IPL_DOWNLOAD_LOCK 0x20 | ||
201 | #define DOC_PROTECT_PROTECTION_ERROR 0x80 | ||
202 | |||
203 | /* | ||
204 | * Flash register : DOC_DPS0_STATUS and DOC_DPS1_STATUS | ||
205 | */ | ||
206 | #define DOC_DPS_OTP_PROTECTED 0x01 | ||
207 | #define DOC_DPS_READ_PROTECTED 0x02 | ||
208 | #define DOC_DPS_WRITE_PROTECTED 0x04 | ||
209 | #define DOC_DPS_HW_LOCK_ENABLED 0x08 | ||
210 | #define DOC_DPS_KEY_OK 0x80 | ||
211 | |||
212 | /* | ||
213 | * Flash register : DOC_CONFIGURATION | ||
214 | */ | ||
215 | #define DOC_CONF_IF_CFG 0x80 | ||
216 | #define DOC_CONF_MAX_ID_MASK 0x30 | ||
217 | #define DOC_CONF_VCCQ_3V 0x01 | ||
218 | |||
219 | /* | ||
220 | * Flash register : DOC_READADDRESS | ||
221 | */ | ||
222 | #define DOC_READADDR_INC 0x8000 | ||
223 | #define DOC_READADDR_ONE_BYTE 0x4000 | ||
224 | #define DOC_READADDR_ADDR_MASK 0x1fff | ||
225 | |||
226 | /** | ||
227 | * struct docg3 - DiskOnChip driver private data | ||
228 | * @dev: the device currently under control | ||
229 | * @base: mapped IO space | ||
230 | * @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 | ||
232 | * @bbt: bad block table cache | ||
233 | * @debugfs_root: debugfs root node | ||
234 | */ | ||
235 | struct docg3 { | ||
236 | struct device *dev; | ||
237 | void __iomem *base; | ||
238 | unsigned int device_id:4; | ||
239 | unsigned int if_cfg:1; | ||
240 | int max_block; | ||
241 | u8 *bbt; | ||
242 | struct dentry *debugfs_root; | ||
243 | }; | ||
244 | |||
245 | #define doc_err(fmt, arg...) dev_err(docg3->dev, (fmt), ## arg) | ||
246 | #define doc_info(fmt, arg...) dev_info(docg3->dev, (fmt), ## arg) | ||
247 | #define doc_dbg(fmt, arg...) dev_dbg(docg3->dev, (fmt), ## arg) | ||
248 | #define doc_vdbg(fmt, arg...) dev_vdbg(docg3->dev, (fmt), ## arg) | ||
249 | |||
250 | #define DEBUGFS_RO_ATTR(name, show_fct) \ | ||
251 | static int name##_open(struct inode *inode, struct file *file) \ | ||
252 | { return single_open(file, show_fct, inode->i_private); } \ | ||
253 | static const struct file_operations name##_fops = { \ | ||
254 | .owner = THIS_MODULE, \ | ||
255 | .open = name##_open, \ | ||
256 | .llseek = seq_lseek, \ | ||
257 | .read = seq_read, \ | ||
258 | .release = single_release \ | ||
259 | }; | ||
260 | #endif | ||
261 | |||
262 | /* | ||
263 | * Trace events part | ||
264 | */ | ||
265 | #undef TRACE_SYSTEM | ||
266 | #define TRACE_SYSTEM docg3 | ||
267 | |||
268 | #if !defined(_MTD_DOCG3_TRACE) || defined(TRACE_HEADER_MULTI_READ) | ||
269 | #define _MTD_DOCG3_TRACE | ||
270 | |||
271 | #include <linux/tracepoint.h> | ||
272 | |||
273 | TRACE_EVENT(docg3_io, | ||
274 | TP_PROTO(int op, int width, u16 reg, int val), | ||
275 | TP_ARGS(op, width, reg, val), | ||
276 | TP_STRUCT__entry( | ||
277 | __field(int, op) | ||
278 | __field(unsigned char, width) | ||
279 | __field(u16, reg) | ||
280 | __field(int, val)), | ||
281 | TP_fast_assign( | ||
282 | __entry->op = op; | ||
283 | __entry->width = width; | ||
284 | __entry->reg = reg; | ||
285 | __entry->val = val;), | ||
286 | TP_printk("docg3: %s%02d reg=%04x, val=%04x", | ||
287 | __entry->op ? "write" : "read", __entry->width, | ||
288 | __entry->reg, __entry->val) | ||
289 | ); | ||
290 | #endif | ||
291 | |||
292 | /* This part must be outside protection */ | ||
293 | #undef TRACE_INCLUDE_PATH | ||
294 | #undef TRACE_INCLUDE_FILE | ||
295 | #define TRACE_INCLUDE_PATH . | ||
296 | #define TRACE_INCLUDE_FILE docg3 | ||
297 | #include <trace/define_trace.h> | ||
diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c index d374603493a7..45116bb30297 100644 --- a/drivers/mtd/devices/docprobe.c +++ b/drivers/mtd/devices/docprobe.c | |||
@@ -50,11 +50,6 @@ | |||
50 | #include <linux/mtd/nand.h> | 50 | #include <linux/mtd/nand.h> |
51 | #include <linux/mtd/doc2000.h> | 51 | #include <linux/mtd/doc2000.h> |
52 | 52 | ||
53 | /* Where to look for the devices? */ | ||
54 | #ifndef CONFIG_MTD_DOCPROBE_ADDRESS | ||
55 | #define CONFIG_MTD_DOCPROBE_ADDRESS 0 | ||
56 | #endif | ||
57 | |||
58 | 53 | ||
59 | static unsigned long doc_config_location = CONFIG_MTD_DOCPROBE_ADDRESS; | 54 | static unsigned long doc_config_location = CONFIG_MTD_DOCPROBE_ADDRESS; |
60 | module_param(doc_config_location, ulong, 0); | 55 | module_param(doc_config_location, ulong, 0); |
diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c index 772a0ff89e0f..3a11ea628e58 100644 --- a/drivers/mtd/devices/lart.c +++ b/drivers/mtd/devices/lart.c | |||
@@ -34,9 +34,6 @@ | |||
34 | /* debugging */ | 34 | /* debugging */ |
35 | //#define LART_DEBUG | 35 | //#define LART_DEBUG |
36 | 36 | ||
37 | /* partition support */ | ||
38 | #define HAVE_PARTITIONS | ||
39 | |||
40 | #include <linux/kernel.h> | 37 | #include <linux/kernel.h> |
41 | #include <linux/module.h> | 38 | #include <linux/module.h> |
42 | #include <linux/types.h> | 39 | #include <linux/types.h> |
@@ -44,9 +41,7 @@ | |||
44 | #include <linux/errno.h> | 41 | #include <linux/errno.h> |
45 | #include <linux/string.h> | 42 | #include <linux/string.h> |
46 | #include <linux/mtd/mtd.h> | 43 | #include <linux/mtd/mtd.h> |
47 | #ifdef HAVE_PARTITIONS | ||
48 | #include <linux/mtd/partitions.h> | 44 | #include <linux/mtd/partitions.h> |
49 | #endif | ||
50 | 45 | ||
51 | #ifndef CONFIG_SA1100_LART | 46 | #ifndef CONFIG_SA1100_LART |
52 | #error This is for LART architecture only | 47 | #error This is for LART architecture only |
@@ -598,7 +593,6 @@ static struct mtd_erase_region_info erase_regions[] = { | |||
598 | } | 593 | } |
599 | }; | 594 | }; |
600 | 595 | ||
601 | #ifdef HAVE_PARTITIONS | ||
602 | static struct mtd_partition lart_partitions[] = { | 596 | static struct mtd_partition lart_partitions[] = { |
603 | /* blob */ | 597 | /* blob */ |
604 | { | 598 | { |
@@ -619,7 +613,7 @@ static struct mtd_partition lart_partitions[] = { | |||
619 | .size = INITRD_LEN, /* MTDPART_SIZ_FULL */ | 613 | .size = INITRD_LEN, /* MTDPART_SIZ_FULL */ |
620 | } | 614 | } |
621 | }; | 615 | }; |
622 | #endif | 616 | #define NUM_PARTITIONS ARRAY_SIZE(lart_partitions) |
623 | 617 | ||
624 | static int __init lart_flash_init (void) | 618 | static int __init lart_flash_init (void) |
625 | { | 619 | { |
@@ -668,7 +662,6 @@ static int __init lart_flash_init (void) | |||
668 | result,mtd.eraseregions[result].erasesize,mtd.eraseregions[result].erasesize / 1024, | 662 | result,mtd.eraseregions[result].erasesize,mtd.eraseregions[result].erasesize / 1024, |
669 | result,mtd.eraseregions[result].numblocks); | 663 | result,mtd.eraseregions[result].numblocks); |
670 | 664 | ||
671 | #ifdef HAVE_PARTITIONS | ||
672 | printk ("\npartitions = %d\n", ARRAY_SIZE(lart_partitions)); | 665 | printk ("\npartitions = %d\n", ARRAY_SIZE(lart_partitions)); |
673 | 666 | ||
674 | for (result = 0; result < ARRAY_SIZE(lart_partitions); result++) | 667 | for (result = 0; result < ARRAY_SIZE(lart_partitions); result++) |
@@ -681,25 +674,16 @@ static int __init lart_flash_init (void) | |||
681 | result,lart_partitions[result].offset, | 674 | result,lart_partitions[result].offset, |
682 | result,lart_partitions[result].size,lart_partitions[result].size / 1024); | 675 | result,lart_partitions[result].size,lart_partitions[result].size / 1024); |
683 | #endif | 676 | #endif |
684 | #endif | ||
685 | 677 | ||
686 | #ifndef HAVE_PARTITIONS | ||
687 | result = mtd_device_register(&mtd, NULL, 0); | ||
688 | #else | ||
689 | result = mtd_device_register(&mtd, lart_partitions, | 678 | result = mtd_device_register(&mtd, lart_partitions, |
690 | ARRAY_SIZE(lart_partitions)); | 679 | ARRAY_SIZE(lart_partitions)); |
691 | #endif | ||
692 | 680 | ||
693 | return (result); | 681 | return (result); |
694 | } | 682 | } |
695 | 683 | ||
696 | static void __exit lart_flash_exit (void) | 684 | static void __exit lart_flash_exit (void) |
697 | { | 685 | { |
698 | #ifndef HAVE_PARTITIONS | ||
699 | mtd_device_unregister(&mtd); | ||
700 | #else | ||
701 | mtd_device_unregister(&mtd); | 686 | mtd_device_unregister(&mtd); |
702 | #endif | ||
703 | } | 687 | } |
704 | 688 | ||
705 | module_init (lart_flash_init); | 689 | module_init (lart_flash_init); |
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 35180e475c4c..884904d3f9d2 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/mtd/cfi.h> | 30 | #include <linux/mtd/cfi.h> |
31 | #include <linux/mtd/mtd.h> | 31 | #include <linux/mtd/mtd.h> |
32 | #include <linux/mtd/partitions.h> | 32 | #include <linux/mtd/partitions.h> |
33 | #include <linux/of_platform.h> | ||
33 | 34 | ||
34 | #include <linux/spi/spi.h> | 35 | #include <linux/spi/spi.h> |
35 | #include <linux/spi/flash.h> | 36 | #include <linux/spi/flash.h> |
@@ -88,7 +89,6 @@ struct m25p { | |||
88 | struct spi_device *spi; | 89 | struct spi_device *spi; |
89 | struct mutex lock; | 90 | struct mutex lock; |
90 | struct mtd_info mtd; | 91 | struct mtd_info mtd; |
91 | unsigned partitioned:1; | ||
92 | u16 page_size; | 92 | u16 page_size; |
93 | u16 addr_width; | 93 | u16 addr_width; |
94 | u8 erase_opcode; | 94 | u8 erase_opcode; |
@@ -209,9 +209,8 @@ static int wait_till_ready(struct m25p *flash) | |||
209 | */ | 209 | */ |
210 | static int erase_chip(struct m25p *flash) | 210 | static int erase_chip(struct m25p *flash) |
211 | { | 211 | { |
212 | DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %lldKiB\n", | 212 | pr_debug("%s: %s %lldKiB\n", dev_name(&flash->spi->dev), __func__, |
213 | dev_name(&flash->spi->dev), __func__, | 213 | (long long)(flash->mtd.size >> 10)); |
214 | (long long)(flash->mtd.size >> 10)); | ||
215 | 214 | ||
216 | /* Wait until finished previous write command. */ | 215 | /* Wait until finished previous write command. */ |
217 | if (wait_till_ready(flash)) | 216 | if (wait_till_ready(flash)) |
@@ -250,9 +249,8 @@ static int m25p_cmdsz(struct m25p *flash) | |||
250 | */ | 249 | */ |
251 | static int erase_sector(struct m25p *flash, u32 offset) | 250 | static int erase_sector(struct m25p *flash, u32 offset) |
252 | { | 251 | { |
253 | DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n", | 252 | pr_debug("%s: %s %dKiB at 0x%08x\n", dev_name(&flash->spi->dev), |
254 | dev_name(&flash->spi->dev), __func__, | 253 | __func__, flash->mtd.erasesize / 1024, offset); |
255 | flash->mtd.erasesize / 1024, offset); | ||
256 | 254 | ||
257 | /* Wait until finished previous write command. */ | 255 | /* Wait until finished previous write command. */ |
258 | if (wait_till_ready(flash)) | 256 | if (wait_till_ready(flash)) |
@@ -286,9 +284,9 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
286 | u32 addr,len; | 284 | u32 addr,len; |
287 | uint32_t rem; | 285 | uint32_t rem; |
288 | 286 | ||
289 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%llx, len %lld\n", | 287 | pr_debug("%s: %s at 0x%llx, len %lld\n", dev_name(&flash->spi->dev), |
290 | dev_name(&flash->spi->dev), __func__, "at", | 288 | __func__, (long long)instr->addr, |
291 | (long long)instr->addr, (long long)instr->len); | 289 | (long long)instr->len); |
292 | 290 | ||
293 | /* sanity checks */ | 291 | /* sanity checks */ |
294 | if (instr->addr + instr->len > flash->mtd.size) | 292 | if (instr->addr + instr->len > flash->mtd.size) |
@@ -348,9 +346,8 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
348 | struct spi_transfer t[2]; | 346 | struct spi_transfer t[2]; |
349 | struct spi_message m; | 347 | struct spi_message m; |
350 | 348 | ||
351 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", | 349 | pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev), |
352 | dev_name(&flash->spi->dev), __func__, "from", | 350 | __func__, (u32)from, len); |
353 | (u32)from, len); | ||
354 | 351 | ||
355 | /* sanity checks */ | 352 | /* sanity checks */ |
356 | if (!len) | 353 | if (!len) |
@@ -417,9 +414,8 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
417 | struct spi_transfer t[2]; | 414 | struct spi_transfer t[2]; |
418 | struct spi_message m; | 415 | struct spi_message m; |
419 | 416 | ||
420 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", | 417 | pr_debug("%s: %s to 0x%08x, len %zd\n", dev_name(&flash->spi->dev), |
421 | dev_name(&flash->spi->dev), __func__, "to", | 418 | __func__, (u32)to, len); |
422 | (u32)to, len); | ||
423 | 419 | ||
424 | *retlen = 0; | 420 | *retlen = 0; |
425 | 421 | ||
@@ -510,9 +506,8 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
510 | size_t actual; | 506 | size_t actual; |
511 | int cmd_sz, ret; | 507 | int cmd_sz, ret; |
512 | 508 | ||
513 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", | 509 | pr_debug("%s: %s to 0x%08x, len %zd\n", dev_name(&flash->spi->dev), |
514 | dev_name(&flash->spi->dev), __func__, "to", | 510 | __func__, (u32)to, len); |
515 | (u32)to, len); | ||
516 | 511 | ||
517 | *retlen = 0; | 512 | *retlen = 0; |
518 | 513 | ||
@@ -661,6 +656,7 @@ static const struct spi_device_id m25p_ids[] = { | |||
661 | { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K) }, | 656 | { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K) }, |
662 | 657 | ||
663 | { "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K) }, | 658 | { "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K) }, |
659 | { "at25df321a", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) }, | ||
664 | { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) }, | 660 | { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) }, |
665 | 661 | ||
666 | { "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) }, | 662 | { "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) }, |
@@ -671,6 +667,7 @@ static const struct spi_device_id m25p_ids[] = { | |||
671 | /* EON -- en25xxx */ | 667 | /* EON -- en25xxx */ |
672 | { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) }, | 668 | { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) }, |
673 | { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) }, | 669 | { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) }, |
670 | { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) }, | ||
674 | { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, | 671 | { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, |
675 | 672 | ||
676 | /* Intel/Numonyx -- xxxs33b */ | 673 | /* Intel/Numonyx -- xxxs33b */ |
@@ -788,8 +785,8 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi) | |||
788 | */ | 785 | */ |
789 | tmp = spi_write_then_read(spi, &code, 1, id, 5); | 786 | tmp = spi_write_then_read(spi, &code, 1, id, 5); |
790 | if (tmp < 0) { | 787 | if (tmp < 0) { |
791 | DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n", | 788 | pr_debug("%s: error %d reading JEDEC ID\n", |
792 | dev_name(&spi->dev), tmp); | 789 | dev_name(&spi->dev), tmp); |
793 | return ERR_PTR(tmp); | 790 | return ERR_PTR(tmp); |
794 | } | 791 | } |
795 | jedec = id[0]; | 792 | jedec = id[0]; |
@@ -825,8 +822,12 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
825 | struct m25p *flash; | 822 | struct m25p *flash; |
826 | struct flash_info *info; | 823 | struct flash_info *info; |
827 | unsigned i; | 824 | unsigned i; |
828 | struct mtd_partition *parts = NULL; | 825 | struct mtd_part_parser_data ppdata; |
829 | int nr_parts = 0; | 826 | |
827 | #ifdef CONFIG_MTD_OF_PARTS | ||
828 | if (!of_device_is_available(spi->dev.of_node)) | ||
829 | return -ENODEV; | ||
830 | #endif | ||
830 | 831 | ||
831 | /* Platform data helps sort out which chip type we have, as | 832 | /* Platform data helps sort out which chip type we have, as |
832 | * well as how this board partitions it. If we don't have | 833 | * well as how this board partitions it. If we don't have |
@@ -928,6 +929,7 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
928 | if (info->flags & M25P_NO_ERASE) | 929 | if (info->flags & M25P_NO_ERASE) |
929 | flash->mtd.flags |= MTD_NO_ERASE; | 930 | flash->mtd.flags |= MTD_NO_ERASE; |
930 | 931 | ||
932 | ppdata.of_node = spi->dev.of_node; | ||
931 | flash->mtd.dev.parent = &spi->dev; | 933 | flash->mtd.dev.parent = &spi->dev; |
932 | flash->page_size = info->page_size; | 934 | flash->page_size = info->page_size; |
933 | 935 | ||
@@ -945,8 +947,7 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
945 | dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name, | 947 | dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name, |
946 | (long long)flash->mtd.size >> 10); | 948 | (long long)flash->mtd.size >> 10); |
947 | 949 | ||
948 | DEBUG(MTD_DEBUG_LEVEL2, | 950 | pr_debug("mtd .name = %s, .size = 0x%llx (%lldMiB) " |
949 | "mtd .name = %s, .size = 0x%llx (%lldMiB) " | ||
950 | ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n", | 951 | ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n", |
951 | flash->mtd.name, | 952 | flash->mtd.name, |
952 | (long long)flash->mtd.size, (long long)(flash->mtd.size >> 20), | 953 | (long long)flash->mtd.size, (long long)(flash->mtd.size >> 20), |
@@ -955,8 +956,7 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
955 | 956 | ||
956 | if (flash->mtd.numeraseregions) | 957 | if (flash->mtd.numeraseregions) |
957 | for (i = 0; i < flash->mtd.numeraseregions; i++) | 958 | for (i = 0; i < flash->mtd.numeraseregions; i++) |
958 | DEBUG(MTD_DEBUG_LEVEL2, | 959 | pr_debug("mtd.eraseregions[%d] = { .offset = 0x%llx, " |
959 | "mtd.eraseregions[%d] = { .offset = 0x%llx, " | ||
960 | ".erasesize = 0x%.8x (%uKiB), " | 960 | ".erasesize = 0x%.8x (%uKiB), " |
961 | ".numblocks = %d }\n", | 961 | ".numblocks = %d }\n", |
962 | i, (long long)flash->mtd.eraseregions[i].offset, | 962 | i, (long long)flash->mtd.eraseregions[i].offset, |
@@ -968,41 +968,9 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
968 | /* partitions should match sector boundaries; and it may be good to | 968 | /* partitions should match sector boundaries; and it may be good to |
969 | * use readonly partitions for writeprotected sectors (BP2..BP0). | 969 | * use readonly partitions for writeprotected sectors (BP2..BP0). |
970 | */ | 970 | */ |
971 | if (mtd_has_cmdlinepart()) { | 971 | return mtd_device_parse_register(&flash->mtd, NULL, &ppdata, |
972 | static const char *part_probes[] | 972 | data ? data->parts : NULL, |
973 | = { "cmdlinepart", NULL, }; | 973 | data ? data->nr_parts : 0); |
974 | |||
975 | nr_parts = parse_mtd_partitions(&flash->mtd, | ||
976 | part_probes, &parts, 0); | ||
977 | } | ||
978 | |||
979 | if (nr_parts <= 0 && data && data->parts) { | ||
980 | parts = data->parts; | ||
981 | nr_parts = data->nr_parts; | ||
982 | } | ||
983 | |||
984 | #ifdef CONFIG_MTD_OF_PARTS | ||
985 | if (nr_parts <= 0 && spi->dev.of_node) { | ||
986 | nr_parts = of_mtd_parse_partitions(&spi->dev, | ||
987 | spi->dev.of_node, &parts); | ||
988 | } | ||
989 | #endif | ||
990 | |||
991 | if (nr_parts > 0) { | ||
992 | for (i = 0; i < nr_parts; i++) { | ||
993 | DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = " | ||
994 | "{.name = %s, .offset = 0x%llx, " | ||
995 | ".size = 0x%llx (%lldKiB) }\n", | ||
996 | i, parts[i].name, | ||
997 | (long long)parts[i].offset, | ||
998 | (long long)parts[i].size, | ||
999 | (long long)(parts[i].size >> 10)); | ||
1000 | } | ||
1001 | flash->partitioned = 1; | ||
1002 | } | ||
1003 | |||
1004 | return mtd_device_register(&flash->mtd, parts, nr_parts) == 1 ? | ||
1005 | -ENODEV : 0; | ||
1006 | } | 974 | } |
1007 | 975 | ||
1008 | 976 | ||
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index 13749d458a31..d75c7af18a63 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <linux/mutex.h> | 17 | #include <linux/mutex.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/math64.h> | 19 | #include <linux/math64.h> |
20 | #include <linux/of.h> | ||
21 | #include <linux/of_device.h> | ||
20 | 22 | ||
21 | #include <linux/spi/spi.h> | 23 | #include <linux/spi/spi.h> |
22 | #include <linux/spi/flash.h> | 24 | #include <linux/spi/flash.h> |
@@ -24,7 +26,6 @@ | |||
24 | #include <linux/mtd/mtd.h> | 26 | #include <linux/mtd/mtd.h> |
25 | #include <linux/mtd/partitions.h> | 27 | #include <linux/mtd/partitions.h> |
26 | 28 | ||
27 | |||
28 | /* | 29 | /* |
29 | * DataFlash is a kind of SPI flash. Most AT45 chips have two buffers in | 30 | * DataFlash is a kind of SPI flash. Most AT45 chips have two buffers in |
30 | * each chip, which may be used for double buffered I/O; but this driver | 31 | * each chip, which may be used for double buffered I/O; but this driver |
@@ -98,6 +99,16 @@ struct dataflash { | |||
98 | struct mtd_info mtd; | 99 | struct mtd_info mtd; |
99 | }; | 100 | }; |
100 | 101 | ||
102 | #ifdef CONFIG_OF | ||
103 | static const struct of_device_id dataflash_dt_ids[] = { | ||
104 | { .compatible = "atmel,at45", }, | ||
105 | { .compatible = "atmel,dataflash", }, | ||
106 | { /* sentinel */ } | ||
107 | }; | ||
108 | #else | ||
109 | #define dataflash_dt_ids NULL | ||
110 | #endif | ||
111 | |||
101 | /* ......................................................................... */ | 112 | /* ......................................................................... */ |
102 | 113 | ||
103 | /* | 114 | /* |
@@ -122,7 +133,7 @@ static int dataflash_waitready(struct spi_device *spi) | |||
122 | for (;;) { | 133 | for (;;) { |
123 | status = dataflash_status(spi); | 134 | status = dataflash_status(spi); |
124 | if (status < 0) { | 135 | if (status < 0) { |
125 | DEBUG(MTD_DEBUG_LEVEL1, "%s: status %d?\n", | 136 | pr_debug("%s: status %d?\n", |
126 | dev_name(&spi->dev), status); | 137 | dev_name(&spi->dev), status); |
127 | status = 0; | 138 | status = 0; |
128 | } | 139 | } |
@@ -149,7 +160,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
149 | uint8_t *command; | 160 | uint8_t *command; |
150 | uint32_t rem; | 161 | uint32_t rem; |
151 | 162 | ||
152 | DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%llx len 0x%llx\n", | 163 | pr_debug("%s: erase addr=0x%llx len 0x%llx\n", |
153 | dev_name(&spi->dev), (long long)instr->addr, | 164 | dev_name(&spi->dev), (long long)instr->addr, |
154 | (long long)instr->len); | 165 | (long long)instr->len); |
155 | 166 | ||
@@ -187,7 +198,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
187 | command[2] = (uint8_t)(pageaddr >> 8); | 198 | command[2] = (uint8_t)(pageaddr >> 8); |
188 | command[3] = 0; | 199 | command[3] = 0; |
189 | 200 | ||
190 | DEBUG(MTD_DEBUG_LEVEL3, "ERASE %s: (%x) %x %x %x [%i]\n", | 201 | pr_debug("ERASE %s: (%x) %x %x %x [%i]\n", |
191 | do_block ? "block" : "page", | 202 | do_block ? "block" : "page", |
192 | command[0], command[1], command[2], command[3], | 203 | command[0], command[1], command[2], command[3], |
193 | pageaddr); | 204 | pageaddr); |
@@ -238,8 +249,8 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
238 | uint8_t *command; | 249 | uint8_t *command; |
239 | int status; | 250 | int status; |
240 | 251 | ||
241 | DEBUG(MTD_DEBUG_LEVEL2, "%s: read 0x%x..0x%x\n", | 252 | pr_debug("%s: read 0x%x..0x%x\n", dev_name(&priv->spi->dev), |
242 | dev_name(&priv->spi->dev), (unsigned)from, (unsigned)(from + len)); | 253 | (unsigned)from, (unsigned)(from + len)); |
243 | 254 | ||
244 | *retlen = 0; | 255 | *retlen = 0; |
245 | 256 | ||
@@ -255,7 +266,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
255 | 266 | ||
256 | command = priv->command; | 267 | command = priv->command; |
257 | 268 | ||
258 | DEBUG(MTD_DEBUG_LEVEL3, "READ: (%x) %x %x %x\n", | 269 | pr_debug("READ: (%x) %x %x %x\n", |
259 | command[0], command[1], command[2], command[3]); | 270 | command[0], command[1], command[2], command[3]); |
260 | 271 | ||
261 | spi_message_init(&msg); | 272 | spi_message_init(&msg); |
@@ -287,7 +298,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
287 | *retlen = msg.actual_length - 8; | 298 | *retlen = msg.actual_length - 8; |
288 | status = 0; | 299 | status = 0; |
289 | } else | 300 | } else |
290 | DEBUG(MTD_DEBUG_LEVEL1, "%s: read %x..%x --> %d\n", | 301 | pr_debug("%s: read %x..%x --> %d\n", |
291 | dev_name(&priv->spi->dev), | 302 | dev_name(&priv->spi->dev), |
292 | (unsigned)from, (unsigned)(from + len), | 303 | (unsigned)from, (unsigned)(from + len), |
293 | status); | 304 | status); |
@@ -314,7 +325,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
314 | int status = -EINVAL; | 325 | int status = -EINVAL; |
315 | uint8_t *command; | 326 | uint8_t *command; |
316 | 327 | ||
317 | DEBUG(MTD_DEBUG_LEVEL2, "%s: write 0x%x..0x%x\n", | 328 | pr_debug("%s: write 0x%x..0x%x\n", |
318 | dev_name(&spi->dev), (unsigned)to, (unsigned)(to + len)); | 329 | dev_name(&spi->dev), (unsigned)to, (unsigned)(to + len)); |
319 | 330 | ||
320 | *retlen = 0; | 331 | *retlen = 0; |
@@ -340,7 +351,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
340 | 351 | ||
341 | mutex_lock(&priv->lock); | 352 | mutex_lock(&priv->lock); |
342 | while (remaining > 0) { | 353 | while (remaining > 0) { |
343 | DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n", | 354 | pr_debug("write @ %i:%i len=%i\n", |
344 | pageaddr, offset, writelen); | 355 | pageaddr, offset, writelen); |
345 | 356 | ||
346 | /* REVISIT: | 357 | /* REVISIT: |
@@ -368,12 +379,12 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
368 | command[2] = (addr & 0x0000FF00) >> 8; | 379 | command[2] = (addr & 0x0000FF00) >> 8; |
369 | command[3] = 0; | 380 | command[3] = 0; |
370 | 381 | ||
371 | DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n", | 382 | pr_debug("TRANSFER: (%x) %x %x %x\n", |
372 | command[0], command[1], command[2], command[3]); | 383 | command[0], command[1], command[2], command[3]); |
373 | 384 | ||
374 | status = spi_sync(spi, &msg); | 385 | status = spi_sync(spi, &msg); |
375 | if (status < 0) | 386 | if (status < 0) |
376 | DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n", | 387 | pr_debug("%s: xfer %u -> %d\n", |
377 | dev_name(&spi->dev), addr, status); | 388 | dev_name(&spi->dev), addr, status); |
378 | 389 | ||
379 | (void) dataflash_waitready(priv->spi); | 390 | (void) dataflash_waitready(priv->spi); |
@@ -386,7 +397,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
386 | command[2] = (addr & 0x0000FF00) >> 8; | 397 | command[2] = (addr & 0x0000FF00) >> 8; |
387 | command[3] = (addr & 0x000000FF); | 398 | command[3] = (addr & 0x000000FF); |
388 | 399 | ||
389 | DEBUG(MTD_DEBUG_LEVEL3, "PROGRAM: (%x) %x %x %x\n", | 400 | pr_debug("PROGRAM: (%x) %x %x %x\n", |
390 | command[0], command[1], command[2], command[3]); | 401 | command[0], command[1], command[2], command[3]); |
391 | 402 | ||
392 | x[1].tx_buf = writebuf; | 403 | x[1].tx_buf = writebuf; |
@@ -395,7 +406,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
395 | status = spi_sync(spi, &msg); | 406 | status = spi_sync(spi, &msg); |
396 | spi_transfer_del(x + 1); | 407 | spi_transfer_del(x + 1); |
397 | if (status < 0) | 408 | if (status < 0) |
398 | DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n", | 409 | pr_debug("%s: pgm %u/%u -> %d\n", |
399 | dev_name(&spi->dev), addr, writelen, status); | 410 | dev_name(&spi->dev), addr, writelen, status); |
400 | 411 | ||
401 | (void) dataflash_waitready(priv->spi); | 412 | (void) dataflash_waitready(priv->spi); |
@@ -410,12 +421,12 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
410 | command[2] = (addr & 0x0000FF00) >> 8; | 421 | command[2] = (addr & 0x0000FF00) >> 8; |
411 | command[3] = 0; | 422 | command[3] = 0; |
412 | 423 | ||
413 | DEBUG(MTD_DEBUG_LEVEL3, "COMPARE: (%x) %x %x %x\n", | 424 | pr_debug("COMPARE: (%x) %x %x %x\n", |
414 | command[0], command[1], command[2], command[3]); | 425 | command[0], command[1], command[2], command[3]); |
415 | 426 | ||
416 | status = spi_sync(spi, &msg); | 427 | status = spi_sync(spi, &msg); |
417 | if (status < 0) | 428 | if (status < 0) |
418 | DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n", | 429 | pr_debug("%s: compare %u -> %d\n", |
419 | dev_name(&spi->dev), addr, status); | 430 | dev_name(&spi->dev), addr, status); |
420 | 431 | ||
421 | status = dataflash_waitready(priv->spi); | 432 | status = dataflash_waitready(priv->spi); |
@@ -634,11 +645,10 @@ add_dataflash_otp(struct spi_device *spi, char *name, | |||
634 | { | 645 | { |
635 | struct dataflash *priv; | 646 | struct dataflash *priv; |
636 | struct mtd_info *device; | 647 | struct mtd_info *device; |
648 | struct mtd_part_parser_data ppdata; | ||
637 | struct flash_platform_data *pdata = spi->dev.platform_data; | 649 | struct flash_platform_data *pdata = spi->dev.platform_data; |
638 | char *otp_tag = ""; | 650 | char *otp_tag = ""; |
639 | int err = 0; | 651 | int err = 0; |
640 | struct mtd_partition *parts; | ||
641 | int nr_parts = 0; | ||
642 | 652 | ||
643 | priv = kzalloc(sizeof *priv, GFP_KERNEL); | 653 | priv = kzalloc(sizeof *priv, GFP_KERNEL); |
644 | if (!priv) | 654 | if (!priv) |
@@ -677,28 +687,11 @@ add_dataflash_otp(struct spi_device *spi, char *name, | |||
677 | pagesize, otp_tag); | 687 | pagesize, otp_tag); |
678 | dev_set_drvdata(&spi->dev, priv); | 688 | dev_set_drvdata(&spi->dev, priv); |
679 | 689 | ||
680 | if (mtd_has_cmdlinepart()) { | 690 | ppdata.of_node = spi->dev.of_node; |
681 | static const char *part_probes[] = { "cmdlinepart", NULL, }; | 691 | err = mtd_device_parse_register(device, NULL, &ppdata, |
682 | 692 | pdata ? pdata->parts : NULL, | |
683 | nr_parts = parse_mtd_partitions(device, part_probes, &parts, | 693 | pdata ? pdata->nr_parts : 0); |
684 | 0); | ||
685 | } | ||
686 | 694 | ||
687 | if (nr_parts <= 0 && pdata && pdata->parts) { | ||
688 | parts = pdata->parts; | ||
689 | nr_parts = pdata->nr_parts; | ||
690 | } | ||
691 | |||
692 | if (nr_parts > 0) { | ||
693 | priv->partitioned = 1; | ||
694 | err = mtd_device_register(device, parts, nr_parts); | ||
695 | goto out; | ||
696 | } | ||
697 | |||
698 | if (mtd_device_register(device, NULL, 0) == 1) | ||
699 | err = -ENODEV; | ||
700 | |||
701 | out: | ||
702 | if (!err) | 695 | if (!err) |
703 | return 0; | 696 | return 0; |
704 | 697 | ||
@@ -787,7 +780,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi) | |||
787 | */ | 780 | */ |
788 | tmp = spi_write_then_read(spi, &code, 1, id, 3); | 781 | tmp = spi_write_then_read(spi, &code, 1, id, 3); |
789 | if (tmp < 0) { | 782 | if (tmp < 0) { |
790 | DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n", | 783 | pr_debug("%s: error %d reading JEDEC ID\n", |
791 | dev_name(&spi->dev), tmp); | 784 | dev_name(&spi->dev), tmp); |
792 | return ERR_PTR(tmp); | 785 | return ERR_PTR(tmp); |
793 | } | 786 | } |
@@ -804,7 +797,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi) | |||
804 | tmp < ARRAY_SIZE(dataflash_data); | 797 | tmp < ARRAY_SIZE(dataflash_data); |
805 | tmp++, info++) { | 798 | tmp++, info++) { |
806 | if (info->jedec_id == jedec) { | 799 | if (info->jedec_id == jedec) { |
807 | DEBUG(MTD_DEBUG_LEVEL1, "%s: OTP, sector protect%s\n", | 800 | pr_debug("%s: OTP, sector protect%s\n", |
808 | dev_name(&spi->dev), | 801 | dev_name(&spi->dev), |
809 | (info->flags & SUP_POW2PS) | 802 | (info->flags & SUP_POW2PS) |
810 | ? ", binary pagesize" : "" | 803 | ? ", binary pagesize" : "" |
@@ -812,8 +805,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi) | |||
812 | if (info->flags & SUP_POW2PS) { | 805 | if (info->flags & SUP_POW2PS) { |
813 | status = dataflash_status(spi); | 806 | status = dataflash_status(spi); |
814 | if (status < 0) { | 807 | if (status < 0) { |
815 | DEBUG(MTD_DEBUG_LEVEL1, | 808 | pr_debug("%s: status error %d\n", |
816 | "%s: status error %d\n", | ||
817 | dev_name(&spi->dev), status); | 809 | dev_name(&spi->dev), status); |
818 | return ERR_PTR(status); | 810 | return ERR_PTR(status); |
819 | } | 811 | } |
@@ -878,7 +870,7 @@ static int __devinit dataflash_probe(struct spi_device *spi) | |||
878 | */ | 870 | */ |
879 | status = dataflash_status(spi); | 871 | status = dataflash_status(spi); |
880 | if (status <= 0 || status == 0xff) { | 872 | if (status <= 0 || status == 0xff) { |
881 | DEBUG(MTD_DEBUG_LEVEL1, "%s: status error %d\n", | 873 | pr_debug("%s: status error %d\n", |
882 | dev_name(&spi->dev), status); | 874 | dev_name(&spi->dev), status); |
883 | if (status == 0 || status == 0xff) | 875 | if (status == 0 || status == 0xff) |
884 | status = -ENODEV; | 876 | status = -ENODEV; |
@@ -914,14 +906,14 @@ static int __devinit dataflash_probe(struct spi_device *spi) | |||
914 | break; | 906 | break; |
915 | /* obsolete AT45DB1282 not (yet?) supported */ | 907 | /* obsolete AT45DB1282 not (yet?) supported */ |
916 | default: | 908 | default: |
917 | DEBUG(MTD_DEBUG_LEVEL1, "%s: unsupported device (%x)\n", | 909 | pr_debug("%s: unsupported device (%x)\n", dev_name(&spi->dev), |
918 | dev_name(&spi->dev), status & 0x3c); | 910 | status & 0x3c); |
919 | status = -ENODEV; | 911 | status = -ENODEV; |
920 | } | 912 | } |
921 | 913 | ||
922 | if (status < 0) | 914 | if (status < 0) |
923 | DEBUG(MTD_DEBUG_LEVEL1, "%s: add_dataflash --> %d\n", | 915 | pr_debug("%s: add_dataflash --> %d\n", dev_name(&spi->dev), |
924 | dev_name(&spi->dev), status); | 916 | status); |
925 | 917 | ||
926 | return status; | 918 | return status; |
927 | } | 919 | } |
@@ -931,7 +923,7 @@ static int __devexit dataflash_remove(struct spi_device *spi) | |||
931 | struct dataflash *flash = dev_get_drvdata(&spi->dev); | 923 | struct dataflash *flash = dev_get_drvdata(&spi->dev); |
932 | int status; | 924 | int status; |
933 | 925 | ||
934 | DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", dev_name(&spi->dev)); | 926 | pr_debug("%s: remove\n", dev_name(&spi->dev)); |
935 | 927 | ||
936 | status = mtd_device_unregister(&flash->mtd); | 928 | status = mtd_device_unregister(&flash->mtd); |
937 | if (status == 0) { | 929 | if (status == 0) { |
@@ -946,6 +938,7 @@ static struct spi_driver dataflash_driver = { | |||
946 | .name = "mtd_dataflash", | 938 | .name = "mtd_dataflash", |
947 | .bus = &spi_bus_type, | 939 | .bus = &spi_bus_type, |
948 | .owner = THIS_MODULE, | 940 | .owner = THIS_MODULE, |
941 | .of_match_table = dataflash_dt_ids, | ||
949 | }, | 942 | }, |
950 | 943 | ||
951 | .probe = dataflash_probe, | 944 | .probe = dataflash_probe, |
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c index 83e80c65d6e7..d38ef3bffe8d 100644 --- a/drivers/mtd/devices/sst25l.c +++ b/drivers/mtd/devices/sst25l.c | |||
@@ -52,8 +52,6 @@ struct sst25l_flash { | |||
52 | struct spi_device *spi; | 52 | struct spi_device *spi; |
53 | struct mutex lock; | 53 | struct mutex lock; |
54 | struct mtd_info mtd; | 54 | struct mtd_info mtd; |
55 | |||
56 | int partitioned; | ||
57 | }; | 55 | }; |
58 | 56 | ||
59 | struct flash_info { | 57 | struct flash_info { |
@@ -381,8 +379,6 @@ static int __devinit sst25l_probe(struct spi_device *spi) | |||
381 | struct sst25l_flash *flash; | 379 | struct sst25l_flash *flash; |
382 | struct flash_platform_data *data; | 380 | struct flash_platform_data *data; |
383 | int ret, i; | 381 | int ret, i; |
384 | struct mtd_partition *parts = NULL; | ||
385 | int nr_parts = 0; | ||
386 | 382 | ||
387 | flash_info = sst25l_match_device(spi); | 383 | flash_info = sst25l_match_device(spi); |
388 | if (!flash_info) | 384 | if (!flash_info) |
@@ -414,8 +410,7 @@ static int __devinit sst25l_probe(struct spi_device *spi) | |||
414 | dev_info(&spi->dev, "%s (%lld KiB)\n", flash_info->name, | 410 | dev_info(&spi->dev, "%s (%lld KiB)\n", flash_info->name, |
415 | (long long)flash->mtd.size >> 10); | 411 | (long long)flash->mtd.size >> 10); |
416 | 412 | ||
417 | DEBUG(MTD_DEBUG_LEVEL2, | 413 | pr_debug("mtd .name = %s, .size = 0x%llx (%lldMiB) " |
418 | "mtd .name = %s, .size = 0x%llx (%lldMiB) " | ||
419 | ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n", | 414 | ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n", |
420 | flash->mtd.name, | 415 | flash->mtd.name, |
421 | (long long)flash->mtd.size, (long long)(flash->mtd.size >> 20), | 416 | (long long)flash->mtd.size, (long long)(flash->mtd.size >> 20), |
@@ -423,37 +418,10 @@ static int __devinit sst25l_probe(struct spi_device *spi) | |||
423 | flash->mtd.numeraseregions); | 418 | flash->mtd.numeraseregions); |
424 | 419 | ||
425 | 420 | ||
426 | if (mtd_has_cmdlinepart()) { | 421 | ret = mtd_device_parse_register(&flash->mtd, NULL, 0, |
427 | static const char *part_probes[] = {"cmdlinepart", NULL}; | 422 | data ? data->parts : NULL, |
428 | 423 | data ? data->nr_parts : 0); | |
429 | nr_parts = parse_mtd_partitions(&flash->mtd, | 424 | if (ret) { |
430 | part_probes, | ||
431 | &parts, 0); | ||
432 | } | ||
433 | |||
434 | if (nr_parts <= 0 && data && data->parts) { | ||
435 | parts = data->parts; | ||
436 | nr_parts = data->nr_parts; | ||
437 | } | ||
438 | |||
439 | if (nr_parts > 0) { | ||
440 | for (i = 0; i < nr_parts; i++) { | ||
441 | DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = " | ||
442 | "{.name = %s, .offset = 0x%llx, " | ||
443 | ".size = 0x%llx (%lldKiB) }\n", | ||
444 | i, parts[i].name, | ||
445 | (long long)parts[i].offset, | ||
446 | (long long)parts[i].size, | ||
447 | (long long)(parts[i].size >> 10)); | ||
448 | } | ||
449 | |||
450 | flash->partitioned = 1; | ||
451 | return mtd_device_register(&flash->mtd, parts, | ||
452 | nr_parts); | ||
453 | } | ||
454 | |||
455 | ret = mtd_device_register(&flash->mtd, NULL, 0); | ||
456 | if (ret == 1) { | ||
457 | kfree(flash); | 425 | kfree(flash); |
458 | dev_set_drvdata(&spi->dev, NULL); | 426 | dev_set_drvdata(&spi->dev, NULL); |
459 | return -ENODEV; | 427 | return -ENODEV; |