diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-01 19:55:42 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-01 19:55:42 -0400 |
commit | f5e7e844a571124ffc117d4696787d6afc4fc5ae (patch) | |
tree | 26bb17dc94e9536da540c187b00cedb0c1b24664 | |
parent | 48445159e9ecb44a96a4de06c6ae7c54eb43ba5b (diff) | |
parent | 4a43faf54e9173b6acce37cf7f053fc9515a2cdf (diff) |
Merge tag 'for-linus-3.5-20120601' of git://git.infradead.org/linux-mtd
Pull mtd update from David Woodhouse:
- More robust parsing especially of xattr data in JFFS2
- Updates to mxc_nand and gpmi drivers to support new boards and device tree
- Improve consistency of information about ECC strength in NAND devices
- Clean up partition handling of plat_nand
- Support NAND drivers without dedicated access to OOB area
- BCH hardware ECC support for OMAP
- Other fixes and cleanups, and a few new device IDs
Fixed trivial conflict in drivers/mtd/nand/gpmi-nand/gpmi-nand.c due to
added include files next to each other.
* tag 'for-linus-3.5-20120601' of git://git.infradead.org/linux-mtd: (75 commits)
mtd: mxc_nand: move ecc strengh setup before nand_scan_tail
mtd: block2mtd: fix recursive call of mtd_writev
mtd: gpmi-nand: define ecc.strength
mtd: of_parts: fix breakage in Kconfig
mtd: nand: fix scan_read_raw_oob
mtd: docg3 fix in-middle of blocks reads
mtd: cfi_cmdset_0002: Slight cleanup of fixup messages
mtd: add fixup for S29NS512P NOR flash.
jffs2: allow to complete xattr integrity check on first GC scan
jffs2: allow to discriminate between recoverable and non-recoverable errors
mtd: nand: omap: add support for hardware BCH ecc
ARM: OMAP3: gpmc: add BCH ecc api and modes
mtd: nand: check the return code of 'read_oob/read_oob_raw'
mtd: nand: remove 'sndcmd' parameter of 'read_oob/read_oob_raw'
mtd: m25p80: Add support for Winbond W25Q80BW
jffs2: get rid of jffs2_sync_super
jffs2: remove unnecessary GC pass on sync
jffs2: remove unnecessary GC pass on umount
jffs2: remove lock_super
mtd: gpmi: add gpmi support for mx6q
...
86 files changed, 1775 insertions, 792 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-mtd b/Documentation/ABI/testing/sysfs-class-mtd index 4d55a1888981..db1ad7e34fc3 100644 --- a/Documentation/ABI/testing/sysfs-class-mtd +++ b/Documentation/ABI/testing/sysfs-class-mtd | |||
@@ -123,3 +123,54 @@ Description: | |||
123 | half page, or a quarter page). | 123 | half page, or a quarter page). |
124 | 124 | ||
125 | In the case of ECC NOR, it is the ECC block size. | 125 | In the case of ECC NOR, it is the ECC block size. |
126 | |||
127 | What: /sys/class/mtd/mtdX/ecc_strength | ||
128 | Date: April 2012 | ||
129 | KernelVersion: 3.4 | ||
130 | Contact: linux-mtd@lists.infradead.org | ||
131 | Description: | ||
132 | Maximum number of bit errors that the device is capable of | ||
133 | correcting within each region covering an ecc step. This will | ||
134 | always be a non-negative integer. Note that some devices will | ||
135 | have multiple ecc steps within each writesize region. | ||
136 | |||
137 | In the case of devices lacking any ECC capability, it is 0. | ||
138 | |||
139 | What: /sys/class/mtd/mtdX/bitflip_threshold | ||
140 | Date: April 2012 | ||
141 | KernelVersion: 3.4 | ||
142 | Contact: linux-mtd@lists.infradead.org | ||
143 | Description: | ||
144 | This allows the user to examine and adjust the criteria by which | ||
145 | mtd returns -EUCLEAN from mtd_read(). If the maximum number of | ||
146 | bit errors that were corrected on any single region comprising | ||
147 | an ecc step (as reported by the driver) equals or exceeds this | ||
148 | value, -EUCLEAN is returned. Otherwise, absent an error, 0 is | ||
149 | returned. Higher layers (e.g., UBI) use this return code as an | ||
150 | indication that an erase block may be degrading and should be | ||
151 | scrutinized as a candidate for being marked as bad. | ||
152 | |||
153 | The initial value may be specified by the flash device driver. | ||
154 | If not, then the default value is ecc_strength. | ||
155 | |||
156 | The introduction of this feature brings a subtle change to the | ||
157 | meaning of the -EUCLEAN return code. Previously, it was | ||
158 | interpreted to mean simply "one or more bit errors were | ||
159 | corrected". Its new interpretation can be phrased as "a | ||
160 | dangerously high number of bit errors were corrected on one or | ||
161 | more regions comprising an ecc step". The precise definition of | ||
162 | "dangerously high" can be adjusted by the user with | ||
163 | bitflip_threshold. Users are discouraged from doing this, | ||
164 | however, unless they know what they are doing and have intimate | ||
165 | knowledge of the properties of their device. Broadly speaking, | ||
166 | bitflip_threshold should be low enough to detect genuine erase | ||
167 | block degradation, but high enough to avoid the consequences of | ||
168 | a persistent return value of -EUCLEAN on devices where sticky | ||
169 | bitflips occur. Note that if bitflip_threshold exceeds | ||
170 | ecc_strength, -EUCLEAN is never returned by mtd_read(). | ||
171 | Conversely, if bitflip_threshold is zero, -EUCLEAN is always | ||
172 | returned, absent a hard error. | ||
173 | |||
174 | This is generally applicable only to NAND flash devices with ECC | ||
175 | capability. It is ignored on devices lacking ECC capability; | ||
176 | i.e., devices for which ecc_strength is zero. | ||
diff --git a/Documentation/DocBook/mtdnand.tmpl b/Documentation/DocBook/mtdnand.tmpl index 0c674be0d3c6..e0aedb7a7827 100644 --- a/Documentation/DocBook/mtdnand.tmpl +++ b/Documentation/DocBook/mtdnand.tmpl | |||
@@ -1119,8 +1119,6 @@ in this page</entry> | |||
1119 | These constants are defined in nand.h. They are ored together to describe | 1119 | These constants are defined in nand.h. They are ored together to describe |
1120 | the chip functionality. | 1120 | the chip functionality. |
1121 | <programlisting> | 1121 | <programlisting> |
1122 | /* Chip can not auto increment pages */ | ||
1123 | #define NAND_NO_AUTOINCR 0x00000001 | ||
1124 | /* Buswitdh is 16 bit */ | 1122 | /* Buswitdh is 16 bit */ |
1125 | #define NAND_BUSWIDTH_16 0x00000002 | 1123 | #define NAND_BUSWIDTH_16 0x00000002 |
1126 | /* Device supports partial programming without padding */ | 1124 | /* Device supports partial programming without padding */ |
diff --git a/Documentation/devicetree/bindings/mtd/gpmi-nand.txt b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt new file mode 100644 index 000000000000..1a5bbd346d22 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt | |||
@@ -0,0 +1,33 @@ | |||
1 | * Freescale General-Purpose Media Interface (GPMI) | ||
2 | |||
3 | The GPMI nand controller provides an interface to control the | ||
4 | NAND flash chips. We support only one NAND chip now. | ||
5 | |||
6 | Required properties: | ||
7 | - compatible : should be "fsl,<chip>-gpmi-nand" | ||
8 | - reg : should contain registers location and length for gpmi and bch. | ||
9 | - reg-names: Should contain the reg names "gpmi-nand" and "bch" | ||
10 | - interrupts : The first is the DMA interrupt number for GPMI. | ||
11 | The second is the BCH interrupt number. | ||
12 | - interrupt-names : The interrupt names "gpmi-dma", "bch"; | ||
13 | - fsl,gpmi-dma-channel : Should contain the dma channel it uses. | ||
14 | |||
15 | The device tree may optionally contain sub-nodes describing partitions of the | ||
16 | address space. See partition.txt for more detail. | ||
17 | |||
18 | Examples: | ||
19 | |||
20 | gpmi-nand@8000c000 { | ||
21 | compatible = "fsl,imx28-gpmi-nand"; | ||
22 | #address-cells = <1>; | ||
23 | #size-cells = <1>; | ||
24 | reg = <0x8000c000 2000>, <0x8000a000 2000>; | ||
25 | reg-names = "gpmi-nand", "bch"; | ||
26 | interrupts = <88>, <41>; | ||
27 | interrupt-names = "gpmi-dma", "bch"; | ||
28 | fsl,gpmi-dma-channel = <4>; | ||
29 | |||
30 | partition@0 { | ||
31 | ... | ||
32 | }; | ||
33 | }; | ||
diff --git a/Documentation/devicetree/bindings/mtd/mxc-nand.txt b/Documentation/devicetree/bindings/mtd/mxc-nand.txt new file mode 100644 index 000000000000..b5833d11c7be --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/mxc-nand.txt | |||
@@ -0,0 +1,19 @@ | |||
1 | * Freescale's mxc_nand | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: "fsl,imxXX-nand" | ||
5 | - reg: address range of the nfc block | ||
6 | - interrupts: irq to be used | ||
7 | - nand-bus-width: see nand.txt | ||
8 | - nand-ecc-mode: see nand.txt | ||
9 | - nand-on-flash-bbt: see nand.txt | ||
10 | |||
11 | Example: | ||
12 | |||
13 | nand@d8000000 { | ||
14 | compatible = "fsl,imx27-nand"; | ||
15 | reg = <0xd8000000 0x1000>; | ||
16 | interrupts = <29>; | ||
17 | nand-bus-width = <8>; | ||
18 | nand-ecc-mode = "hw"; | ||
19 | }; | ||
diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi index 2b1a166d41f9..386c769c38d1 100644 --- a/arch/arm/boot/dts/imx27.dtsi +++ b/arch/arm/boot/dts/imx27.dtsi | |||
@@ -213,5 +213,14 @@ | |||
213 | status = "disabled"; | 213 | status = "disabled"; |
214 | }; | 214 | }; |
215 | }; | 215 | }; |
216 | nand@d8000000 { | ||
217 | #address-cells = <1>; | ||
218 | #size-cells = <1>; | ||
219 | |||
220 | compatible = "fsl,imx27-nand"; | ||
221 | reg = <0xd8000000 0x1000>; | ||
222 | interrupts = <29>; | ||
223 | status = "disabled"; | ||
224 | }; | ||
216 | }; | 225 | }; |
217 | }; | 226 | }; |
diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c index eb282378fa78..01abd3516a77 100644 --- a/arch/arm/mach-ep93xx/snappercl15.c +++ b/arch/arm/mach-ep93xx/snappercl15.c | |||
@@ -82,8 +82,6 @@ static int snappercl15_nand_dev_ready(struct mtd_info *mtd) | |||
82 | return !!(__raw_readw(NAND_CTRL_ADDR(chip)) & SNAPPERCL15_NAND_RDY); | 82 | return !!(__raw_readw(NAND_CTRL_ADDR(chip)) & SNAPPERCL15_NAND_RDY); |
83 | } | 83 | } |
84 | 84 | ||
85 | static const char *snappercl15_nand_part_probes[] = {"cmdlinepart", NULL}; | ||
86 | |||
87 | static struct mtd_partition snappercl15_nand_parts[] = { | 85 | static struct mtd_partition snappercl15_nand_parts[] = { |
88 | { | 86 | { |
89 | .name = "Kernel", | 87 | .name = "Kernel", |
@@ -100,10 +98,8 @@ static struct mtd_partition snappercl15_nand_parts[] = { | |||
100 | static struct platform_nand_data snappercl15_nand_data = { | 98 | static struct platform_nand_data snappercl15_nand_data = { |
101 | .chip = { | 99 | .chip = { |
102 | .nr_chips = 1, | 100 | .nr_chips = 1, |
103 | .part_probe_types = snappercl15_nand_part_probes, | ||
104 | .partitions = snappercl15_nand_parts, | 101 | .partitions = snappercl15_nand_parts, |
105 | .nr_partitions = ARRAY_SIZE(snappercl15_nand_parts), | 102 | .nr_partitions = ARRAY_SIZE(snappercl15_nand_parts), |
106 | .options = NAND_NO_AUTOINCR, | ||
107 | .chip_delay = 25, | 103 | .chip_delay = 25, |
108 | }, | 104 | }, |
109 | .ctrl = { | 105 | .ctrl = { |
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c index d4ef339d961e..75cab2d7ec73 100644 --- a/arch/arm/mach-ep93xx/ts72xx.c +++ b/arch/arm/mach-ep93xx/ts72xx.c | |||
@@ -105,8 +105,6 @@ static int ts72xx_nand_device_ready(struct mtd_info *mtd) | |||
105 | return !!(__raw_readb(addr) & 0x20); | 105 | return !!(__raw_readb(addr) & 0x20); |
106 | } | 106 | } |
107 | 107 | ||
108 | static const char *ts72xx_nand_part_probes[] = { "cmdlinepart", NULL }; | ||
109 | |||
110 | #define TS72XX_BOOTROM_PART_SIZE (SZ_16K) | 108 | #define TS72XX_BOOTROM_PART_SIZE (SZ_16K) |
111 | #define TS72XX_REDBOOT_PART_SIZE (SZ_2M + SZ_1M) | 109 | #define TS72XX_REDBOOT_PART_SIZE (SZ_2M + SZ_1M) |
112 | 110 | ||
@@ -134,7 +132,6 @@ static struct platform_nand_data ts72xx_nand_data = { | |||
134 | .nr_chips = 1, | 132 | .nr_chips = 1, |
135 | .chip_offset = 0, | 133 | .chip_offset = 0, |
136 | .chip_delay = 15, | 134 | .chip_delay = 15, |
137 | .part_probe_types = ts72xx_nand_part_probes, | ||
138 | .partitions = ts72xx_nand_parts, | 135 | .partitions = ts72xx_nand_parts, |
139 | .nr_partitions = ARRAY_SIZE(ts72xx_nand_parts), | 136 | .nr_partitions = ARRAY_SIZE(ts72xx_nand_parts), |
140 | }, | 137 | }, |
diff --git a/arch/arm/mach-imx/imx27-dt.c b/arch/arm/mach-imx/imx27-dt.c index ed38d03c61f2..eee0cc8d92a4 100644 --- a/arch/arm/mach-imx/imx27-dt.c +++ b/arch/arm/mach-imx/imx27-dt.c | |||
@@ -29,6 +29,7 @@ static const struct of_dev_auxdata imx27_auxdata_lookup[] __initconst = { | |||
29 | OF_DEV_AUXDATA("fsl,imx27-cspi", MX27_CSPI2_BASE_ADDR, "imx27-cspi.1", NULL), | 29 | OF_DEV_AUXDATA("fsl,imx27-cspi", MX27_CSPI2_BASE_ADDR, "imx27-cspi.1", NULL), |
30 | OF_DEV_AUXDATA("fsl,imx27-cspi", MX27_CSPI3_BASE_ADDR, "imx27-cspi.2", NULL), | 30 | OF_DEV_AUXDATA("fsl,imx27-cspi", MX27_CSPI3_BASE_ADDR, "imx27-cspi.2", NULL), |
31 | OF_DEV_AUXDATA("fsl,imx27-wdt", MX27_WDOG_BASE_ADDR, "imx2-wdt.0", NULL), | 31 | OF_DEV_AUXDATA("fsl,imx27-wdt", MX27_WDOG_BASE_ADDR, "imx2-wdt.0", NULL), |
32 | OF_DEV_AUXDATA("fsl,imx27-nand", MX27_NFC_BASE_ADDR, "mxc_nand.0", NULL), | ||
32 | { /* sentinel */ } | 33 | { /* sentinel */ } |
33 | }; | 34 | }; |
34 | 35 | ||
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index 3d742aee1773..108a9d3f382d 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c | |||
@@ -60,8 +60,6 @@ static struct platform_device ixdp425_flash = { | |||
60 | #if defined(CONFIG_MTD_NAND_PLATFORM) || \ | 60 | #if defined(CONFIG_MTD_NAND_PLATFORM) || \ |
61 | defined(CONFIG_MTD_NAND_PLATFORM_MODULE) | 61 | defined(CONFIG_MTD_NAND_PLATFORM_MODULE) |
62 | 62 | ||
63 | const char *part_probes[] = { "cmdlinepart", NULL }; | ||
64 | |||
65 | static struct mtd_partition ixdp425_partitions[] = { | 63 | static struct mtd_partition ixdp425_partitions[] = { |
66 | { | 64 | { |
67 | .name = "ixp400 NAND FS 0", | 65 | .name = "ixp400 NAND FS 0", |
@@ -100,8 +98,6 @@ static struct platform_nand_data ixdp425_flash_nand_data = { | |||
100 | .chip = { | 98 | .chip = { |
101 | .nr_chips = 1, | 99 | .nr_chips = 1, |
102 | .chip_delay = 30, | 100 | .chip_delay = 30, |
103 | .options = NAND_NO_AUTOINCR, | ||
104 | .part_probe_types = part_probes, | ||
105 | .partitions = ixdp425_partitions, | 101 | .partitions = ixdp425_partitions, |
106 | .nr_partitions = ARRAY_SIZE(ixdp425_partitions), | 102 | .nr_partitions = ARRAY_SIZE(ixdp425_partitions), |
107 | }, | 103 | }, |
diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c index 58cacafcf662..2e8d3e176bc7 100644 --- a/arch/arm/mach-nomadik/board-nhk8815.c +++ b/arch/arm/mach-nomadik/board-nhk8815.c | |||
@@ -111,7 +111,7 @@ static struct nomadik_nand_platform_data nhk8815_nand_data = { | |||
111 | .parts = nhk8815_partitions, | 111 | .parts = nhk8815_partitions, |
112 | .nparts = ARRAY_SIZE(nhk8815_partitions), | 112 | .nparts = ARRAY_SIZE(nhk8815_partitions), |
113 | .options = NAND_COPYBACK | NAND_CACHEPRG | NAND_NO_PADDING \ | 113 | .options = NAND_COPYBACK | NAND_CACHEPRG | NAND_NO_PADDING \ |
114 | | NAND_NO_READRDY | NAND_NO_AUTOINCR, | 114 | | NAND_NO_READRDY, |
115 | .init = nhk8815_nand_init, | 115 | .init = nhk8815_nand_init, |
116 | }; | 116 | }; |
117 | 117 | ||
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c index c7364fdbda05..6872f3fd400f 100644 --- a/arch/arm/mach-omap1/board-fsample.c +++ b/arch/arm/mach-omap1/board-fsample.c | |||
@@ -192,14 +192,11 @@ static int nand_dev_ready(struct mtd_info *mtd) | |||
192 | return gpio_get_value(FSAMPLE_NAND_RB_GPIO_PIN); | 192 | return gpio_get_value(FSAMPLE_NAND_RB_GPIO_PIN); |
193 | } | 193 | } |
194 | 194 | ||
195 | static const char *part_probes[] = { "cmdlinepart", NULL }; | ||
196 | |||
197 | static struct platform_nand_data nand_data = { | 195 | static struct platform_nand_data nand_data = { |
198 | .chip = { | 196 | .chip = { |
199 | .nr_chips = 1, | 197 | .nr_chips = 1, |
200 | .chip_offset = 0, | 198 | .chip_offset = 0, |
201 | .options = NAND_SAMSUNG_LP_OPTIONS, | 199 | .options = NAND_SAMSUNG_LP_OPTIONS, |
202 | .part_probe_types = part_probes, | ||
203 | }, | 200 | }, |
204 | .ctrl = { | 201 | .ctrl = { |
205 | .cmd_ctrl = omap1_nand_cmd_ctl, | 202 | .cmd_ctrl = omap1_nand_cmd_ctl, |
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c index 7e503686f7af..a28e989a63f4 100644 --- a/arch/arm/mach-omap1/board-h2.c +++ b/arch/arm/mach-omap1/board-h2.c | |||
@@ -186,8 +186,6 @@ static int h2_nand_dev_ready(struct mtd_info *mtd) | |||
186 | return gpio_get_value(H2_NAND_RB_GPIO_PIN); | 186 | return gpio_get_value(H2_NAND_RB_GPIO_PIN); |
187 | } | 187 | } |
188 | 188 | ||
189 | static const char *h2_part_probes[] = { "cmdlinepart", NULL }; | ||
190 | |||
191 | static struct platform_nand_data h2_nand_platdata = { | 189 | static struct platform_nand_data h2_nand_platdata = { |
192 | .chip = { | 190 | .chip = { |
193 | .nr_chips = 1, | 191 | .nr_chips = 1, |
@@ -195,7 +193,6 @@ static struct platform_nand_data h2_nand_platdata = { | |||
195 | .nr_partitions = ARRAY_SIZE(h2_nand_partitions), | 193 | .nr_partitions = ARRAY_SIZE(h2_nand_partitions), |
196 | .partitions = h2_nand_partitions, | 194 | .partitions = h2_nand_partitions, |
197 | .options = NAND_SAMSUNG_LP_OPTIONS, | 195 | .options = NAND_SAMSUNG_LP_OPTIONS, |
198 | .part_probe_types = h2_part_probes, | ||
199 | }, | 196 | }, |
200 | .ctrl = { | 197 | .ctrl = { |
201 | .cmd_ctrl = omap1_nand_cmd_ctl, | 198 | .cmd_ctrl = omap1_nand_cmd_ctl, |
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index 9fb03f189d93..108a8640fc6f 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c | |||
@@ -188,8 +188,6 @@ static int nand_dev_ready(struct mtd_info *mtd) | |||
188 | return gpio_get_value(H3_NAND_RB_GPIO_PIN); | 188 | return gpio_get_value(H3_NAND_RB_GPIO_PIN); |
189 | } | 189 | } |
190 | 190 | ||
191 | static const char *part_probes[] = { "cmdlinepart", NULL }; | ||
192 | |||
193 | static struct platform_nand_data nand_platdata = { | 191 | static struct platform_nand_data nand_platdata = { |
194 | .chip = { | 192 | .chip = { |
195 | .nr_chips = 1, | 193 | .nr_chips = 1, |
@@ -197,7 +195,6 @@ static struct platform_nand_data nand_platdata = { | |||
197 | .nr_partitions = ARRAY_SIZE(nand_partitions), | 195 | .nr_partitions = ARRAY_SIZE(nand_partitions), |
198 | .partitions = nand_partitions, | 196 | .partitions = nand_partitions, |
199 | .options = NAND_SAMSUNG_LP_OPTIONS, | 197 | .options = NAND_SAMSUNG_LP_OPTIONS, |
200 | .part_probe_types = part_probes, | ||
201 | }, | 198 | }, |
202 | .ctrl = { | 199 | .ctrl = { |
203 | .cmd_ctrl = omap1_nand_cmd_ctl, | 200 | .cmd_ctrl = omap1_nand_cmd_ctl, |
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c index f2cb24387c22..703d55ecffe2 100644 --- a/arch/arm/mach-omap1/board-perseus2.c +++ b/arch/arm/mach-omap1/board-perseus2.c | |||
@@ -150,14 +150,11 @@ static int nand_dev_ready(struct mtd_info *mtd) | |||
150 | return gpio_get_value(P2_NAND_RB_GPIO_PIN); | 150 | return gpio_get_value(P2_NAND_RB_GPIO_PIN); |
151 | } | 151 | } |
152 | 152 | ||
153 | static const char *part_probes[] = { "cmdlinepart", NULL }; | ||
154 | |||
155 | static struct platform_nand_data nand_data = { | 153 | static struct platform_nand_data nand_data = { |
156 | .chip = { | 154 | .chip = { |
157 | .nr_chips = 1, | 155 | .nr_chips = 1, |
158 | .chip_offset = 0, | 156 | .chip_offset = 0, |
159 | .options = NAND_SAMSUNG_LP_OPTIONS, | 157 | .options = NAND_SAMSUNG_LP_OPTIONS, |
160 | .part_probe_types = part_probes, | ||
161 | }, | 158 | }, |
162 | .ctrl = { | 159 | .ctrl = { |
163 | .cmd_ctrl = omap1_nand_cmd_ctl, | 160 | .cmd_ctrl = omap1_nand_cmd_ctl, |
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 46b09dae770e..2286410671e7 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #define GPMC_ECC_CONTROL 0x1f8 | 49 | #define GPMC_ECC_CONTROL 0x1f8 |
50 | #define GPMC_ECC_SIZE_CONFIG 0x1fc | 50 | #define GPMC_ECC_SIZE_CONFIG 0x1fc |
51 | #define GPMC_ECC1_RESULT 0x200 | 51 | #define GPMC_ECC1_RESULT 0x200 |
52 | #define GPMC_ECC_BCH_RESULT_0 0x240 /* not available on OMAP2 */ | ||
52 | 53 | ||
53 | /* GPMC ECC control settings */ | 54 | /* GPMC ECC control settings */ |
54 | #define GPMC_ECC_CTRL_ECCCLEAR 0x100 | 55 | #define GPMC_ECC_CTRL_ECCCLEAR 0x100 |
@@ -935,3 +936,186 @@ int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code) | |||
935 | return 0; | 936 | return 0; |
936 | } | 937 | } |
937 | EXPORT_SYMBOL_GPL(gpmc_calculate_ecc); | 938 | EXPORT_SYMBOL_GPL(gpmc_calculate_ecc); |
939 | |||
940 | #ifdef CONFIG_ARCH_OMAP3 | ||
941 | |||
942 | /** | ||
943 | * gpmc_init_hwecc_bch - initialize hardware BCH ecc functionality | ||
944 | * @cs: chip select number | ||
945 | * @nsectors: how many 512-byte sectors to process | ||
946 | * @nerrors: how many errors to correct per sector (4 or 8) | ||
947 | * | ||
948 | * This function must be executed before any call to gpmc_enable_hwecc_bch. | ||
949 | */ | ||
950 | int gpmc_init_hwecc_bch(int cs, int nsectors, int nerrors) | ||
951 | { | ||
952 | /* check if ecc module is in use */ | ||
953 | if (gpmc_ecc_used != -EINVAL) | ||
954 | return -EINVAL; | ||
955 | |||
956 | /* support only OMAP3 class */ | ||
957 | if (!cpu_is_omap34xx()) { | ||
958 | printk(KERN_ERR "BCH ecc is not supported on this CPU\n"); | ||
959 | return -EINVAL; | ||
960 | } | ||
961 | |||
962 | /* | ||
963 | * For now, assume 4-bit mode is only supported on OMAP3630 ES1.x, x>=1. | ||
964 | * Other chips may be added if confirmed to work. | ||
965 | */ | ||
966 | if ((nerrors == 4) && | ||
967 | (!cpu_is_omap3630() || (GET_OMAP_REVISION() == 0))) { | ||
968 | printk(KERN_ERR "BCH 4-bit mode is not supported on this CPU\n"); | ||
969 | return -EINVAL; | ||
970 | } | ||
971 | |||
972 | /* sanity check */ | ||
973 | if (nsectors > 8) { | ||
974 | printk(KERN_ERR "BCH cannot process %d sectors (max is 8)\n", | ||
975 | nsectors); | ||
976 | return -EINVAL; | ||
977 | } | ||
978 | |||
979 | return 0; | ||
980 | } | ||
981 | EXPORT_SYMBOL_GPL(gpmc_init_hwecc_bch); | ||
982 | |||
983 | /** | ||
984 | * gpmc_enable_hwecc_bch - enable hardware BCH ecc functionality | ||
985 | * @cs: chip select number | ||
986 | * @mode: read/write mode | ||
987 | * @dev_width: device bus width(1 for x16, 0 for x8) | ||
988 | * @nsectors: how many 512-byte sectors to process | ||
989 | * @nerrors: how many errors to correct per sector (4 or 8) | ||
990 | */ | ||
991 | int gpmc_enable_hwecc_bch(int cs, int mode, int dev_width, int nsectors, | ||
992 | int nerrors) | ||
993 | { | ||
994 | unsigned int val; | ||
995 | |||
996 | /* check if ecc module is in use */ | ||
997 | if (gpmc_ecc_used != -EINVAL) | ||
998 | return -EINVAL; | ||
999 | |||
1000 | gpmc_ecc_used = cs; | ||
1001 | |||
1002 | /* clear ecc and enable bits */ | ||
1003 | gpmc_write_reg(GPMC_ECC_CONTROL, 0x1); | ||
1004 | |||
1005 | /* | ||
1006 | * When using BCH, sector size is hardcoded to 512 bytes. | ||
1007 | * Here we are using wrapping mode 6 both for reading and writing, with: | ||
1008 | * size0 = 0 (no additional protected byte in spare area) | ||
1009 | * size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area) | ||
1010 | */ | ||
1011 | gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, (32 << 22) | (0 << 12)); | ||
1012 | |||
1013 | /* BCH configuration */ | ||
1014 | val = ((1 << 16) | /* enable BCH */ | ||
1015 | (((nerrors == 8) ? 1 : 0) << 12) | /* 8 or 4 bits */ | ||
1016 | (0x06 << 8) | /* wrap mode = 6 */ | ||
1017 | (dev_width << 7) | /* bus width */ | ||
1018 | (((nsectors-1) & 0x7) << 4) | /* number of sectors */ | ||
1019 | (cs << 1) | /* ECC CS */ | ||
1020 | (0x1)); /* enable ECC */ | ||
1021 | |||
1022 | gpmc_write_reg(GPMC_ECC_CONFIG, val); | ||
1023 | gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); | ||
1024 | return 0; | ||
1025 | } | ||
1026 | EXPORT_SYMBOL_GPL(gpmc_enable_hwecc_bch); | ||
1027 | |||
1028 | /** | ||
1029 | * gpmc_calculate_ecc_bch4 - Generate 7 ecc bytes per sector of 512 data bytes | ||
1030 | * @cs: chip select number | ||
1031 | * @dat: The pointer to data on which ecc is computed | ||
1032 | * @ecc: The ecc output buffer | ||
1033 | */ | ||
1034 | int gpmc_calculate_ecc_bch4(int cs, const u_char *dat, u_char *ecc) | ||
1035 | { | ||
1036 | int i; | ||
1037 | unsigned long nsectors, reg, val1, val2; | ||
1038 | |||
1039 | if (gpmc_ecc_used != cs) | ||
1040 | return -EINVAL; | ||
1041 | |||
1042 | nsectors = ((gpmc_read_reg(GPMC_ECC_CONFIG) >> 4) & 0x7) + 1; | ||
1043 | |||
1044 | for (i = 0; i < nsectors; i++) { | ||
1045 | |||
1046 | reg = GPMC_ECC_BCH_RESULT_0 + 16*i; | ||
1047 | |||
1048 | /* Read hw-computed remainder */ | ||
1049 | val1 = gpmc_read_reg(reg + 0); | ||
1050 | val2 = gpmc_read_reg(reg + 4); | ||
1051 | |||
1052 | /* | ||
1053 | * Add constant polynomial to remainder, in order to get an ecc | ||
1054 | * sequence of 0xFFs for a buffer filled with 0xFFs; and | ||
1055 | * left-justify the resulting polynomial. | ||
1056 | */ | ||
1057 | *ecc++ = 0x28 ^ ((val2 >> 12) & 0xFF); | ||
1058 | *ecc++ = 0x13 ^ ((val2 >> 4) & 0xFF); | ||
1059 | *ecc++ = 0xcc ^ (((val2 & 0xF) << 4)|((val1 >> 28) & 0xF)); | ||
1060 | *ecc++ = 0x39 ^ ((val1 >> 20) & 0xFF); | ||
1061 | *ecc++ = 0x96 ^ ((val1 >> 12) & 0xFF); | ||
1062 | *ecc++ = 0xac ^ ((val1 >> 4) & 0xFF); | ||
1063 | *ecc++ = 0x7f ^ ((val1 & 0xF) << 4); | ||
1064 | } | ||
1065 | |||
1066 | gpmc_ecc_used = -EINVAL; | ||
1067 | return 0; | ||
1068 | } | ||
1069 | EXPORT_SYMBOL_GPL(gpmc_calculate_ecc_bch4); | ||
1070 | |||
1071 | /** | ||
1072 | * gpmc_calculate_ecc_bch8 - Generate 13 ecc bytes per block of 512 data bytes | ||
1073 | * @cs: chip select number | ||
1074 | * @dat: The pointer to data on which ecc is computed | ||
1075 | * @ecc: The ecc output buffer | ||
1076 | */ | ||
1077 | int gpmc_calculate_ecc_bch8(int cs, const u_char *dat, u_char *ecc) | ||
1078 | { | ||
1079 | int i; | ||
1080 | unsigned long nsectors, reg, val1, val2, val3, val4; | ||
1081 | |||
1082 | if (gpmc_ecc_used != cs) | ||
1083 | return -EINVAL; | ||
1084 | |||
1085 | nsectors = ((gpmc_read_reg(GPMC_ECC_CONFIG) >> 4) & 0x7) + 1; | ||
1086 | |||
1087 | for (i = 0; i < nsectors; i++) { | ||
1088 | |||
1089 | reg = GPMC_ECC_BCH_RESULT_0 + 16*i; | ||
1090 | |||
1091 | /* Read hw-computed remainder */ | ||
1092 | val1 = gpmc_read_reg(reg + 0); | ||
1093 | val2 = gpmc_read_reg(reg + 4); | ||
1094 | val3 = gpmc_read_reg(reg + 8); | ||
1095 | val4 = gpmc_read_reg(reg + 12); | ||
1096 | |||
1097 | /* | ||
1098 | * Add constant polynomial to remainder, in order to get an ecc | ||
1099 | * sequence of 0xFFs for a buffer filled with 0xFFs. | ||
1100 | */ | ||
1101 | *ecc++ = 0xef ^ (val4 & 0xFF); | ||
1102 | *ecc++ = 0x51 ^ ((val3 >> 24) & 0xFF); | ||
1103 | *ecc++ = 0x2e ^ ((val3 >> 16) & 0xFF); | ||
1104 | *ecc++ = 0x09 ^ ((val3 >> 8) & 0xFF); | ||
1105 | *ecc++ = 0xed ^ (val3 & 0xFF); | ||
1106 | *ecc++ = 0x93 ^ ((val2 >> 24) & 0xFF); | ||
1107 | *ecc++ = 0x9a ^ ((val2 >> 16) & 0xFF); | ||
1108 | *ecc++ = 0xc2 ^ ((val2 >> 8) & 0xFF); | ||
1109 | *ecc++ = 0x97 ^ (val2 & 0xFF); | ||
1110 | *ecc++ = 0x79 ^ ((val1 >> 24) & 0xFF); | ||
1111 | *ecc++ = 0xe5 ^ ((val1 >> 16) & 0xFF); | ||
1112 | *ecc++ = 0x24 ^ ((val1 >> 8) & 0xFF); | ||
1113 | *ecc++ = 0xb5 ^ (val1 & 0xFF); | ||
1114 | } | ||
1115 | |||
1116 | gpmc_ecc_used = -EINVAL; | ||
1117 | return 0; | ||
1118 | } | ||
1119 | EXPORT_SYMBOL_GPL(gpmc_calculate_ecc_bch8); | ||
1120 | |||
1121 | #endif /* CONFIG_ARCH_OMAP3 */ | ||
diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c index a74f3cf54cc5..b4203277f3cd 100644 --- a/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/arch/arm/mach-orion5x/ts78xx-setup.c | |||
@@ -251,8 +251,6 @@ static void ts78xx_ts_nand_read_buf(struct mtd_info *mtd, | |||
251 | readsb(io_base, buf, len); | 251 | readsb(io_base, buf, len); |
252 | } | 252 | } |
253 | 253 | ||
254 | const char *ts_nand_part_probes[] = { "cmdlinepart", NULL }; | ||
255 | |||
256 | static struct mtd_partition ts78xx_ts_nand_parts[] = { | 254 | static struct mtd_partition ts78xx_ts_nand_parts[] = { |
257 | { | 255 | { |
258 | .name = "mbr", | 256 | .name = "mbr", |
@@ -277,7 +275,6 @@ static struct mtd_partition ts78xx_ts_nand_parts[] = { | |||
277 | static struct platform_nand_data ts78xx_ts_nand_data = { | 275 | static struct platform_nand_data ts78xx_ts_nand_data = { |
278 | .chip = { | 276 | .chip = { |
279 | .nr_chips = 1, | 277 | .nr_chips = 1, |
280 | .part_probe_types = ts_nand_part_probes, | ||
281 | .partitions = ts78xx_ts_nand_parts, | 278 | .partitions = ts78xx_ts_nand_parts, |
282 | .nr_partitions = ARRAY_SIZE(ts78xx_ts_nand_parts), | 279 | .nr_partitions = ARRAY_SIZE(ts78xx_ts_nand_parts), |
283 | .chip_delay = 15, | 280 | .chip_delay = 15, |
diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c index 56e8cebeb7d5..9244493dbcb7 100644 --- a/arch/arm/mach-pxa/balloon3.c +++ b/arch/arm/mach-pxa/balloon3.c | |||
@@ -679,8 +679,6 @@ static struct mtd_partition balloon3_partition_info[] = { | |||
679 | }, | 679 | }, |
680 | }; | 680 | }; |
681 | 681 | ||
682 | static const char *balloon3_part_probes[] = { "cmdlinepart", NULL }; | ||
683 | |||
684 | struct platform_nand_data balloon3_nand_pdata = { | 682 | struct platform_nand_data balloon3_nand_pdata = { |
685 | .chip = { | 683 | .chip = { |
686 | .nr_chips = 4, | 684 | .nr_chips = 4, |
@@ -688,7 +686,6 @@ struct platform_nand_data balloon3_nand_pdata = { | |||
688 | .nr_partitions = ARRAY_SIZE(balloon3_partition_info), | 686 | .nr_partitions = ARRAY_SIZE(balloon3_partition_info), |
689 | .partitions = balloon3_partition_info, | 687 | .partitions = balloon3_partition_info, |
690 | .chip_delay = 50, | 688 | .chip_delay = 50, |
691 | .part_probe_types = balloon3_part_probes, | ||
692 | }, | 689 | }, |
693 | .ctrl = { | 690 | .ctrl = { |
694 | .hwcontrol = 0, | 691 | .hwcontrol = 0, |
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index a3a4a38d4972..97f82ad341bf 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c | |||
@@ -338,8 +338,6 @@ static struct mtd_partition em_x270_partition_info[] = { | |||
338 | }, | 338 | }, |
339 | }; | 339 | }; |
340 | 340 | ||
341 | static const char *em_x270_part_probes[] = { "cmdlinepart", NULL }; | ||
342 | |||
343 | struct platform_nand_data em_x270_nand_platdata = { | 341 | struct platform_nand_data em_x270_nand_platdata = { |
344 | .chip = { | 342 | .chip = { |
345 | .nr_chips = 1, | 343 | .nr_chips = 1, |
@@ -347,7 +345,6 @@ struct platform_nand_data em_x270_nand_platdata = { | |||
347 | .nr_partitions = ARRAY_SIZE(em_x270_partition_info), | 345 | .nr_partitions = ARRAY_SIZE(em_x270_partition_info), |
348 | .partitions = em_x270_partition_info, | 346 | .partitions = em_x270_partition_info, |
349 | .chip_delay = 20, | 347 | .chip_delay = 20, |
350 | .part_probe_types = em_x270_part_probes, | ||
351 | }, | 348 | }, |
352 | .ctrl = { | 349 | .ctrl = { |
353 | .hwcontrol = 0, | 350 | .hwcontrol = 0, |
diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c index 9507605ed547..0da35dccfd89 100644 --- a/arch/arm/mach-pxa/palmtx.c +++ b/arch/arm/mach-pxa/palmtx.c | |||
@@ -268,8 +268,6 @@ static struct mtd_partition palmtx_partition_info[] = { | |||
268 | }, | 268 | }, |
269 | }; | 269 | }; |
270 | 270 | ||
271 | static const char *palmtx_part_probes[] = { "cmdlinepart", NULL }; | ||
272 | |||
273 | struct platform_nand_data palmtx_nand_platdata = { | 271 | struct platform_nand_data palmtx_nand_platdata = { |
274 | .chip = { | 272 | .chip = { |
275 | .nr_chips = 1, | 273 | .nr_chips = 1, |
@@ -277,7 +275,6 @@ struct platform_nand_data palmtx_nand_platdata = { | |||
277 | .nr_partitions = ARRAY_SIZE(palmtx_partition_info), | 275 | .nr_partitions = ARRAY_SIZE(palmtx_partition_info), |
278 | .partitions = palmtx_partition_info, | 276 | .partitions = palmtx_partition_info, |
279 | .chip_delay = 20, | 277 | .chip_delay = 20, |
280 | .part_probe_types = palmtx_part_probes, | ||
281 | }, | 278 | }, |
282 | .ctrl = { | 279 | .ctrl = { |
283 | .cmd_ctrl = palmtx_nand_cmd_ctl, | 280 | .cmd_ctrl = palmtx_nand_cmd_ctl, |
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index 1527929b445a..f37764a36072 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h | |||
@@ -92,6 +92,8 @@ enum omap_ecc { | |||
92 | OMAP_ECC_HAMMING_CODE_HW, /* gpmc to detect the error */ | 92 | OMAP_ECC_HAMMING_CODE_HW, /* gpmc to detect the error */ |
93 | /* 1-bit ecc: stored at beginning of spare area as romcode */ | 93 | /* 1-bit ecc: stored at beginning of spare area as romcode */ |
94 | OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */ | 94 | OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */ |
95 | OMAP_ECC_BCH4_CODE_HW, /* 4-bit BCH ecc code */ | ||
96 | OMAP_ECC_BCH8_CODE_HW, /* 8-bit BCH ecc code */ | ||
95 | }; | 97 | }; |
96 | 98 | ||
97 | /* | 99 | /* |
@@ -157,4 +159,13 @@ extern int gpmc_nand_write(int cs, int cmd, int wval); | |||
157 | 159 | ||
158 | int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size); | 160 | int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size); |
159 | int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code); | 161 | int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code); |
162 | |||
163 | #ifdef CONFIG_ARCH_OMAP3 | ||
164 | int gpmc_init_hwecc_bch(int cs, int nsectors, int nerrors); | ||
165 | int gpmc_enable_hwecc_bch(int cs, int mode, int dev_width, int nsectors, | ||
166 | int nerrors); | ||
167 | int gpmc_calculate_ecc_bch4(int cs, const u_char *dat, u_char *ecc); | ||
168 | int gpmc_calculate_ecc_bch8(int cs, const u_char *dat, u_char *ecc); | ||
169 | #endif /* CONFIG_ARCH_OMAP3 */ | ||
170 | |||
160 | #endif | 171 | #endif |
diff --git a/arch/blackfin/mach-bf561/boards/acvilon.c b/arch/blackfin/mach-bf561/boards/acvilon.c index f6ffd6f054c3..0b74218fdd3a 100644 --- a/arch/blackfin/mach-bf561/boards/acvilon.c +++ b/arch/blackfin/mach-bf561/boards/acvilon.c | |||
@@ -248,8 +248,6 @@ static struct platform_device bfin_uart0_device = { | |||
248 | 248 | ||
249 | #if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE) | 249 | #if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE) |
250 | 250 | ||
251 | const char *part_probes[] = { "cmdlinepart", NULL }; | ||
252 | |||
253 | static struct mtd_partition bfin_plat_nand_partitions[] = { | 251 | static struct mtd_partition bfin_plat_nand_partitions[] = { |
254 | { | 252 | { |
255 | .name = "params(nand)", | 253 | .name = "params(nand)", |
@@ -289,7 +287,6 @@ static struct platform_nand_data bfin_plat_nand_data = { | |||
289 | .chip = { | 287 | .chip = { |
290 | .nr_chips = 1, | 288 | .nr_chips = 1, |
291 | .chip_delay = 30, | 289 | .chip_delay = 30, |
292 | .part_probe_types = part_probes, | ||
293 | .partitions = bfin_plat_nand_partitions, | 290 | .partitions = bfin_plat_nand_partitions, |
294 | .nr_partitions = ARRAY_SIZE(bfin_plat_nand_partitions), | 291 | .nr_partitions = ARRAY_SIZE(bfin_plat_nand_partitions), |
295 | }, | 292 | }, |
diff --git a/arch/mips/alchemy/devboards/db1200.c b/arch/mips/alchemy/devboards/db1200.c index 7dde01642d6b..bf2248474fa8 100644 --- a/arch/mips/alchemy/devboards/db1200.c +++ b/arch/mips/alchemy/devboards/db1200.c | |||
@@ -213,8 +213,6 @@ static int au1200_nand_device_ready(struct mtd_info *mtd) | |||
213 | return __raw_readl((void __iomem *)MEM_STSTAT) & 1; | 213 | return __raw_readl((void __iomem *)MEM_STSTAT) & 1; |
214 | } | 214 | } |
215 | 215 | ||
216 | static const char *db1200_part_probes[] = { "cmdlinepart", NULL }; | ||
217 | |||
218 | static struct mtd_partition db1200_nand_parts[] = { | 216 | static struct mtd_partition db1200_nand_parts[] = { |
219 | { | 217 | { |
220 | .name = "NAND FS 0", | 218 | .name = "NAND FS 0", |
@@ -235,7 +233,6 @@ struct platform_nand_data db1200_nand_platdata = { | |||
235 | .nr_partitions = ARRAY_SIZE(db1200_nand_parts), | 233 | .nr_partitions = ARRAY_SIZE(db1200_nand_parts), |
236 | .partitions = db1200_nand_parts, | 234 | .partitions = db1200_nand_parts, |
237 | .chip_delay = 20, | 235 | .chip_delay = 20, |
238 | .part_probe_types = db1200_part_probes, | ||
239 | }, | 236 | }, |
240 | .ctrl = { | 237 | .ctrl = { |
241 | .dev_ready = au1200_nand_device_ready, | 238 | .dev_ready = au1200_nand_device_ready, |
diff --git a/arch/mips/alchemy/devboards/db1300.c b/arch/mips/alchemy/devboards/db1300.c index 0893f2af0d01..c56e0246694e 100644 --- a/arch/mips/alchemy/devboards/db1300.c +++ b/arch/mips/alchemy/devboards/db1300.c | |||
@@ -145,8 +145,6 @@ static int au1300_nand_device_ready(struct mtd_info *mtd) | |||
145 | return __raw_readl((void __iomem *)MEM_STSTAT) & 1; | 145 | return __raw_readl((void __iomem *)MEM_STSTAT) & 1; |
146 | } | 146 | } |
147 | 147 | ||
148 | static const char *db1300_part_probes[] = { "cmdlinepart", NULL }; | ||
149 | |||
150 | static struct mtd_partition db1300_nand_parts[] = { | 148 | static struct mtd_partition db1300_nand_parts[] = { |
151 | { | 149 | { |
152 | .name = "NAND FS 0", | 150 | .name = "NAND FS 0", |
@@ -167,7 +165,6 @@ struct platform_nand_data db1300_nand_platdata = { | |||
167 | .nr_partitions = ARRAY_SIZE(db1300_nand_parts), | 165 | .nr_partitions = ARRAY_SIZE(db1300_nand_parts), |
168 | .partitions = db1300_nand_parts, | 166 | .partitions = db1300_nand_parts, |
169 | .chip_delay = 20, | 167 | .chip_delay = 20, |
170 | .part_probe_types = db1300_part_probes, | ||
171 | }, | 168 | }, |
172 | .ctrl = { | 169 | .ctrl = { |
173 | .dev_ready = au1300_nand_device_ready, | 170 | .dev_ready = au1300_nand_device_ready, |
diff --git a/arch/mips/alchemy/devboards/db1550.c b/arch/mips/alchemy/devboards/db1550.c index 6815d0783cd8..9eb79062f46e 100644 --- a/arch/mips/alchemy/devboards/db1550.c +++ b/arch/mips/alchemy/devboards/db1550.c | |||
@@ -149,8 +149,6 @@ static int au1550_nand_device_ready(struct mtd_info *mtd) | |||
149 | return __raw_readl((void __iomem *)MEM_STSTAT) & 1; | 149 | return __raw_readl((void __iomem *)MEM_STSTAT) & 1; |
150 | } | 150 | } |
151 | 151 | ||
152 | static const char *db1550_part_probes[] = { "cmdlinepart", NULL }; | ||
153 | |||
154 | static struct mtd_partition db1550_nand_parts[] = { | 152 | static struct mtd_partition db1550_nand_parts[] = { |
155 | { | 153 | { |
156 | .name = "NAND FS 0", | 154 | .name = "NAND FS 0", |
@@ -171,7 +169,6 @@ struct platform_nand_data db1550_nand_platdata = { | |||
171 | .nr_partitions = ARRAY_SIZE(db1550_nand_parts), | 169 | .nr_partitions = ARRAY_SIZE(db1550_nand_parts), |
172 | .partitions = db1550_nand_parts, | 170 | .partitions = db1550_nand_parts, |
173 | .chip_delay = 20, | 171 | .chip_delay = 20, |
174 | .part_probe_types = db1550_part_probes, | ||
175 | }, | 172 | }, |
176 | .ctrl = { | 173 | .ctrl = { |
177 | .dev_ready = au1550_nand_device_ready, | 174 | .dev_ready = au1550_nand_device_ready, |
diff --git a/arch/mips/pnx833x/common/platform.c b/arch/mips/pnx833x/common/platform.c index 87167dcc79fa..05a1d922cd60 100644 --- a/arch/mips/pnx833x/common/platform.c +++ b/arch/mips/pnx833x/common/platform.c | |||
@@ -244,11 +244,6 @@ static struct platform_device pnx833x_sata_device = { | |||
244 | .resource = pnx833x_sata_resources, | 244 | .resource = pnx833x_sata_resources, |
245 | }; | 245 | }; |
246 | 246 | ||
247 | static const char *part_probes[] = { | ||
248 | "cmdlinepart", | ||
249 | NULL | ||
250 | }; | ||
251 | |||
252 | static void | 247 | static void |
253 | pnx833x_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) | 248 | pnx833x_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) |
254 | { | 249 | { |
@@ -268,7 +263,6 @@ static struct platform_nand_data pnx833x_flash_nand_data = { | |||
268 | .chip = { | 263 | .chip = { |
269 | .nr_chips = 1, | 264 | .nr_chips = 1, |
270 | .chip_delay = 25, | 265 | .chip_delay = 25, |
271 | .part_probe_types = part_probes, | ||
272 | }, | 266 | }, |
273 | .ctrl = { | 267 | .ctrl = { |
274 | .cmd_ctrl = pnx833x_flash_nand_cmd_ctrl | 268 | .cmd_ctrl = pnx833x_flash_nand_cmd_ctrl |
diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index ea774285e6c5..716e9a12f0e7 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c | |||
@@ -293,7 +293,6 @@ static void __init rb532_nand_setup(void) | |||
293 | rb532_nand_data.chip.nr_partitions = ARRAY_SIZE(rb532_partition_info); | 293 | rb532_nand_data.chip.nr_partitions = ARRAY_SIZE(rb532_partition_info); |
294 | rb532_nand_data.chip.partitions = rb532_partition_info; | 294 | rb532_nand_data.chip.partitions = rb532_partition_info; |
295 | rb532_nand_data.chip.chip_delay = NAND_CHIP_DELAY; | 295 | rb532_nand_data.chip.chip_delay = NAND_CHIP_DELAY; |
296 | rb532_nand_data.chip.options = NAND_NO_AUTOINCR; | ||
297 | } | 296 | } |
298 | 297 | ||
299 | 298 | ||
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c index 34cd0c5ff2e1..a8a1ca741c85 100644 --- a/arch/sh/boards/mach-migor/setup.c +++ b/arch/sh/boards/mach-migor/setup.c | |||
@@ -188,7 +188,6 @@ static struct platform_nand_data migor_nand_flash_data = { | |||
188 | .partitions = migor_nand_flash_partitions, | 188 | .partitions = migor_nand_flash_partitions, |
189 | .nr_partitions = ARRAY_SIZE(migor_nand_flash_partitions), | 189 | .nr_partitions = ARRAY_SIZE(migor_nand_flash_partitions), |
190 | .chip_delay = 20, | 190 | .chip_delay = 20, |
191 | .part_probe_types = (const char *[]) { "cmdlinepart", NULL }, | ||
192 | }, | 191 | }, |
193 | .ctrl = { | 192 | .ctrl = { |
194 | .dev_ready = migor_nand_flash_ready, | 193 | .dev_ready = migor_nand_flash_ready, |
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 5760c1a4b3f6..27143e042af5 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig | |||
@@ -128,7 +128,7 @@ config MTD_AFS_PARTS | |||
128 | 128 | ||
129 | config MTD_OF_PARTS | 129 | config MTD_OF_PARTS |
130 | tristate "OpenFirmware partitioning information support" | 130 | tristate "OpenFirmware partitioning information support" |
131 | default Y | 131 | default y |
132 | depends on OF | 132 | depends on OF |
133 | help | 133 | help |
134 | This provides a partition parsing function which derives | 134 | This provides a partition parsing function which derives |
diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c index 608321ee056e..63d2a64331f7 100644 --- a/drivers/mtd/bcm63xxpart.c +++ b/drivers/mtd/bcm63xxpart.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright © 2006-2008 Florian Fainelli <florian@openwrt.org> | 4 | * Copyright © 2006-2008 Florian Fainelli <florian@openwrt.org> |
5 | * Mike Albon <malbon@openwrt.org> | 5 | * Mike Albon <malbon@openwrt.org> |
6 | * Copyright © 2009-2010 Daniel Dickinson <openwrt@cshore.neomailbox.net> | 6 | * Copyright © 2009-2010 Daniel Dickinson <openwrt@cshore.neomailbox.net> |
7 | * Copyright © 2011 Jonas Gorski <jonas.gorski@gmail.com> | 7 | * Copyright © 2011-2012 Jonas Gorski <jonas.gorski@gmail.com> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
@@ -82,6 +82,7 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, | |||
82 | int namelen = 0; | 82 | int namelen = 0; |
83 | int i; | 83 | int i; |
84 | u32 computed_crc; | 84 | u32 computed_crc; |
85 | bool rootfs_first = false; | ||
85 | 86 | ||
86 | if (bcm63xx_detect_cfe(master)) | 87 | if (bcm63xx_detect_cfe(master)) |
87 | return -EINVAL; | 88 | return -EINVAL; |
@@ -109,6 +110,7 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, | |||
109 | char *boardid = &(buf->board_id[0]); | 110 | char *boardid = &(buf->board_id[0]); |
110 | char *tagversion = &(buf->tag_version[0]); | 111 | char *tagversion = &(buf->tag_version[0]); |
111 | 112 | ||
113 | sscanf(buf->flash_image_start, "%u", &rootfsaddr); | ||
112 | sscanf(buf->kernel_address, "%u", &kerneladdr); | 114 | sscanf(buf->kernel_address, "%u", &kerneladdr); |
113 | sscanf(buf->kernel_length, "%u", &kernellen); | 115 | sscanf(buf->kernel_length, "%u", &kernellen); |
114 | sscanf(buf->total_length, "%u", &totallen); | 116 | sscanf(buf->total_length, "%u", &totallen); |
@@ -117,10 +119,19 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, | |||
117 | tagversion, boardid); | 119 | tagversion, boardid); |
118 | 120 | ||
119 | kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE; | 121 | kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE; |
120 | rootfsaddr = kerneladdr + kernellen; | 122 | rootfsaddr = rootfsaddr - BCM63XX_EXTENDED_SIZE; |
121 | spareaddr = roundup(totallen, master->erasesize) + cfelen; | 123 | spareaddr = roundup(totallen, master->erasesize) + cfelen; |
122 | sparelen = master->size - spareaddr - nvramlen; | 124 | sparelen = master->size - spareaddr - nvramlen; |
123 | rootfslen = spareaddr - rootfsaddr; | 125 | |
126 | if (rootfsaddr < kerneladdr) { | ||
127 | /* default Broadcom layout */ | ||
128 | rootfslen = kerneladdr - rootfsaddr; | ||
129 | rootfs_first = true; | ||
130 | } else { | ||
131 | /* OpenWrt layout */ | ||
132 | rootfsaddr = kerneladdr + kernellen; | ||
133 | rootfslen = spareaddr - rootfsaddr; | ||
134 | } | ||
124 | } else { | 135 | } else { |
125 | pr_warn("CFE boot tag CRC invalid (expected %08x, actual %08x)\n", | 136 | pr_warn("CFE boot tag CRC invalid (expected %08x, actual %08x)\n", |
126 | buf->header_crc, computed_crc); | 137 | buf->header_crc, computed_crc); |
@@ -156,18 +167,26 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, | |||
156 | curpart++; | 167 | curpart++; |
157 | 168 | ||
158 | if (kernellen > 0) { | 169 | if (kernellen > 0) { |
159 | parts[curpart].name = "kernel"; | 170 | int kernelpart = curpart; |
160 | parts[curpart].offset = kerneladdr; | 171 | |
161 | parts[curpart].size = kernellen; | 172 | if (rootfslen > 0 && rootfs_first) |
173 | kernelpart++; | ||
174 | parts[kernelpart].name = "kernel"; | ||
175 | parts[kernelpart].offset = kerneladdr; | ||
176 | parts[kernelpart].size = kernellen; | ||
162 | curpart++; | 177 | curpart++; |
163 | } | 178 | } |
164 | 179 | ||
165 | if (rootfslen > 0) { | 180 | if (rootfslen > 0) { |
166 | parts[curpart].name = "rootfs"; | 181 | int rootfspart = curpart; |
167 | parts[curpart].offset = rootfsaddr; | 182 | |
168 | parts[curpart].size = rootfslen; | 183 | if (kernellen > 0 && rootfs_first) |
169 | if (sparelen > 0) | 184 | rootfspart--; |
170 | parts[curpart].size += sparelen; | 185 | parts[rootfspart].name = "rootfs"; |
186 | parts[rootfspart].offset = rootfsaddr; | ||
187 | parts[rootfspart].size = rootfslen; | ||
188 | if (sparelen > 0 && !rootfs_first) | ||
189 | parts[rootfspart].size += sparelen; | ||
171 | curpart++; | 190 | curpart++; |
172 | } | 191 | } |
173 | 192 | ||
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index d02592e6a0f0..22d0493a026f 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | |||
@@ -317,7 +317,7 @@ static void fixup_s29gl064n_sectors(struct mtd_info *mtd) | |||
317 | 317 | ||
318 | if ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0x003f) { | 318 | if ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0x003f) { |
319 | cfi->cfiq->EraseRegionInfo[0] |= 0x0040; | 319 | cfi->cfiq->EraseRegionInfo[0] |= 0x0040; |
320 | pr_warning("%s: Bad S29GL064N CFI data, adjust from 64 to 128 sectors\n", mtd->name); | 320 | pr_warning("%s: Bad S29GL064N CFI data; adjust from 64 to 128 sectors\n", mtd->name); |
321 | } | 321 | } |
322 | } | 322 | } |
323 | 323 | ||
@@ -328,10 +328,23 @@ static void fixup_s29gl032n_sectors(struct mtd_info *mtd) | |||
328 | 328 | ||
329 | if ((cfi->cfiq->EraseRegionInfo[1] & 0xffff) == 0x007e) { | 329 | if ((cfi->cfiq->EraseRegionInfo[1] & 0xffff) == 0x007e) { |
330 | cfi->cfiq->EraseRegionInfo[1] &= ~0x0040; | 330 | cfi->cfiq->EraseRegionInfo[1] &= ~0x0040; |
331 | pr_warning("%s: Bad S29GL032N CFI data, adjust from 127 to 63 sectors\n", mtd->name); | 331 | pr_warning("%s: Bad S29GL032N CFI data; adjust from 127 to 63 sectors\n", mtd->name); |
332 | } | 332 | } |
333 | } | 333 | } |
334 | 334 | ||
335 | static void fixup_s29ns512p_sectors(struct mtd_info *mtd) | ||
336 | { | ||
337 | struct map_info *map = mtd->priv; | ||
338 | struct cfi_private *cfi = map->fldrv_priv; | ||
339 | |||
340 | /* | ||
341 | * S29NS512P flash uses more than 8bits to report number of sectors, | ||
342 | * which is not permitted by CFI. | ||
343 | */ | ||
344 | cfi->cfiq->EraseRegionInfo[0] = 0x020001ff; | ||
345 | pr_warning("%s: Bad S29NS512P CFI data; adjust to 512 sectors\n", mtd->name); | ||
346 | } | ||
347 | |||
335 | /* Used to fix CFI-Tables of chips without Extended Query Tables */ | 348 | /* Used to fix CFI-Tables of chips without Extended Query Tables */ |
336 | static struct cfi_fixup cfi_nopri_fixup_table[] = { | 349 | static struct cfi_fixup cfi_nopri_fixup_table[] = { |
337 | { CFI_MFR_SST, 0x234a, fixup_sst39vf }, /* SST39VF1602 */ | 350 | { CFI_MFR_SST, 0x234a, fixup_sst39vf }, /* SST39VF1602 */ |
@@ -362,6 +375,7 @@ static struct cfi_fixup cfi_fixup_table[] = { | |||
362 | { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors }, | 375 | { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors }, |
363 | { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors }, | 376 | { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors }, |
364 | { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors }, | 377 | { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors }, |
378 | { CFI_MFR_AMD, 0x3f00, fixup_s29ns512p_sectors }, | ||
365 | { CFI_MFR_SST, 0x536a, fixup_sst38vf640x_sectorsize }, /* SST38VF6402 */ | 379 | { CFI_MFR_SST, 0x536a, fixup_sst38vf640x_sectorsize }, /* SST38VF6402 */ |
366 | { CFI_MFR_SST, 0x536b, fixup_sst38vf640x_sectorsize }, /* SST38VF6401 */ | 380 | { CFI_MFR_SST, 0x536b, fixup_sst38vf640x_sectorsize }, /* SST38VF6401 */ |
367 | { CFI_MFR_SST, 0x536c, fixup_sst38vf640x_sectorsize }, /* SST38VF6404 */ | 381 | { CFI_MFR_SST, 0x536c, fixup_sst38vf640x_sectorsize }, /* SST38VF6404 */ |
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index ddf9ec6d9168..4558e0f4d07f 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c | |||
@@ -70,7 +70,7 @@ struct cmdline_mtd_partition { | |||
70 | /* mtdpart_setup() parses into here */ | 70 | /* mtdpart_setup() parses into here */ |
71 | static struct cmdline_mtd_partition *partitions; | 71 | static struct cmdline_mtd_partition *partitions; |
72 | 72 | ||
73 | /* the command line passed to mtdpart_setupd() */ | 73 | /* the command line passed to mtdpart_setup() */ |
74 | static char *cmdline; | 74 | static char *cmdline; |
75 | static int cmdline_parsed = 0; | 75 | static int cmdline_parsed = 0; |
76 | 76 | ||
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index a4a80b742e65..681e2ee0f2d6 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c | |||
@@ -52,8 +52,6 @@ static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len) | |||
52 | 52 | ||
53 | while (pages) { | 53 | while (pages) { |
54 | page = page_read(mapping, index); | 54 | page = page_read(mapping, index); |
55 | if (!page) | ||
56 | return -ENOMEM; | ||
57 | if (IS_ERR(page)) | 55 | if (IS_ERR(page)) |
58 | return PTR_ERR(page); | 56 | return PTR_ERR(page); |
59 | 57 | ||
@@ -112,8 +110,6 @@ static int block2mtd_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
112 | len = len - cpylen; | 110 | len = len - cpylen; |
113 | 111 | ||
114 | page = page_read(dev->blkdev->bd_inode->i_mapping, index); | 112 | page = page_read(dev->blkdev->bd_inode->i_mapping, index); |
115 | if (!page) | ||
116 | return -ENOMEM; | ||
117 | if (IS_ERR(page)) | 113 | if (IS_ERR(page)) |
118 | return PTR_ERR(page); | 114 | return PTR_ERR(page); |
119 | 115 | ||
@@ -148,8 +144,6 @@ static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf, | |||
148 | len = len - cpylen; | 144 | len = len - cpylen; |
149 | 145 | ||
150 | page = page_read(mapping, index); | 146 | page = page_read(mapping, index); |
151 | if (!page) | ||
152 | return -ENOMEM; | ||
153 | if (IS_ERR(page)) | 147 | if (IS_ERR(page)) |
154 | return PTR_ERR(page); | 148 | return PTR_ERR(page); |
155 | 149 | ||
@@ -271,7 +265,6 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) | |||
271 | dev->mtd.flags = MTD_CAP_RAM; | 265 | dev->mtd.flags = MTD_CAP_RAM; |
272 | dev->mtd._erase = block2mtd_erase; | 266 | dev->mtd._erase = block2mtd_erase; |
273 | dev->mtd._write = block2mtd_write; | 267 | dev->mtd._write = block2mtd_write; |
274 | dev->mtd._writev = mtd_writev; | ||
275 | dev->mtd._sync = block2mtd_sync; | 268 | dev->mtd._sync = block2mtd_sync; |
276 | dev->mtd._read = block2mtd_read; | 269 | dev->mtd._read = block2mtd_read; |
277 | dev->mtd.priv = dev; | 270 | dev->mtd.priv = dev; |
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c index 50aa90aa7a7f..f70854d728fe 100644 --- a/drivers/mtd/devices/docg3.c +++ b/drivers/mtd/devices/docg3.c | |||
@@ -227,7 +227,7 @@ static void doc_read_data_area(struct docg3 *docg3, void *buf, int len, | |||
227 | u8 data8, *dst8; | 227 | u8 data8, *dst8; |
228 | 228 | ||
229 | doc_dbg("doc_read_data_area(buf=%p, len=%d)\n", buf, len); | 229 | doc_dbg("doc_read_data_area(buf=%p, len=%d)\n", buf, len); |
230 | cdr = len & 0x3; | 230 | cdr = len & 0x1; |
231 | len4 = len - cdr; | 231 | len4 = len - cdr; |
232 | 232 | ||
233 | if (first) | 233 | if (first) |
@@ -732,12 +732,24 @@ err: | |||
732 | * @len: the number of bytes to be read (must be a multiple of 4) | 732 | * @len: the number of bytes to be read (must be a multiple of 4) |
733 | * @buf: the buffer to be filled in (or NULL is forget bytes) | 733 | * @buf: the buffer to be filled in (or NULL is forget bytes) |
734 | * @first: 1 if first time read, DOC_READADDRESS should be set | 734 | * @first: 1 if first time read, DOC_READADDRESS should be set |
735 | * @last_odd: 1 if last read ended up on an odd byte | ||
736 | * | ||
737 | * Reads bytes from a prepared page. There is a trickery here : if the last read | ||
738 | * ended up on an odd offset in the 1024 bytes double page, ie. between the 2 | ||
739 | * planes, the first byte must be read apart. If a word (16bit) read was used, | ||
740 | * the read would return the byte of plane 2 as low *and* high endian, which | ||
741 | * will mess the read. | ||
735 | * | 742 | * |
736 | */ | 743 | */ |
737 | static int doc_read_page_getbytes(struct docg3 *docg3, int len, u_char *buf, | 744 | static int doc_read_page_getbytes(struct docg3 *docg3, int len, u_char *buf, |
738 | int first) | 745 | int first, int last_odd) |
739 | { | 746 | { |
740 | doc_read_data_area(docg3, buf, len, first); | 747 | if (last_odd && len > 0) { |
748 | doc_read_data_area(docg3, buf, 1, first); | ||
749 | doc_read_data_area(docg3, buf ? buf + 1 : buf, len - 1, 0); | ||
750 | } else { | ||
751 | doc_read_data_area(docg3, buf, len, first); | ||
752 | } | ||
741 | doc_delay(docg3, 2); | 753 | doc_delay(docg3, 2); |
742 | return len; | 754 | return len; |
743 | } | 755 | } |
@@ -850,6 +862,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t from, | |||
850 | u8 *buf = ops->datbuf; | 862 | u8 *buf = ops->datbuf; |
851 | size_t len, ooblen, nbdata, nboob; | 863 | size_t len, ooblen, nbdata, nboob; |
852 | u8 hwecc[DOC_ECC_BCH_SIZE], eccconf1; | 864 | u8 hwecc[DOC_ECC_BCH_SIZE], eccconf1; |
865 | int max_bitflips = 0; | ||
853 | 866 | ||
854 | if (buf) | 867 | if (buf) |
855 | len = ops->len; | 868 | len = ops->len; |
@@ -876,7 +889,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t from, | |||
876 | ret = 0; | 889 | ret = 0; |
877 | skip = from % DOC_LAYOUT_PAGE_SIZE; | 890 | skip = from % DOC_LAYOUT_PAGE_SIZE; |
878 | mutex_lock(&docg3->cascade->lock); | 891 | mutex_lock(&docg3->cascade->lock); |
879 | while (!ret && (len > 0 || ooblen > 0)) { | 892 | while (ret >= 0 && (len > 0 || ooblen > 0)) { |
880 | calc_block_sector(from - skip, &block0, &block1, &page, &ofs, | 893 | calc_block_sector(from - skip, &block0, &block1, &page, &ofs, |
881 | docg3->reliable); | 894 | docg3->reliable); |
882 | nbdata = min_t(size_t, len, DOC_LAYOUT_PAGE_SIZE - skip); | 895 | nbdata = min_t(size_t, len, DOC_LAYOUT_PAGE_SIZE - skip); |
@@ -887,20 +900,20 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t from, | |||
887 | ret = doc_read_page_ecc_init(docg3, DOC_ECC_BCH_TOTAL_BYTES); | 900 | ret = doc_read_page_ecc_init(docg3, DOC_ECC_BCH_TOTAL_BYTES); |
888 | if (ret < 0) | 901 | if (ret < 0) |
889 | goto err_in_read; | 902 | goto err_in_read; |
890 | ret = doc_read_page_getbytes(docg3, skip, NULL, 1); | 903 | ret = doc_read_page_getbytes(docg3, skip, NULL, 1, 0); |
891 | if (ret < skip) | 904 | if (ret < skip) |
892 | goto err_in_read; | 905 | goto err_in_read; |
893 | ret = doc_read_page_getbytes(docg3, nbdata, buf, 0); | 906 | ret = doc_read_page_getbytes(docg3, nbdata, buf, 0, skip % 2); |
894 | if (ret < nbdata) | 907 | if (ret < nbdata) |
895 | goto err_in_read; | 908 | goto err_in_read; |
896 | doc_read_page_getbytes(docg3, | 909 | doc_read_page_getbytes(docg3, |
897 | DOC_LAYOUT_PAGE_SIZE - nbdata - skip, | 910 | DOC_LAYOUT_PAGE_SIZE - nbdata - skip, |
898 | NULL, 0); | 911 | NULL, 0, (skip + nbdata) % 2); |
899 | ret = doc_read_page_getbytes(docg3, nboob, oobbuf, 0); | 912 | ret = doc_read_page_getbytes(docg3, nboob, oobbuf, 0, 0); |
900 | if (ret < nboob) | 913 | if (ret < nboob) |
901 | goto err_in_read; | 914 | goto err_in_read; |
902 | doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE - nboob, | 915 | doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE - nboob, |
903 | NULL, 0); | 916 | NULL, 0, nboob % 2); |
904 | 917 | ||
905 | doc_get_bch_hw_ecc(docg3, hwecc); | 918 | doc_get_bch_hw_ecc(docg3, hwecc); |
906 | eccconf1 = doc_register_readb(docg3, DOC_ECCCONF1); | 919 | eccconf1 = doc_register_readb(docg3, DOC_ECCCONF1); |
@@ -936,7 +949,8 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t from, | |||
936 | } | 949 | } |
937 | if (ret > 0) { | 950 | if (ret > 0) { |
938 | mtd->ecc_stats.corrected += ret; | 951 | mtd->ecc_stats.corrected += ret; |
939 | ret = -EUCLEAN; | 952 | max_bitflips = max(max_bitflips, ret); |
953 | ret = max_bitflips; | ||
940 | } | 954 | } |
941 | } | 955 | } |
942 | 956 | ||
@@ -1004,7 +1018,7 @@ static int doc_reload_bbt(struct docg3 *docg3) | |||
1004 | DOC_LAYOUT_PAGE_SIZE); | 1018 | DOC_LAYOUT_PAGE_SIZE); |
1005 | if (!ret) | 1019 | if (!ret) |
1006 | doc_read_page_getbytes(docg3, DOC_LAYOUT_PAGE_SIZE, | 1020 | doc_read_page_getbytes(docg3, DOC_LAYOUT_PAGE_SIZE, |
1007 | buf, 1); | 1021 | buf, 1, 0); |
1008 | buf += DOC_LAYOUT_PAGE_SIZE; | 1022 | buf += DOC_LAYOUT_PAGE_SIZE; |
1009 | } | 1023 | } |
1010 | doc_read_page_finish(docg3); | 1024 | doc_read_page_finish(docg3); |
@@ -1064,10 +1078,10 @@ static int doc_get_erase_count(struct docg3 *docg3, loff_t from) | |||
1064 | ret = doc_reset_seq(docg3); | 1078 | ret = doc_reset_seq(docg3); |
1065 | if (!ret) | 1079 | if (!ret) |
1066 | ret = doc_read_page_prepare(docg3, block0, block1, page, | 1080 | ret = doc_read_page_prepare(docg3, block0, block1, page, |
1067 | ofs + DOC_LAYOUT_WEAR_OFFSET); | 1081 | ofs + DOC_LAYOUT_WEAR_OFFSET, 0); |
1068 | if (!ret) | 1082 | if (!ret) |
1069 | ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_WEAR_SIZE, | 1083 | ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_WEAR_SIZE, |
1070 | buf, 1); | 1084 | buf, 1, 0); |
1071 | doc_read_page_finish(docg3); | 1085 | doc_read_page_finish(docg3); |
1072 | 1086 | ||
1073 | if (ret || (buf[0] != DOC_ERASE_MARK) || (buf[2] != DOC_ERASE_MARK)) | 1087 | if (ret || (buf[0] != DOC_ERASE_MARK) || (buf[2] != DOC_ERASE_MARK)) |
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 1924d247c1cb..5d0d68c3fe27 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -639,12 +639,16 @@ static const struct spi_device_id m25p_ids[] = { | |||
639 | { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) }, | 639 | { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) }, |
640 | { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, | 640 | { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, |
641 | 641 | ||
642 | /* Everspin */ | ||
643 | { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2) }, | ||
644 | |||
642 | /* Intel/Numonyx -- xxxs33b */ | 645 | /* Intel/Numonyx -- xxxs33b */ |
643 | { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, | 646 | { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, |
644 | { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) }, | 647 | { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) }, |
645 | { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) }, | 648 | { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) }, |
646 | 649 | ||
647 | /* Macronix */ | 650 | /* Macronix */ |
651 | { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) }, | ||
648 | { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, | 652 | { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, |
649 | { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, | 653 | { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, |
650 | { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) }, | 654 | { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) }, |
@@ -728,6 +732,7 @@ static const struct spi_device_id m25p_ids[] = { | |||
728 | { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, | 732 | { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, |
729 | { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, | 733 | { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, |
730 | { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, | 734 | { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, |
735 | { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, | ||
731 | 736 | ||
732 | /* Catalyst / On Semiconductor -- non-JEDEC */ | 737 | /* Catalyst / On Semiconductor -- non-JEDEC */ |
733 | { "cat25c11", CAT25_INFO( 16, 8, 16, 1) }, | 738 | { "cat25c11", CAT25_INFO( 16, 8, 16, 1) }, |
diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c index 797d43cd3550..67960362681e 100644 --- a/drivers/mtd/devices/spear_smi.c +++ b/drivers/mtd/devices/spear_smi.c | |||
@@ -990,9 +990,9 @@ static int __devinit spear_smi_probe(struct platform_device *pdev) | |||
990 | goto err_clk; | 990 | goto err_clk; |
991 | } | 991 | } |
992 | 992 | ||
993 | ret = clk_enable(dev->clk); | 993 | ret = clk_prepare_enable(dev->clk); |
994 | if (ret) | 994 | if (ret) |
995 | goto err_clk_enable; | 995 | goto err_clk_prepare_enable; |
996 | 996 | ||
997 | ret = request_irq(irq, spear_smi_int_handler, 0, pdev->name, dev); | 997 | ret = request_irq(irq, spear_smi_int_handler, 0, pdev->name, dev); |
998 | if (ret) { | 998 | if (ret) { |
@@ -1020,8 +1020,8 @@ err_bank_setup: | |||
1020 | free_irq(irq, dev); | 1020 | free_irq(irq, dev); |
1021 | platform_set_drvdata(pdev, NULL); | 1021 | platform_set_drvdata(pdev, NULL); |
1022 | err_irq: | 1022 | err_irq: |
1023 | clk_disable(dev->clk); | 1023 | clk_disable_unprepare(dev->clk); |
1024 | err_clk_enable: | 1024 | err_clk_prepare_enable: |
1025 | clk_put(dev->clk); | 1025 | clk_put(dev->clk); |
1026 | err_clk: | 1026 | err_clk: |
1027 | iounmap(dev->io_base); | 1027 | iounmap(dev->io_base); |
@@ -1074,7 +1074,7 @@ static int __devexit spear_smi_remove(struct platform_device *pdev) | |||
1074 | irq = platform_get_irq(pdev, 0); | 1074 | irq = platform_get_irq(pdev, 0); |
1075 | free_irq(irq, dev); | 1075 | free_irq(irq, dev); |
1076 | 1076 | ||
1077 | clk_disable(dev->clk); | 1077 | clk_disable_unprepare(dev->clk); |
1078 | clk_put(dev->clk); | 1078 | clk_put(dev->clk); |
1079 | iounmap(dev->io_base); | 1079 | iounmap(dev->io_base); |
1080 | kfree(dev); | 1080 | kfree(dev); |
@@ -1091,7 +1091,7 @@ int spear_smi_suspend(struct platform_device *pdev, pm_message_t state) | |||
1091 | struct spear_smi *dev = platform_get_drvdata(pdev); | 1091 | struct spear_smi *dev = platform_get_drvdata(pdev); |
1092 | 1092 | ||
1093 | if (dev && dev->clk) | 1093 | if (dev && dev->clk) |
1094 | clk_disable(dev->clk); | 1094 | clk_disable_unprepare(dev->clk); |
1095 | 1095 | ||
1096 | return 0; | 1096 | return 0; |
1097 | } | 1097 | } |
@@ -1102,7 +1102,7 @@ int spear_smi_resume(struct platform_device *pdev) | |||
1102 | int ret = -EPERM; | 1102 | int ret = -EPERM; |
1103 | 1103 | ||
1104 | if (dev && dev->clk) | 1104 | if (dev && dev->clk) |
1105 | ret = clk_enable(dev->clk); | 1105 | ret = clk_prepare_enable(dev->clk); |
1106 | 1106 | ||
1107 | if (!ret) | 1107 | if (!ret) |
1108 | spear_smi_hw_init(dev); | 1108 | spear_smi_hw_init(dev); |
diff --git a/drivers/mtd/lpddr/qinfo_probe.c b/drivers/mtd/lpddr/qinfo_probe.c index dbfe17baf046..45abed67f1ef 100644 --- a/drivers/mtd/lpddr/qinfo_probe.c +++ b/drivers/mtd/lpddr/qinfo_probe.c | |||
@@ -57,7 +57,7 @@ static struct qinfo_query_info qinfo_array[] = { | |||
57 | 57 | ||
58 | static long lpddr_get_qinforec_pos(struct map_info *map, char *id_str) | 58 | static long lpddr_get_qinforec_pos(struct map_info *map, char *id_str) |
59 | { | 59 | { |
60 | int qinfo_lines = sizeof(qinfo_array)/sizeof(struct qinfo_query_info); | 60 | int qinfo_lines = ARRAY_SIZE(qinfo_array); |
61 | int i; | 61 | int i; |
62 | int bankwidth = map_bankwidth(map) * 8; | 62 | int bankwidth = map_bankwidth(map) * 8; |
63 | int major, minor; | 63 | int major, minor; |
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 8af67cfd671a..5ba2458e799a 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
@@ -224,7 +224,7 @@ config MTD_CK804XROM | |||
224 | 224 | ||
225 | config MTD_SCB2_FLASH | 225 | config MTD_SCB2_FLASH |
226 | tristate "BIOS flash chip on Intel SCB2 boards" | 226 | tristate "BIOS flash chip on Intel SCB2 boards" |
227 | depends on X86 && MTD_JEDECPROBE | 227 | depends on X86 && MTD_JEDECPROBE && PCI |
228 | help | 228 | help |
229 | Support for treating the BIOS flash chip on Intel SCB2 boards | 229 | Support for treating the BIOS flash chip on Intel SCB2 boards |
230 | as an MTD device - with this you can reprogram your BIOS. | 230 | as an MTD device - with this you can reprogram your BIOS. |
diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c index 92e1f41634c7..93f03175c82d 100644 --- a/drivers/mtd/maps/intel_vr_nor.c +++ b/drivers/mtd/maps/intel_vr_nor.c | |||
@@ -260,18 +260,7 @@ static struct pci_driver vr_nor_pci_driver = { | |||
260 | .id_table = vr_nor_pci_ids, | 260 | .id_table = vr_nor_pci_ids, |
261 | }; | 261 | }; |
262 | 262 | ||
263 | static int __init vr_nor_mtd_init(void) | 263 | module_pci_driver(vr_nor_pci_driver); |
264 | { | ||
265 | return pci_register_driver(&vr_nor_pci_driver); | ||
266 | } | ||
267 | |||
268 | static void __exit vr_nor_mtd_exit(void) | ||
269 | { | ||
270 | pci_unregister_driver(&vr_nor_pci_driver); | ||
271 | } | ||
272 | |||
273 | module_init(vr_nor_mtd_init); | ||
274 | module_exit(vr_nor_mtd_exit); | ||
275 | 264 | ||
276 | MODULE_AUTHOR("Andy Lowe"); | 265 | MODULE_AUTHOR("Andy Lowe"); |
277 | MODULE_DESCRIPTION("MTD map driver for NOR flash on Intel Vermilion Range"); | 266 | MODULE_DESCRIPTION("MTD map driver for NOR flash on Intel Vermilion Range"); |
diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c index 1d005a3e9b41..f14ce0af763f 100644 --- a/drivers/mtd/maps/pci.c +++ b/drivers/mtd/maps/pci.c | |||
@@ -352,18 +352,7 @@ static struct pci_driver mtd_pci_driver = { | |||
352 | .id_table = mtd_pci_ids, | 352 | .id_table = mtd_pci_ids, |
353 | }; | 353 | }; |
354 | 354 | ||
355 | static int __init mtd_pci_maps_init(void) | 355 | module_pci_driver(mtd_pci_driver); |
356 | { | ||
357 | return pci_register_driver(&mtd_pci_driver); | ||
358 | } | ||
359 | |||
360 | static void __exit mtd_pci_maps_exit(void) | ||
361 | { | ||
362 | pci_unregister_driver(&mtd_pci_driver); | ||
363 | } | ||
364 | |||
365 | module_init(mtd_pci_maps_init); | ||
366 | module_exit(mtd_pci_maps_exit); | ||
367 | 356 | ||
368 | MODULE_LICENSE("GPL"); | 357 | MODULE_LICENSE("GPL"); |
369 | MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); | 358 | MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); |
diff --git a/drivers/mtd/maps/scb2_flash.c b/drivers/mtd/maps/scb2_flash.c index 934a72c80078..9dcbc684abdb 100644 --- a/drivers/mtd/maps/scb2_flash.c +++ b/drivers/mtd/maps/scb2_flash.c | |||
@@ -234,20 +234,7 @@ static struct pci_driver scb2_flash_driver = { | |||
234 | .remove = __devexit_p(scb2_flash_remove), | 234 | .remove = __devexit_p(scb2_flash_remove), |
235 | }; | 235 | }; |
236 | 236 | ||
237 | static int __init | 237 | module_pci_driver(scb2_flash_driver); |
238 | scb2_flash_init(void) | ||
239 | { | ||
240 | return pci_register_driver(&scb2_flash_driver); | ||
241 | } | ||
242 | |||
243 | static void __exit | ||
244 | scb2_flash_exit(void) | ||
245 | { | ||
246 | pci_unregister_driver(&scb2_flash_driver); | ||
247 | } | ||
248 | |||
249 | module_init(scb2_flash_init); | ||
250 | module_exit(scb2_flash_exit); | ||
251 | 238 | ||
252 | MODULE_LICENSE("GPL"); | 239 | MODULE_LICENSE("GPL"); |
253 | MODULE_AUTHOR("Tim Hockin <thockin@sun.com>"); | 240 | MODULE_AUTHOR("Tim Hockin <thockin@sun.com>"); |
diff --git a/drivers/mtd/maps/wr_sbc82xx_flash.c b/drivers/mtd/maps/wr_sbc82xx_flash.c index 71b0ba797912..e7534c82f93a 100644 --- a/drivers/mtd/maps/wr_sbc82xx_flash.c +++ b/drivers/mtd/maps/wr_sbc82xx_flash.c | |||
@@ -59,7 +59,7 @@ static struct mtd_partition bigflash_parts[] = { | |||
59 | } | 59 | } |
60 | }; | 60 | }; |
61 | 61 | ||
62 | static const char *part_probes[] __initdata = {"cmdlinepart", "RedBoot", NULL}; | 62 | static const char *part_probes[] __initconst = {"cmdlinepart", "RedBoot", NULL}; |
63 | 63 | ||
64 | #define init_sbc82xx_one_flash(map, br, or) \ | 64 | #define init_sbc82xx_one_flash(map, br, or) \ |
65 | do { \ | 65 | do { \ |
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index c837507dfb1c..575730744fdb 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c | |||
@@ -250,6 +250,43 @@ static ssize_t mtd_name_show(struct device *dev, | |||
250 | } | 250 | } |
251 | static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL); | 251 | static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL); |
252 | 252 | ||
253 | static ssize_t mtd_ecc_strength_show(struct device *dev, | ||
254 | struct device_attribute *attr, char *buf) | ||
255 | { | ||
256 | struct mtd_info *mtd = dev_get_drvdata(dev); | ||
257 | |||
258 | return snprintf(buf, PAGE_SIZE, "%u\n", mtd->ecc_strength); | ||
259 | } | ||
260 | static DEVICE_ATTR(ecc_strength, S_IRUGO, mtd_ecc_strength_show, NULL); | ||
261 | |||
262 | static ssize_t mtd_bitflip_threshold_show(struct device *dev, | ||
263 | struct device_attribute *attr, | ||
264 | char *buf) | ||
265 | { | ||
266 | struct mtd_info *mtd = dev_get_drvdata(dev); | ||
267 | |||
268 | return snprintf(buf, PAGE_SIZE, "%u\n", mtd->bitflip_threshold); | ||
269 | } | ||
270 | |||
271 | static ssize_t mtd_bitflip_threshold_store(struct device *dev, | ||
272 | struct device_attribute *attr, | ||
273 | const char *buf, size_t count) | ||
274 | { | ||
275 | struct mtd_info *mtd = dev_get_drvdata(dev); | ||
276 | unsigned int bitflip_threshold; | ||
277 | int retval; | ||
278 | |||
279 | retval = kstrtouint(buf, 0, &bitflip_threshold); | ||
280 | if (retval) | ||
281 | return retval; | ||
282 | |||
283 | mtd->bitflip_threshold = bitflip_threshold; | ||
284 | return count; | ||
285 | } | ||
286 | static DEVICE_ATTR(bitflip_threshold, S_IRUGO | S_IWUSR, | ||
287 | mtd_bitflip_threshold_show, | ||
288 | mtd_bitflip_threshold_store); | ||
289 | |||
253 | static struct attribute *mtd_attrs[] = { | 290 | static struct attribute *mtd_attrs[] = { |
254 | &dev_attr_type.attr, | 291 | &dev_attr_type.attr, |
255 | &dev_attr_flags.attr, | 292 | &dev_attr_flags.attr, |
@@ -260,6 +297,8 @@ static struct attribute *mtd_attrs[] = { | |||
260 | &dev_attr_oobsize.attr, | 297 | &dev_attr_oobsize.attr, |
261 | &dev_attr_numeraseregions.attr, | 298 | &dev_attr_numeraseregions.attr, |
262 | &dev_attr_name.attr, | 299 | &dev_attr_name.attr, |
300 | &dev_attr_ecc_strength.attr, | ||
301 | &dev_attr_bitflip_threshold.attr, | ||
263 | NULL, | 302 | NULL, |
264 | }; | 303 | }; |
265 | 304 | ||
@@ -322,6 +361,10 @@ int add_mtd_device(struct mtd_info *mtd) | |||
322 | mtd->index = i; | 361 | mtd->index = i; |
323 | mtd->usecount = 0; | 362 | mtd->usecount = 0; |
324 | 363 | ||
364 | /* default value if not set by driver */ | ||
365 | if (mtd->bitflip_threshold == 0) | ||
366 | mtd->bitflip_threshold = mtd->ecc_strength; | ||
367 | |||
325 | if (is_power_of_2(mtd->erasesize)) | 368 | if (is_power_of_2(mtd->erasesize)) |
326 | mtd->erasesize_shift = ffs(mtd->erasesize) - 1; | 369 | mtd->erasesize_shift = ffs(mtd->erasesize) - 1; |
327 | else | 370 | else |
@@ -757,12 +800,24 @@ EXPORT_SYMBOL_GPL(mtd_get_unmapped_area); | |||
757 | int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, | 800 | int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, |
758 | u_char *buf) | 801 | u_char *buf) |
759 | { | 802 | { |
803 | int ret_code; | ||
760 | *retlen = 0; | 804 | *retlen = 0; |
761 | if (from < 0 || from > mtd->size || len > mtd->size - from) | 805 | if (from < 0 || from > mtd->size || len > mtd->size - from) |
762 | return -EINVAL; | 806 | return -EINVAL; |
763 | if (!len) | 807 | if (!len) |
764 | return 0; | 808 | return 0; |
765 | return mtd->_read(mtd, from, len, retlen, buf); | 809 | |
810 | /* | ||
811 | * In the absence of an error, drivers return a non-negative integer | ||
812 | * representing the maximum number of bitflips that were corrected on | ||
813 | * any one ecc region (if applicable; zero otherwise). | ||
814 | */ | ||
815 | ret_code = mtd->_read(mtd, from, len, retlen, buf); | ||
816 | if (unlikely(ret_code < 0)) | ||
817 | return ret_code; | ||
818 | if (mtd->ecc_strength == 0) | ||
819 | return 0; /* device lacks ecc */ | ||
820 | return ret_code >= mtd->bitflip_threshold ? -EUCLEAN : 0; | ||
766 | } | 821 | } |
767 | EXPORT_SYMBOL_GPL(mtd_read); | 822 | EXPORT_SYMBOL_GPL(mtd_read); |
768 | 823 | ||
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 9651c06de0a9..d518e4db8a0b 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c | |||
@@ -67,12 +67,12 @@ static int part_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
67 | stats = part->master->ecc_stats; | 67 | stats = part->master->ecc_stats; |
68 | res = part->master->_read(part->master, from + part->offset, len, | 68 | res = part->master->_read(part->master, from + part->offset, len, |
69 | retlen, buf); | 69 | retlen, buf); |
70 | if (unlikely(res)) { | 70 | if (unlikely(mtd_is_eccerr(res))) |
71 | if (mtd_is_bitflip(res)) | 71 | mtd->ecc_stats.failed += |
72 | mtd->ecc_stats.corrected += part->master->ecc_stats.corrected - stats.corrected; | 72 | part->master->ecc_stats.failed - stats.failed; |
73 | if (mtd_is_eccerr(res)) | 73 | else |
74 | mtd->ecc_stats.failed += part->master->ecc_stats.failed - stats.failed; | 74 | mtd->ecc_stats.corrected += |
75 | } | 75 | part->master->ecc_stats.corrected - stats.corrected; |
76 | return res; | 76 | return res; |
77 | } | 77 | } |
78 | 78 | ||
@@ -517,6 +517,8 @@ static struct mtd_part *allocate_partition(struct mtd_info *master, | |||
517 | 517 | ||
518 | slave->mtd.ecclayout = master->ecclayout; | 518 | slave->mtd.ecclayout = master->ecclayout; |
519 | slave->mtd.ecc_strength = master->ecc_strength; | 519 | slave->mtd.ecc_strength = master->ecc_strength; |
520 | slave->mtd.bitflip_threshold = master->bitflip_threshold; | ||
521 | |||
520 | if (master->_block_isbad) { | 522 | if (master->_block_isbad) { |
521 | uint64_t offs = 0; | 523 | uint64_t offs = 0; |
522 | 524 | ||
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 7d17cecad69d..31bb7e5b504a 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -115,6 +115,46 @@ config MTD_NAND_OMAP2 | |||
115 | Support for NAND flash on Texas Instruments OMAP2, OMAP3 and OMAP4 | 115 | Support for NAND flash on Texas Instruments OMAP2, OMAP3 and OMAP4 |
116 | platforms. | 116 | platforms. |
117 | 117 | ||
118 | config MTD_NAND_OMAP_BCH | ||
119 | depends on MTD_NAND && MTD_NAND_OMAP2 && ARCH_OMAP3 | ||
120 | bool "Enable support for hardware BCH error correction" | ||
121 | default n | ||
122 | select BCH | ||
123 | select BCH_CONST_PARAMS | ||
124 | help | ||
125 | Support for hardware BCH error correction. | ||
126 | |||
127 | choice | ||
128 | prompt "BCH error correction capability" | ||
129 | depends on MTD_NAND_OMAP_BCH | ||
130 | |||
131 | config MTD_NAND_OMAP_BCH8 | ||
132 | bool "8 bits / 512 bytes (recommended)" | ||
133 | help | ||
134 | Support correcting up to 8 bitflips per 512-byte block. | ||
135 | This will use 13 bytes of spare area per 512 bytes of page data. | ||
136 | This is the recommended mode, as 4-bit mode does not work | ||
137 | on some OMAP3 revisions, due to a hardware bug. | ||
138 | |||
139 | config MTD_NAND_OMAP_BCH4 | ||
140 | bool "4 bits / 512 bytes" | ||
141 | help | ||
142 | Support correcting up to 4 bitflips per 512-byte block. | ||
143 | This will use 7 bytes of spare area per 512 bytes of page data. | ||
144 | Note that this mode does not work on some OMAP3 revisions, due to a | ||
145 | hardware bug. Please check your OMAP datasheet before selecting this | ||
146 | mode. | ||
147 | |||
148 | endchoice | ||
149 | |||
150 | if MTD_NAND_OMAP_BCH | ||
151 | config BCH_CONST_M | ||
152 | default 13 | ||
153 | config BCH_CONST_T | ||
154 | default 4 if MTD_NAND_OMAP_BCH4 | ||
155 | default 8 if MTD_NAND_OMAP_BCH8 | ||
156 | endif | ||
157 | |||
118 | config MTD_NAND_IDS | 158 | config MTD_NAND_IDS |
119 | tristate | 159 | tristate |
120 | 160 | ||
@@ -440,7 +480,7 @@ config MTD_NAND_NANDSIM | |||
440 | 480 | ||
441 | config MTD_NAND_GPMI_NAND | 481 | config MTD_NAND_GPMI_NAND |
442 | bool "GPMI NAND Flash Controller driver" | 482 | bool "GPMI NAND Flash Controller driver" |
443 | depends on MTD_NAND && (SOC_IMX23 || SOC_IMX28) | 483 | depends on MTD_NAND && (SOC_IMX23 || SOC_IMX28 || SOC_IMX6Q) |
444 | help | 484 | help |
445 | Enables NAND Flash support for IMX23 or IMX28. | 485 | Enables NAND Flash support for IMX23 or IMX28. |
446 | The GPMI controller is very powerful, with the help of BCH | 486 | The GPMI controller is very powerful, with the help of BCH |
diff --git a/drivers/mtd/nand/alauda.c b/drivers/mtd/nand/alauda.c index 4f20e1d8bef1..60a0dfdb0808 100644 --- a/drivers/mtd/nand/alauda.c +++ b/drivers/mtd/nand/alauda.c | |||
@@ -414,7 +414,7 @@ static int alauda_bounce_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
414 | } | 414 | } |
415 | err = 0; | 415 | err = 0; |
416 | if (corrected) | 416 | if (corrected) |
417 | err = -EUCLEAN; | 417 | err = 1; /* return max_bitflips per ecc step */ |
418 | if (uncorrected) | 418 | if (uncorrected) |
419 | err = -EBADMSG; | 419 | err = -EBADMSG; |
420 | out: | 420 | out: |
@@ -446,7 +446,7 @@ static int alauda_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
446 | } | 446 | } |
447 | err = 0; | 447 | err = 0; |
448 | if (corrected) | 448 | if (corrected) |
449 | err = -EUCLEAN; | 449 | err = 1; /* return max_bitflips per ecc step */ |
450 | if (uncorrected) | 450 | if (uncorrected) |
451 | err = -EBADMSG; | 451 | err = -EBADMSG; |
452 | return err; | 452 | return err; |
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 2165576a1c67..97ac6712bb19 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
@@ -324,9 +324,10 @@ static int atmel_nand_calculate(struct mtd_info *mtd, | |||
324 | * mtd: mtd info structure | 324 | * mtd: mtd info structure |
325 | * chip: nand chip info structure | 325 | * chip: nand chip info structure |
326 | * buf: buffer to store read data | 326 | * buf: buffer to store read data |
327 | * oob_required: caller expects OOB data read to chip->oob_poi | ||
327 | */ | 328 | */ |
328 | static int atmel_nand_read_page(struct mtd_info *mtd, | 329 | static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, |
329 | struct nand_chip *chip, uint8_t *buf, int page) | 330 | uint8_t *buf, int oob_required, int page) |
330 | { | 331 | { |
331 | int eccsize = chip->ecc.size; | 332 | int eccsize = chip->ecc.size; |
332 | int eccbytes = chip->ecc.bytes; | 333 | int eccbytes = chip->ecc.bytes; |
@@ -335,6 +336,7 @@ static int atmel_nand_read_page(struct mtd_info *mtd, | |||
335 | uint8_t *oob = chip->oob_poi; | 336 | uint8_t *oob = chip->oob_poi; |
336 | uint8_t *ecc_pos; | 337 | uint8_t *ecc_pos; |
337 | int stat; | 338 | int stat; |
339 | unsigned int max_bitflips = 0; | ||
338 | 340 | ||
339 | /* | 341 | /* |
340 | * Errata: ALE is incorrectly wired up to the ECC controller | 342 | * Errata: ALE is incorrectly wired up to the ECC controller |
@@ -371,10 +373,12 @@ static int atmel_nand_read_page(struct mtd_info *mtd, | |||
371 | /* check if there's an error */ | 373 | /* check if there's an error */ |
372 | stat = chip->ecc.correct(mtd, p, oob, NULL); | 374 | stat = chip->ecc.correct(mtd, p, oob, NULL); |
373 | 375 | ||
374 | if (stat < 0) | 376 | if (stat < 0) { |
375 | mtd->ecc_stats.failed++; | 377 | mtd->ecc_stats.failed++; |
376 | else | 378 | } else { |
377 | mtd->ecc_stats.corrected += stat; | 379 | mtd->ecc_stats.corrected += stat; |
380 | max_bitflips = max_t(unsigned int, max_bitflips, stat); | ||
381 | } | ||
378 | 382 | ||
379 | /* get back to oob start (end of page) */ | 383 | /* get back to oob start (end of page) */ |
380 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1); | 384 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1); |
@@ -382,7 +386,7 @@ static int atmel_nand_read_page(struct mtd_info *mtd, | |||
382 | /* read the oob */ | 386 | /* read the oob */ |
383 | chip->read_buf(mtd, oob, mtd->oobsize); | 387 | chip->read_buf(mtd, oob, mtd->oobsize); |
384 | 388 | ||
385 | return 0; | 389 | return max_bitflips; |
386 | } | 390 | } |
387 | 391 | ||
388 | /* | 392 | /* |
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 73abbc3e093e..9f609d2dcf62 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c | |||
@@ -508,8 +508,6 @@ static int __devinit au1550nd_probe(struct platform_device *pdev) | |||
508 | this->chip_delay = 30; | 508 | this->chip_delay = 30; |
509 | this->ecc.mode = NAND_ECC_SOFT; | 509 | this->ecc.mode = NAND_ECC_SOFT; |
510 | 510 | ||
511 | this->options = NAND_NO_AUTOINCR; | ||
512 | |||
513 | if (pd->devwidth) | 511 | if (pd->devwidth) |
514 | this->options |= NAND_BUSWIDTH_16; | 512 | this->options |= NAND_BUSWIDTH_16; |
515 | 513 | ||
diff --git a/drivers/mtd/nand/bcm_umi_bch.c b/drivers/mtd/nand/bcm_umi_bch.c index a930666d0687..5914bb32e001 100644 --- a/drivers/mtd/nand/bcm_umi_bch.c +++ b/drivers/mtd/nand/bcm_umi_bch.c | |||
@@ -22,9 +22,9 @@ | |||
22 | 22 | ||
23 | /* ---- Private Function Prototypes -------------------------------------- */ | 23 | /* ---- Private Function Prototypes -------------------------------------- */ |
24 | static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, | 24 | static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, |
25 | struct nand_chip *chip, uint8_t *buf, int page); | 25 | struct nand_chip *chip, uint8_t *buf, int oob_required, int page); |
26 | static void bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd, | 26 | static void bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd, |
27 | struct nand_chip *chip, const uint8_t *buf); | 27 | struct nand_chip *chip, const uint8_t *buf, int oob_required); |
28 | 28 | ||
29 | /* ---- Private Variables ------------------------------------------------ */ | 29 | /* ---- Private Variables ------------------------------------------------ */ |
30 | 30 | ||
@@ -103,11 +103,12 @@ static struct nand_ecclayout nand_hw_eccoob_4096 = { | |||
103 | * @mtd: mtd info structure | 103 | * @mtd: mtd info structure |
104 | * @chip: nand chip info structure | 104 | * @chip: nand chip info structure |
105 | * @buf: buffer to store read data | 105 | * @buf: buffer to store read data |
106 | * @oob_required: caller expects OOB data read to chip->oob_poi | ||
106 | * | 107 | * |
107 | ***************************************************************************/ | 108 | ***************************************************************************/ |
108 | static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, | 109 | static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, |
109 | struct nand_chip *chip, uint8_t * buf, | 110 | struct nand_chip *chip, uint8_t * buf, |
110 | int page) | 111 | int oob_required, int page) |
111 | { | 112 | { |
112 | int sectorIdx = 0; | 113 | int sectorIdx = 0; |
113 | int eccsize = chip->ecc.size; | 114 | int eccsize = chip->ecc.size; |
@@ -116,6 +117,7 @@ static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, | |||
116 | uint8_t eccCalc[NAND_ECC_NUM_BYTES]; | 117 | uint8_t eccCalc[NAND_ECC_NUM_BYTES]; |
117 | int sectorOobSize = mtd->oobsize / eccsteps; | 118 | int sectorOobSize = mtd->oobsize / eccsteps; |
118 | int stat; | 119 | int stat; |
120 | unsigned int max_bitflips = 0; | ||
119 | 121 | ||
120 | for (sectorIdx = 0; sectorIdx < eccsteps; | 122 | for (sectorIdx = 0; sectorIdx < eccsteps; |
121 | sectorIdx++, datap += eccsize) { | 123 | sectorIdx++, datap += eccsize) { |
@@ -177,9 +179,10 @@ static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, | |||
177 | } | 179 | } |
178 | #endif | 180 | #endif |
179 | mtd->ecc_stats.corrected += stat; | 181 | mtd->ecc_stats.corrected += stat; |
182 | max_bitflips = max_t(unsigned int, max_bitflips, stat); | ||
180 | } | 183 | } |
181 | } | 184 | } |
182 | return 0; | 185 | return max_bitflips; |
183 | } | 186 | } |
184 | 187 | ||
185 | /**************************************************************************** | 188 | /**************************************************************************** |
@@ -188,10 +191,11 @@ static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, | |||
188 | * @mtd: mtd info structure | 191 | * @mtd: mtd info structure |
189 | * @chip: nand chip info structure | 192 | * @chip: nand chip info structure |
190 | * @buf: data buffer | 193 | * @buf: data buffer |
194 | * @oob_required: must write chip->oob_poi to OOB | ||
191 | * | 195 | * |
192 | ***************************************************************************/ | 196 | ***************************************************************************/ |
193 | static void bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd, | 197 | static void bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd, |
194 | struct nand_chip *chip, const uint8_t *buf) | 198 | struct nand_chip *chip, const uint8_t *buf, int oob_required) |
195 | { | 199 | { |
196 | int sectorIdx = 0; | 200 | int sectorIdx = 0; |
197 | int eccsize = chip->ecc.size; | 201 | int eccsize = chip->ecc.size; |
diff --git a/drivers/mtd/nand/bcm_umi_nand.c b/drivers/mtd/nand/bcm_umi_nand.c index 6908cdde3065..c855e7cd337b 100644 --- a/drivers/mtd/nand/bcm_umi_nand.c +++ b/drivers/mtd/nand/bcm_umi_nand.c | |||
@@ -341,7 +341,7 @@ static int bcm_umi_nand_verify_buf(struct mtd_info *mtd, const u_char * buf, | |||
341 | * for MLC parts which may have permanently stuck bits. | 341 | * for MLC parts which may have permanently stuck bits. |
342 | */ | 342 | */ |
343 | struct nand_chip *chip = mtd->priv; | 343 | struct nand_chip *chip = mtd->priv; |
344 | int ret = chip->ecc.read_page(mtd, chip, readbackbuf, 0); | 344 | int ret = chip->ecc.read_page(mtd, chip, readbackbuf, 0, 0); |
345 | if (ret < 0) | 345 | if (ret < 0) |
346 | return -EFAULT; | 346 | return -EFAULT; |
347 | else { | 347 | else { |
@@ -476,12 +476,7 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev) | |||
476 | this->badblock_pattern = &largepage_bbt; | 476 | this->badblock_pattern = &largepage_bbt; |
477 | } | 477 | } |
478 | 478 | ||
479 | /* | 479 | this->ecc.strength = 8; |
480 | * FIXME: ecc strength value of 6 bits per 512 bytes of data is a | ||
481 | * conservative guess, given 13 ecc bytes and using bch alg. | ||
482 | * (Assume Galois field order m=15 to allow a margin of error.) | ||
483 | */ | ||
484 | this->ecc.strength = 6; | ||
485 | 480 | ||
486 | #endif | 481 | #endif |
487 | 482 | ||
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index d7b86b925de5..3f1c18599cbd 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c | |||
@@ -558,7 +558,7 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd, | |||
558 | } | 558 | } |
559 | 559 | ||
560 | static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | 560 | static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, |
561 | uint8_t *buf, int page) | 561 | uint8_t *buf, int oob_required, int page) |
562 | { | 562 | { |
563 | bf5xx_nand_read_buf(mtd, buf, mtd->writesize); | 563 | bf5xx_nand_read_buf(mtd, buf, mtd->writesize); |
564 | bf5xx_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize); | 564 | bf5xx_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize); |
@@ -567,7 +567,7 @@ static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip | |||
567 | } | 567 | } |
568 | 568 | ||
569 | static void bf5xx_nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | 569 | static void bf5xx_nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, |
570 | const uint8_t *buf) | 570 | const uint8_t *buf, int oob_required) |
571 | { | 571 | { |
572 | bf5xx_nand_write_buf(mtd, buf, mtd->writesize); | 572 | bf5xx_nand_write_buf(mtd, buf, mtd->writesize); |
573 | bf5xx_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize); | 573 | bf5xx_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize); |
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index 2a96e1a12062..41371ba1a811 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c | |||
@@ -364,25 +364,27 @@ static int cafe_nand_write_oob(struct mtd_info *mtd, | |||
364 | 364 | ||
365 | /* Don't use -- use nand_read_oob_std for now */ | 365 | /* Don't use -- use nand_read_oob_std for now */ |
366 | static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, | 366 | static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, |
367 | int page, int sndcmd) | 367 | int page) |
368 | { | 368 | { |
369 | chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); | 369 | chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); |
370 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | 370 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |
371 | return 1; | 371 | return 0; |
372 | } | 372 | } |
373 | /** | 373 | /** |
374 | * cafe_nand_read_page_syndrome - [REPLACEABLE] hardware ecc syndrome based page read | 374 | * cafe_nand_read_page_syndrome - [REPLACEABLE] hardware ecc syndrome based page read |
375 | * @mtd: mtd info structure | 375 | * @mtd: mtd info structure |
376 | * @chip: nand chip info structure | 376 | * @chip: nand chip info structure |
377 | * @buf: buffer to store read data | 377 | * @buf: buffer to store read data |
378 | * @oob_required: caller expects OOB data read to chip->oob_poi | ||
378 | * | 379 | * |
379 | * The hw generator calculates the error syndrome automatically. Therefor | 380 | * The hw generator calculates the error syndrome automatically. Therefor |
380 | * we need a special oob layout and handling. | 381 | * we need a special oob layout and handling. |
381 | */ | 382 | */ |
382 | static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, | 383 | static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, |
383 | uint8_t *buf, int page) | 384 | uint8_t *buf, int oob_required, int page) |
384 | { | 385 | { |
385 | struct cafe_priv *cafe = mtd->priv; | 386 | struct cafe_priv *cafe = mtd->priv; |
387 | unsigned int max_bitflips = 0; | ||
386 | 388 | ||
387 | cafe_dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n", | 389 | cafe_dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n", |
388 | cafe_readl(cafe, NAND_ECC_RESULT), | 390 | cafe_readl(cafe, NAND_ECC_RESULT), |
@@ -449,10 +451,11 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
449 | } else { | 451 | } else { |
450 | dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", n); | 452 | dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", n); |
451 | mtd->ecc_stats.corrected += n; | 453 | mtd->ecc_stats.corrected += n; |
454 | max_bitflips = max_t(unsigned int, max_bitflips, n); | ||
452 | } | 455 | } |
453 | } | 456 | } |
454 | 457 | ||
455 | return 0; | 458 | return max_bitflips; |
456 | } | 459 | } |
457 | 460 | ||
458 | static struct nand_ecclayout cafe_oobinfo_2048 = { | 461 | static struct nand_ecclayout cafe_oobinfo_2048 = { |
@@ -518,7 +521,8 @@ static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = { | |||
518 | 521 | ||
519 | 522 | ||
520 | static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd, | 523 | static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd, |
521 | struct nand_chip *chip, const uint8_t *buf) | 524 | struct nand_chip *chip, |
525 | const uint8_t *buf, int oob_required) | ||
522 | { | 526 | { |
523 | struct cafe_priv *cafe = mtd->priv; | 527 | struct cafe_priv *cafe = mtd->priv; |
524 | 528 | ||
@@ -530,16 +534,17 @@ static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd, | |||
530 | } | 534 | } |
531 | 535 | ||
532 | static int cafe_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, | 536 | static int cafe_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, |
533 | const uint8_t *buf, int page, int cached, int raw) | 537 | const uint8_t *buf, int oob_required, int page, |
538 | int cached, int raw) | ||
534 | { | 539 | { |
535 | int status; | 540 | int status; |
536 | 541 | ||
537 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); | 542 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); |
538 | 543 | ||
539 | if (unlikely(raw)) | 544 | if (unlikely(raw)) |
540 | chip->ecc.write_page_raw(mtd, chip, buf); | 545 | chip->ecc.write_page_raw(mtd, chip, buf, oob_required); |
541 | else | 546 | else |
542 | chip->ecc.write_page(mtd, chip, buf); | 547 | chip->ecc.write_page(mtd, chip, buf, oob_required); |
543 | 548 | ||
544 | /* | 549 | /* |
545 | * Cached progamming disabled for now, Not sure if its worth the | 550 | * Cached progamming disabled for now, Not sure if its worth the |
@@ -685,7 +690,7 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, | |||
685 | 690 | ||
686 | /* Enable the following for a flash based bad block table */ | 691 | /* Enable the following for a flash based bad block table */ |
687 | cafe->nand.bbt_options = NAND_BBT_USE_FLASH; | 692 | cafe->nand.bbt_options = NAND_BBT_USE_FLASH; |
688 | cafe->nand.options = NAND_NO_AUTOINCR | NAND_OWN_BUFFERS; | 693 | cafe->nand.options = NAND_OWN_BUFFERS; |
689 | 694 | ||
690 | if (skipbbt) { | 695 | if (skipbbt) { |
691 | cafe->nand.options |= NAND_SKIP_BBTSCAN; | 696 | cafe->nand.options |= NAND_SKIP_BBTSCAN; |
@@ -888,17 +893,7 @@ static struct pci_driver cafe_nand_pci_driver = { | |||
888 | .resume = cafe_nand_resume, | 893 | .resume = cafe_nand_resume, |
889 | }; | 894 | }; |
890 | 895 | ||
891 | static int __init cafe_nand_init(void) | 896 | module_pci_driver(cafe_nand_pci_driver); |
892 | { | ||
893 | return pci_register_driver(&cafe_nand_pci_driver); | ||
894 | } | ||
895 | |||
896 | static void __exit cafe_nand_exit(void) | ||
897 | { | ||
898 | pci_unregister_driver(&cafe_nand_pci_driver); | ||
899 | } | ||
900 | module_init(cafe_nand_init); | ||
901 | module_exit(cafe_nand_exit); | ||
902 | 897 | ||
903 | MODULE_LICENSE("GPL"); | 898 | MODULE_LICENSE("GPL"); |
904 | MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); | 899 | MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); |
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c index 821c34c62500..adb6c3ef37fb 100644 --- a/drivers/mtd/nand/cs553x_nand.c +++ b/drivers/mtd/nand/cs553x_nand.c | |||
@@ -240,7 +240,6 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) | |||
240 | 240 | ||
241 | /* Enable the following for a flash based bad block table */ | 241 | /* Enable the following for a flash based bad block table */ |
242 | this->bbt_options = NAND_BBT_USE_FLASH; | 242 | this->bbt_options = NAND_BBT_USE_FLASH; |
243 | this->options = NAND_NO_AUTOINCR; | ||
244 | 243 | ||
245 | /* Scan to find existence of the device */ | 244 | /* Scan to find existence of the device */ |
246 | if (nand_scan(new_mtd, 1)) { | 245 | if (nand_scan(new_mtd, 1)) { |
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index a9e57d686297..0650aafa0dd2 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c | |||
@@ -924,9 +924,10 @@ bool is_erased(uint8_t *buf, int len) | |||
924 | #define ECC_LAST_ERR(x) ((x) & ERR_CORRECTION_INFO__LAST_ERR_INFO) | 924 | #define ECC_LAST_ERR(x) ((x) & ERR_CORRECTION_INFO__LAST_ERR_INFO) |
925 | 925 | ||
926 | static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, | 926 | static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, |
927 | uint32_t irq_status) | 927 | uint32_t irq_status, unsigned int *max_bitflips) |
928 | { | 928 | { |
929 | bool check_erased_page = false; | 929 | bool check_erased_page = false; |
930 | unsigned int bitflips = 0; | ||
930 | 931 | ||
931 | if (irq_status & INTR_STATUS__ECC_ERR) { | 932 | if (irq_status & INTR_STATUS__ECC_ERR) { |
932 | /* read the ECC errors. we'll ignore them for now */ | 933 | /* read the ECC errors. we'll ignore them for now */ |
@@ -965,6 +966,7 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, | |||
965 | /* correct the ECC error */ | 966 | /* correct the ECC error */ |
966 | buf[offset] ^= err_correction_value; | 967 | buf[offset] ^= err_correction_value; |
967 | denali->mtd.ecc_stats.corrected++; | 968 | denali->mtd.ecc_stats.corrected++; |
969 | bitflips++; | ||
968 | } | 970 | } |
969 | } else { | 971 | } else { |
970 | /* if the error is not correctable, need to | 972 | /* if the error is not correctable, need to |
@@ -984,6 +986,7 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, | |||
984 | clear_interrupts(denali); | 986 | clear_interrupts(denali); |
985 | denali_set_intr_modes(denali, true); | 987 | denali_set_intr_modes(denali, true); |
986 | } | 988 | } |
989 | *max_bitflips = bitflips; | ||
987 | return check_erased_page; | 990 | return check_erased_page; |
988 | } | 991 | } |
989 | 992 | ||
@@ -1084,7 +1087,7 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1084 | * by write_page above. | 1087 | * by write_page above. |
1085 | * */ | 1088 | * */ |
1086 | static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, | 1089 | static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, |
1087 | const uint8_t *buf) | 1090 | const uint8_t *buf, int oob_required) |
1088 | { | 1091 | { |
1089 | /* for regular page writes, we let HW handle all the ECC | 1092 | /* for regular page writes, we let HW handle all the ECC |
1090 | * data written to the device. */ | 1093 | * data written to the device. */ |
@@ -1096,7 +1099,7 @@ static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1096 | * write_page() function above. | 1099 | * write_page() function above. |
1097 | */ | 1100 | */ |
1098 | static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | 1101 | static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, |
1099 | const uint8_t *buf) | 1102 | const uint8_t *buf, int oob_required) |
1100 | { | 1103 | { |
1101 | /* for raw page writes, we want to disable ECC and simply write | 1104 | /* for raw page writes, we want to disable ECC and simply write |
1102 | whatever data is in the buffer. */ | 1105 | whatever data is in the buffer. */ |
@@ -1110,17 +1113,17 @@ static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip, | |||
1110 | } | 1113 | } |
1111 | 1114 | ||
1112 | static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip, | 1115 | static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip, |
1113 | int page, int sndcmd) | 1116 | int page) |
1114 | { | 1117 | { |
1115 | read_oob_data(mtd, chip->oob_poi, page); | 1118 | read_oob_data(mtd, chip->oob_poi, page); |
1116 | 1119 | ||
1117 | return 0; /* notify NAND core to send command to | 1120 | return 0; |
1118 | NAND device. */ | ||
1119 | } | 1121 | } |
1120 | 1122 | ||
1121 | static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, | 1123 | static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, |
1122 | uint8_t *buf, int page) | 1124 | uint8_t *buf, int oob_required, int page) |
1123 | { | 1125 | { |
1126 | unsigned int max_bitflips; | ||
1124 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 1127 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1125 | 1128 | ||
1126 | dma_addr_t addr = denali->buf.dma_buf; | 1129 | dma_addr_t addr = denali->buf.dma_buf; |
@@ -1153,7 +1156,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1153 | 1156 | ||
1154 | memcpy(buf, denali->buf.buf, mtd->writesize); | 1157 | memcpy(buf, denali->buf.buf, mtd->writesize); |
1155 | 1158 | ||
1156 | check_erased_page = handle_ecc(denali, buf, irq_status); | 1159 | check_erased_page = handle_ecc(denali, buf, irq_status, &max_bitflips); |
1157 | denali_enable_dma(denali, false); | 1160 | denali_enable_dma(denali, false); |
1158 | 1161 | ||
1159 | if (check_erased_page) { | 1162 | if (check_erased_page) { |
@@ -1167,11 +1170,11 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1167 | denali->mtd.ecc_stats.failed++; | 1170 | denali->mtd.ecc_stats.failed++; |
1168 | } | 1171 | } |
1169 | } | 1172 | } |
1170 | return 0; | 1173 | return max_bitflips; |
1171 | } | 1174 | } |
1172 | 1175 | ||
1173 | static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | 1176 | static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, |
1174 | uint8_t *buf, int page) | 1177 | uint8_t *buf, int oob_required, int page) |
1175 | { | 1178 | { |
1176 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 1179 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1177 | 1180 | ||
@@ -1702,17 +1705,4 @@ static struct pci_driver denali_pci_driver = { | |||
1702 | .remove = denali_pci_remove, | 1705 | .remove = denali_pci_remove, |
1703 | }; | 1706 | }; |
1704 | 1707 | ||
1705 | static int __devinit denali_init(void) | 1708 | module_pci_driver(denali_pci_driver); |
1706 | { | ||
1707 | printk(KERN_INFO "Spectra MTD driver\n"); | ||
1708 | return pci_register_driver(&denali_pci_driver); | ||
1709 | } | ||
1710 | |||
1711 | /* Free memory */ | ||
1712 | static void __devexit denali_exit(void) | ||
1713 | { | ||
1714 | pci_unregister_driver(&denali_pci_driver); | ||
1715 | } | ||
1716 | |||
1717 | module_init(denali_init); | ||
1718 | module_exit(denali_exit); | ||
diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c index b08202664543..a225e49a5623 100644 --- a/drivers/mtd/nand/docg4.c +++ b/drivers/mtd/nand/docg4.c | |||
@@ -720,6 +720,7 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand, | |||
720 | struct docg4_priv *doc = nand->priv; | 720 | struct docg4_priv *doc = nand->priv; |
721 | void __iomem *docptr = doc->virtadr; | 721 | void __iomem *docptr = doc->virtadr; |
722 | uint16_t status, edc_err, *buf16; | 722 | uint16_t status, edc_err, *buf16; |
723 | int bits_corrected = 0; | ||
723 | 724 | ||
724 | dev_dbg(doc->dev, "%s: page %08x\n", __func__, page); | 725 | dev_dbg(doc->dev, "%s: page %08x\n", __func__, page); |
725 | 726 | ||
@@ -772,7 +773,7 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand, | |||
772 | 773 | ||
773 | /* If bitflips are reported, attempt to correct with ecc */ | 774 | /* If bitflips are reported, attempt to correct with ecc */ |
774 | if (edc_err & DOC_ECCCONF1_BCH_SYNDROM_ERR) { | 775 | if (edc_err & DOC_ECCCONF1_BCH_SYNDROM_ERR) { |
775 | int bits_corrected = correct_data(mtd, buf, page); | 776 | bits_corrected = correct_data(mtd, buf, page); |
776 | if (bits_corrected == -EBADMSG) | 777 | if (bits_corrected == -EBADMSG) |
777 | mtd->ecc_stats.failed++; | 778 | mtd->ecc_stats.failed++; |
778 | else | 779 | else |
@@ -781,24 +782,24 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand, | |||
781 | } | 782 | } |
782 | 783 | ||
783 | writew(0, docptr + DOC_DATAEND); | 784 | writew(0, docptr + DOC_DATAEND); |
784 | return 0; | 785 | return bits_corrected; |
785 | } | 786 | } |
786 | 787 | ||
787 | 788 | ||
788 | static int docg4_read_page_raw(struct mtd_info *mtd, struct nand_chip *nand, | 789 | static int docg4_read_page_raw(struct mtd_info *mtd, struct nand_chip *nand, |
789 | uint8_t *buf, int page) | 790 | uint8_t *buf, int oob_required, int page) |
790 | { | 791 | { |
791 | return read_page(mtd, nand, buf, page, false); | 792 | return read_page(mtd, nand, buf, page, false); |
792 | } | 793 | } |
793 | 794 | ||
794 | static int docg4_read_page(struct mtd_info *mtd, struct nand_chip *nand, | 795 | static int docg4_read_page(struct mtd_info *mtd, struct nand_chip *nand, |
795 | uint8_t *buf, int page) | 796 | uint8_t *buf, int oob_required, int page) |
796 | { | 797 | { |
797 | return read_page(mtd, nand, buf, page, true); | 798 | return read_page(mtd, nand, buf, page, true); |
798 | } | 799 | } |
799 | 800 | ||
800 | static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand, | 801 | static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand, |
801 | int page, int sndcmd) | 802 | int page) |
802 | { | 803 | { |
803 | struct docg4_priv *doc = nand->priv; | 804 | struct docg4_priv *doc = nand->priv; |
804 | void __iomem *docptr = doc->virtadr; | 805 | void __iomem *docptr = doc->virtadr; |
@@ -952,13 +953,13 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *nand, | |||
952 | } | 953 | } |
953 | 954 | ||
954 | static void docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand, | 955 | static void docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand, |
955 | const uint8_t *buf) | 956 | const uint8_t *buf, int oob_required) |
956 | { | 957 | { |
957 | return write_page(mtd, nand, buf, false); | 958 | return write_page(mtd, nand, buf, false); |
958 | } | 959 | } |
959 | 960 | ||
960 | static void docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand, | 961 | static void docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand, |
961 | const uint8_t *buf) | 962 | const uint8_t *buf, int oob_required) |
962 | { | 963 | { |
963 | return write_page(mtd, nand, buf, true); | 964 | return write_page(mtd, nand, buf, true); |
964 | } | 965 | } |
@@ -1002,7 +1003,7 @@ static int __init read_factory_bbt(struct mtd_info *mtd) | |||
1002 | return -ENOMEM; | 1003 | return -ENOMEM; |
1003 | 1004 | ||
1004 | read_page_prologue(mtd, g4_addr); | 1005 | read_page_prologue(mtd, g4_addr); |
1005 | status = docg4_read_page(mtd, nand, buf, DOCG4_FACTORY_BBT_PAGE); | 1006 | status = docg4_read_page(mtd, nand, buf, 0, DOCG4_FACTORY_BBT_PAGE); |
1006 | if (status) | 1007 | if (status) |
1007 | goto exit; | 1008 | goto exit; |
1008 | 1009 | ||
@@ -1079,7 +1080,7 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
1079 | 1080 | ||
1080 | /* write first page of block */ | 1081 | /* write first page of block */ |
1081 | write_page_prologue(mtd, g4_addr); | 1082 | write_page_prologue(mtd, g4_addr); |
1082 | docg4_write_page(mtd, nand, buf); | 1083 | docg4_write_page(mtd, nand, buf, 1); |
1083 | ret = pageprog(mtd); | 1084 | ret = pageprog(mtd); |
1084 | if (!ret) | 1085 | if (!ret) |
1085 | mtd->ecc_stats.badblocks++; | 1086 | mtd->ecc_stats.badblocks++; |
@@ -1192,8 +1193,7 @@ static void __init init_mtd_structs(struct mtd_info *mtd) | |||
1192 | nand->ecc.prepad = 8; | 1193 | nand->ecc.prepad = 8; |
1193 | nand->ecc.bytes = 8; | 1194 | nand->ecc.bytes = 8; |
1194 | nand->ecc.strength = DOCG4_T; | 1195 | nand->ecc.strength = DOCG4_T; |
1195 | nand->options = | 1196 | nand->options = NAND_BUSWIDTH_16 | NAND_NO_SUBPAGE_WRITE; |
1196 | NAND_BUSWIDTH_16 | NAND_NO_SUBPAGE_WRITE | NAND_NO_AUTOINCR; | ||
1197 | nand->IO_ADDR_R = nand->IO_ADDR_W = doc->virtadr + DOC_IOSPACE_DATA; | 1197 | nand->IO_ADDR_R = nand->IO_ADDR_W = doc->virtadr + DOC_IOSPACE_DATA; |
1198 | nand->controller = &nand->hwcontrol; | 1198 | nand->controller = &nand->hwcontrol; |
1199 | spin_lock_init(&nand->controller->lock); | 1199 | spin_lock_init(&nand->controller->lock); |
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 80b5264f0a32..784293806110 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c | |||
@@ -75,6 +75,7 @@ struct fsl_elbc_fcm_ctrl { | |||
75 | unsigned int use_mdr; /* Non zero if the MDR is to be set */ | 75 | unsigned int use_mdr; /* Non zero if the MDR is to be set */ |
76 | unsigned int oob; /* Non zero if operating on OOB data */ | 76 | unsigned int oob; /* Non zero if operating on OOB data */ |
77 | unsigned int counter; /* counter for the initializations */ | 77 | unsigned int counter; /* counter for the initializations */ |
78 | unsigned int max_bitflips; /* Saved during READ0 cmd */ | ||
78 | }; | 79 | }; |
79 | 80 | ||
80 | /* These map to the positions used by the FCM hardware ECC generator */ | 81 | /* These map to the positions used by the FCM hardware ECC generator */ |
@@ -253,6 +254,8 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) | |||
253 | if (chip->ecc.mode != NAND_ECC_HW) | 254 | if (chip->ecc.mode != NAND_ECC_HW) |
254 | return 0; | 255 | return 0; |
255 | 256 | ||
257 | elbc_fcm_ctrl->max_bitflips = 0; | ||
258 | |||
256 | if (elbc_fcm_ctrl->read_bytes == mtd->writesize + mtd->oobsize) { | 259 | if (elbc_fcm_ctrl->read_bytes == mtd->writesize + mtd->oobsize) { |
257 | uint32_t lteccr = in_be32(&lbc->lteccr); | 260 | uint32_t lteccr = in_be32(&lbc->lteccr); |
258 | /* | 261 | /* |
@@ -262,11 +265,16 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) | |||
262 | * bits 28-31 are uncorrectable errors, marked elsewhere. | 265 | * bits 28-31 are uncorrectable errors, marked elsewhere. |
263 | * for small page nand only 1 bit is used. | 266 | * for small page nand only 1 bit is used. |
264 | * if the ELBC doesn't have the lteccr register it reads 0 | 267 | * if the ELBC doesn't have the lteccr register it reads 0 |
268 | * FIXME: 4 bits can be corrected on NANDs with 2k pages, so | ||
269 | * count the number of sub-pages with bitflips and update | ||
270 | * ecc_stats.corrected accordingly. | ||
265 | */ | 271 | */ |
266 | if (lteccr & 0x000F000F) | 272 | if (lteccr & 0x000F000F) |
267 | out_be32(&lbc->lteccr, 0x000F000F); /* clear lteccr */ | 273 | out_be32(&lbc->lteccr, 0x000F000F); /* clear lteccr */ |
268 | if (lteccr & 0x000F0000) | 274 | if (lteccr & 0x000F0000) { |
269 | mtd->ecc_stats.corrected++; | 275 | mtd->ecc_stats.corrected++; |
276 | elbc_fcm_ctrl->max_bitflips = 1; | ||
277 | } | ||
270 | } | 278 | } |
271 | 279 | ||
272 | return 0; | 280 | return 0; |
@@ -738,26 +746,28 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) | |||
738 | return 0; | 746 | return 0; |
739 | } | 747 | } |
740 | 748 | ||
741 | static int fsl_elbc_read_page(struct mtd_info *mtd, | 749 | static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip, |
742 | struct nand_chip *chip, | 750 | uint8_t *buf, int oob_required, int page) |
743 | uint8_t *buf, | ||
744 | int page) | ||
745 | { | 751 | { |
752 | struct fsl_elbc_mtd *priv = chip->priv; | ||
753 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; | ||
754 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; | ||
755 | |||
746 | fsl_elbc_read_buf(mtd, buf, mtd->writesize); | 756 | fsl_elbc_read_buf(mtd, buf, mtd->writesize); |
747 | fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize); | 757 | if (oob_required) |
758 | fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
748 | 759 | ||
749 | if (fsl_elbc_wait(mtd, chip) & NAND_STATUS_FAIL) | 760 | if (fsl_elbc_wait(mtd, chip) & NAND_STATUS_FAIL) |
750 | mtd->ecc_stats.failed++; | 761 | mtd->ecc_stats.failed++; |
751 | 762 | ||
752 | return 0; | 763 | return elbc_fcm_ctrl->max_bitflips; |
753 | } | 764 | } |
754 | 765 | ||
755 | /* ECC will be calculated automatically, and errors will be detected in | 766 | /* ECC will be calculated automatically, and errors will be detected in |
756 | * waitfunc. | 767 | * waitfunc. |
757 | */ | 768 | */ |
758 | static void fsl_elbc_write_page(struct mtd_info *mtd, | 769 | static void fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip, |
759 | struct nand_chip *chip, | 770 | const uint8_t *buf, int oob_required) |
760 | const uint8_t *buf) | ||
761 | { | 771 | { |
762 | fsl_elbc_write_buf(mtd, buf, mtd->writesize); | 772 | fsl_elbc_write_buf(mtd, buf, mtd->writesize); |
763 | fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); | 773 | fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); |
@@ -795,7 +805,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) | |||
795 | chip->bbt_md = &bbt_mirror_descr; | 805 | chip->bbt_md = &bbt_mirror_descr; |
796 | 806 | ||
797 | /* set up nand options */ | 807 | /* set up nand options */ |
798 | chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR; | 808 | chip->options = NAND_NO_READRDY; |
799 | chip->bbt_options = NAND_BBT_USE_FLASH; | 809 | chip->bbt_options = NAND_BBT_USE_FLASH; |
800 | 810 | ||
801 | chip->controller = &elbc_fcm_ctrl->controller; | 811 | chip->controller = &elbc_fcm_ctrl->controller; |
@@ -814,11 +824,6 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) | |||
814 | chip->ecc.size = 512; | 824 | chip->ecc.size = 512; |
815 | chip->ecc.bytes = 3; | 825 | chip->ecc.bytes = 3; |
816 | chip->ecc.strength = 1; | 826 | chip->ecc.strength = 1; |
817 | /* | ||
818 | * FIXME: can hardware ecc correct 4 bitflips if page size is | ||
819 | * 2k? Then does hardware report number of corrections for this | ||
820 | * case? If so, ecc_stats reporting needs to be fixed as well. | ||
821 | */ | ||
822 | } else { | 827 | } else { |
823 | /* otherwise fall back to default software ECC */ | 828 | /* otherwise fall back to default software ECC */ |
824 | chip->ecc.mode = NAND_ECC_SOFT; | 829 | chip->ecc.mode = NAND_ECC_SOFT; |
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index c30ac7b83d28..9602c1b7e27e 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c | |||
@@ -63,6 +63,7 @@ struct fsl_ifc_nand_ctrl { | |||
63 | unsigned int oob; /* Non zero if operating on OOB data */ | 63 | unsigned int oob; /* Non zero if operating on OOB data */ |
64 | unsigned int eccread; /* Non zero for a full-page ECC read */ | 64 | unsigned int eccread; /* Non zero for a full-page ECC read */ |
65 | unsigned int counter; /* counter for the initializations */ | 65 | unsigned int counter; /* counter for the initializations */ |
66 | unsigned int max_bitflips; /* Saved during READ0 cmd */ | ||
66 | }; | 67 | }; |
67 | 68 | ||
68 | static struct fsl_ifc_nand_ctrl *ifc_nand_ctrl; | 69 | static struct fsl_ifc_nand_ctrl *ifc_nand_ctrl; |
@@ -262,6 +263,8 @@ static void fsl_ifc_run_command(struct mtd_info *mtd) | |||
262 | if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_WPER) | 263 | if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_WPER) |
263 | dev_err(priv->dev, "NAND Flash Write Protect Error\n"); | 264 | dev_err(priv->dev, "NAND Flash Write Protect Error\n"); |
264 | 265 | ||
266 | nctrl->max_bitflips = 0; | ||
267 | |||
265 | if (nctrl->eccread) { | 268 | if (nctrl->eccread) { |
266 | int errors; | 269 | int errors; |
267 | int bufnum = nctrl->page & priv->bufnum_mask; | 270 | int bufnum = nctrl->page & priv->bufnum_mask; |
@@ -290,6 +293,9 @@ static void fsl_ifc_run_command(struct mtd_info *mtd) | |||
290 | } | 293 | } |
291 | 294 | ||
292 | mtd->ecc_stats.corrected += errors; | 295 | mtd->ecc_stats.corrected += errors; |
296 | nctrl->max_bitflips = max_t(unsigned int, | ||
297 | nctrl->max_bitflips, | ||
298 | errors); | ||
293 | } | 299 | } |
294 | 300 | ||
295 | nctrl->eccread = 0; | 301 | nctrl->eccread = 0; |
@@ -375,21 +381,31 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
375 | 381 | ||
376 | return; | 382 | return; |
377 | 383 | ||
378 | /* READID must read all 8 possible bytes */ | ||
379 | case NAND_CMD_READID: | 384 | case NAND_CMD_READID: |
385 | case NAND_CMD_PARAM: { | ||
386 | int timing = IFC_FIR_OP_RB; | ||
387 | if (command == NAND_CMD_PARAM) | ||
388 | timing = IFC_FIR_OP_RBCD; | ||
389 | |||
380 | out_be32(&ifc->ifc_nand.nand_fir0, | 390 | out_be32(&ifc->ifc_nand.nand_fir0, |
381 | (IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) | | 391 | (IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) | |
382 | (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | | 392 | (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | |
383 | (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT)); | 393 | (timing << IFC_NAND_FIR0_OP2_SHIFT)); |
384 | out_be32(&ifc->ifc_nand.nand_fcr0, | 394 | out_be32(&ifc->ifc_nand.nand_fcr0, |
385 | NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT); | 395 | command << IFC_NAND_FCR0_CMD0_SHIFT); |
386 | /* 8 bytes for manuf, device and exts */ | 396 | out_be32(&ifc->ifc_nand.row3, column); |
387 | out_be32(&ifc->ifc_nand.nand_fbcr, 8); | 397 | |
388 | ifc_nand_ctrl->read_bytes = 8; | 398 | /* |
399 | * although currently it's 8 bytes for READID, we always read | ||
400 | * the maximum 256 bytes(for PARAM) | ||
401 | */ | ||
402 | out_be32(&ifc->ifc_nand.nand_fbcr, 256); | ||
403 | ifc_nand_ctrl->read_bytes = 256; | ||
389 | 404 | ||
390 | set_addr(mtd, 0, 0, 0); | 405 | set_addr(mtd, 0, 0, 0); |
391 | fsl_ifc_run_command(mtd); | 406 | fsl_ifc_run_command(mtd); |
392 | return; | 407 | return; |
408 | } | ||
393 | 409 | ||
394 | /* ERASE1 stores the block and page address */ | 410 | /* ERASE1 stores the block and page address */ |
395 | case NAND_CMD_ERASE1: | 411 | case NAND_CMD_ERASE1: |
@@ -682,15 +698,16 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
682 | return nand_fsr | NAND_STATUS_WP; | 698 | return nand_fsr | NAND_STATUS_WP; |
683 | } | 699 | } |
684 | 700 | ||
685 | static int fsl_ifc_read_page(struct mtd_info *mtd, | 701 | static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip, |
686 | struct nand_chip *chip, | 702 | uint8_t *buf, int oob_required, int page) |
687 | uint8_t *buf, int page) | ||
688 | { | 703 | { |
689 | struct fsl_ifc_mtd *priv = chip->priv; | 704 | struct fsl_ifc_mtd *priv = chip->priv; |
690 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; | 705 | struct fsl_ifc_ctrl *ctrl = priv->ctrl; |
706 | struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl; | ||
691 | 707 | ||
692 | fsl_ifc_read_buf(mtd, buf, mtd->writesize); | 708 | fsl_ifc_read_buf(mtd, buf, mtd->writesize); |
693 | fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize); | 709 | if (oob_required) |
710 | fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
694 | 711 | ||
695 | if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_ECCER) | 712 | if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_ECCER) |
696 | dev_err(priv->dev, "NAND Flash ECC Uncorrectable Error\n"); | 713 | dev_err(priv->dev, "NAND Flash ECC Uncorrectable Error\n"); |
@@ -698,15 +715,14 @@ static int fsl_ifc_read_page(struct mtd_info *mtd, | |||
698 | if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC) | 715 | if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC) |
699 | mtd->ecc_stats.failed++; | 716 | mtd->ecc_stats.failed++; |
700 | 717 | ||
701 | return 0; | 718 | return nctrl->max_bitflips; |
702 | } | 719 | } |
703 | 720 | ||
704 | /* ECC will be calculated automatically, and errors will be detected in | 721 | /* ECC will be calculated automatically, and errors will be detected in |
705 | * waitfunc. | 722 | * waitfunc. |
706 | */ | 723 | */ |
707 | static void fsl_ifc_write_page(struct mtd_info *mtd, | 724 | static void fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip, |
708 | struct nand_chip *chip, | 725 | const uint8_t *buf, int oob_required) |
709 | const uint8_t *buf) | ||
710 | { | 726 | { |
711 | fsl_ifc_write_buf(mtd, buf, mtd->writesize); | 727 | fsl_ifc_write_buf(mtd, buf, mtd->writesize); |
712 | fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize); | 728 | fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize); |
@@ -789,7 +805,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) | |||
789 | out_be32(&ifc->ifc_nand.ncfgr, 0x0); | 805 | out_be32(&ifc->ifc_nand.ncfgr, 0x0); |
790 | 806 | ||
791 | /* set up nand options */ | 807 | /* set up nand options */ |
792 | chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR; | 808 | chip->options = NAND_NO_READRDY; |
793 | chip->bbt_options = NAND_BBT_USE_FLASH; | 809 | chip->bbt_options = NAND_BBT_USE_FLASH; |
794 | 810 | ||
795 | 811 | ||
@@ -811,6 +827,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) | |||
811 | /* Hardware generates ECC per 512 Bytes */ | 827 | /* Hardware generates ECC per 512 Bytes */ |
812 | chip->ecc.size = 512; | 828 | chip->ecc.size = 512; |
813 | chip->ecc.bytes = 8; | 829 | chip->ecc.bytes = 8; |
830 | chip->ecc.strength = 4; | ||
814 | 831 | ||
815 | switch (csor & CSOR_NAND_PGS_MASK) { | 832 | switch (csor & CSOR_NAND_PGS_MASK) { |
816 | case CSOR_NAND_PGS_512: | 833 | case CSOR_NAND_PGS_512: |
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index 1b8330e1155a..38d26240d8b1 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c | |||
@@ -692,6 +692,7 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf, | |||
692 | * @mtd: mtd info structure | 692 | * @mtd: mtd info structure |
693 | * @chip: nand chip info structure | 693 | * @chip: nand chip info structure |
694 | * @buf: buffer to store read data | 694 | * @buf: buffer to store read data |
695 | * @oob_required: caller expects OOB data read to chip->oob_poi | ||
695 | * @page: page number to read | 696 | * @page: page number to read |
696 | * | 697 | * |
697 | * This routine is needed for fsmc version 8 as reading from NAND chip has to be | 698 | * This routine is needed for fsmc version 8 as reading from NAND chip has to be |
@@ -701,7 +702,7 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf, | |||
701 | * max of 8 bits) | 702 | * max of 8 bits) |
702 | */ | 703 | */ |
703 | static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | 704 | static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, |
704 | uint8_t *buf, int page) | 705 | uint8_t *buf, int oob_required, int page) |
705 | { | 706 | { |
706 | struct fsmc_nand_data *host = container_of(mtd, | 707 | struct fsmc_nand_data *host = container_of(mtd, |
707 | struct fsmc_nand_data, mtd); | 708 | struct fsmc_nand_data, mtd); |
@@ -720,6 +721,7 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
720 | */ | 721 | */ |
721 | uint16_t ecc_oob[7]; | 722 | uint16_t ecc_oob[7]; |
722 | uint8_t *oob = (uint8_t *)&ecc_oob[0]; | 723 | uint8_t *oob = (uint8_t *)&ecc_oob[0]; |
724 | unsigned int max_bitflips = 0; | ||
723 | 725 | ||
724 | for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) { | 726 | for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) { |
725 | chip->cmdfunc(mtd, NAND_CMD_READ0, s * eccsize, page); | 727 | chip->cmdfunc(mtd, NAND_CMD_READ0, s * eccsize, page); |
@@ -748,13 +750,15 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
748 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); | 750 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); |
749 | 751 | ||
750 | stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); | 752 | stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); |
751 | if (stat < 0) | 753 | if (stat < 0) { |
752 | mtd->ecc_stats.failed++; | 754 | mtd->ecc_stats.failed++; |
753 | else | 755 | } else { |
754 | mtd->ecc_stats.corrected += stat; | 756 | mtd->ecc_stats.corrected += stat; |
757 | max_bitflips = max_t(unsigned int, max_bitflips, stat); | ||
758 | } | ||
755 | } | 759 | } |
756 | 760 | ||
757 | return 0; | 761 | return max_bitflips; |
758 | } | 762 | } |
759 | 763 | ||
760 | /* | 764 | /* |
@@ -994,9 +998,9 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) | |||
994 | return PTR_ERR(host->clk); | 998 | return PTR_ERR(host->clk); |
995 | } | 999 | } |
996 | 1000 | ||
997 | ret = clk_enable(host->clk); | 1001 | ret = clk_prepare_enable(host->clk); |
998 | if (ret) | 1002 | if (ret) |
999 | goto err_clk_enable; | 1003 | goto err_clk_prepare_enable; |
1000 | 1004 | ||
1001 | /* | 1005 | /* |
1002 | * This device ID is actually a common AMBA ID as used on the | 1006 | * This device ID is actually a common AMBA ID as used on the |
@@ -1176,8 +1180,8 @@ err_req_write_chnl: | |||
1176 | if (host->mode == USE_DMA_ACCESS) | 1180 | if (host->mode == USE_DMA_ACCESS) |
1177 | dma_release_channel(host->read_dma_chan); | 1181 | dma_release_channel(host->read_dma_chan); |
1178 | err_req_read_chnl: | 1182 | err_req_read_chnl: |
1179 | clk_disable(host->clk); | 1183 | clk_disable_unprepare(host->clk); |
1180 | err_clk_enable: | 1184 | err_clk_prepare_enable: |
1181 | clk_put(host->clk); | 1185 | clk_put(host->clk); |
1182 | return ret; | 1186 | return ret; |
1183 | } | 1187 | } |
@@ -1198,7 +1202,7 @@ static int fsmc_nand_remove(struct platform_device *pdev) | |||
1198 | dma_release_channel(host->write_dma_chan); | 1202 | dma_release_channel(host->write_dma_chan); |
1199 | dma_release_channel(host->read_dma_chan); | 1203 | dma_release_channel(host->read_dma_chan); |
1200 | } | 1204 | } |
1201 | clk_disable(host->clk); | 1205 | clk_disable_unprepare(host->clk); |
1202 | clk_put(host->clk); | 1206 | clk_put(host->clk); |
1203 | } | 1207 | } |
1204 | 1208 | ||
@@ -1210,7 +1214,7 @@ static int fsmc_nand_suspend(struct device *dev) | |||
1210 | { | 1214 | { |
1211 | struct fsmc_nand_data *host = dev_get_drvdata(dev); | 1215 | struct fsmc_nand_data *host = dev_get_drvdata(dev); |
1212 | if (host) | 1216 | if (host) |
1213 | clk_disable(host->clk); | 1217 | clk_disable_unprepare(host->clk); |
1214 | return 0; | 1218 | return 0; |
1215 | } | 1219 | } |
1216 | 1220 | ||
@@ -1218,7 +1222,7 @@ static int fsmc_nand_resume(struct device *dev) | |||
1218 | { | 1222 | { |
1219 | struct fsmc_nand_data *host = dev_get_drvdata(dev); | 1223 | struct fsmc_nand_data *host = dev_get_drvdata(dev); |
1220 | if (host) { | 1224 | if (host) { |
1221 | clk_enable(host->clk); | 1225 | clk_prepare_enable(host->clk); |
1222 | fsmc_nand_setup(host->regs_va, host->bank, | 1226 | fsmc_nand_setup(host->regs_va, host->bank, |
1223 | host->nand.options & NAND_BUSWIDTH_16, | 1227 | host->nand.options & NAND_BUSWIDTH_16, |
1224 | host->dev_timings); | 1228 | host->dev_timings); |
diff --git a/drivers/mtd/nand/gpmi-nand/bch-regs.h b/drivers/mtd/nand/gpmi-nand/bch-regs.h index 4effb8c579db..a0924515c396 100644 --- a/drivers/mtd/nand/gpmi-nand/bch-regs.h +++ b/drivers/mtd/nand/gpmi-nand/bch-regs.h | |||
@@ -51,15 +51,26 @@ | |||
51 | 51 | ||
52 | #define BP_BCH_FLASH0LAYOUT0_ECC0 12 | 52 | #define BP_BCH_FLASH0LAYOUT0_ECC0 12 |
53 | #define BM_BCH_FLASH0LAYOUT0_ECC0 (0xf << BP_BCH_FLASH0LAYOUT0_ECC0) | 53 | #define BM_BCH_FLASH0LAYOUT0_ECC0 (0xf << BP_BCH_FLASH0LAYOUT0_ECC0) |
54 | #define BF_BCH_FLASH0LAYOUT0_ECC0(v) \ | 54 | #define MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0 11 |
55 | (((v) << BP_BCH_FLASH0LAYOUT0_ECC0) & BM_BCH_FLASH0LAYOUT0_ECC0) | 55 | #define MX6Q_BM_BCH_FLASH0LAYOUT0_ECC0 (0x1f << MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0) |
56 | #define BF_BCH_FLASH0LAYOUT0_ECC0(v, x) \ | ||
57 | (GPMI_IS_MX6Q(x) \ | ||
58 | ? (((v) << MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0) \ | ||
59 | & MX6Q_BM_BCH_FLASH0LAYOUT0_ECC0) \ | ||
60 | : (((v) << BP_BCH_FLASH0LAYOUT0_ECC0) \ | ||
61 | & BM_BCH_FLASH0LAYOUT0_ECC0) \ | ||
62 | ) | ||
56 | 63 | ||
57 | #define BP_BCH_FLASH0LAYOUT0_DATA0_SIZE 0 | 64 | #define BP_BCH_FLASH0LAYOUT0_DATA0_SIZE 0 |
58 | #define BM_BCH_FLASH0LAYOUT0_DATA0_SIZE \ | 65 | #define BM_BCH_FLASH0LAYOUT0_DATA0_SIZE \ |
59 | (0xfff << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE) | 66 | (0xfff << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE) |
60 | #define BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(v) \ | 67 | #define MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE \ |
61 | (((v) << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE)\ | 68 | (0x3ff << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE) |
62 | & BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) | 69 | #define BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(v, x) \ |
70 | (GPMI_IS_MX6Q(x) \ | ||
71 | ? (((v) >> 2) & MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) \ | ||
72 | : ((v) & BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) \ | ||
73 | ) | ||
63 | 74 | ||
64 | #define HW_BCH_FLASH0LAYOUT1 0x00000090 | 75 | #define HW_BCH_FLASH0LAYOUT1 0x00000090 |
65 | 76 | ||
@@ -72,13 +83,24 @@ | |||
72 | 83 | ||
73 | #define BP_BCH_FLASH0LAYOUT1_ECCN 12 | 84 | #define BP_BCH_FLASH0LAYOUT1_ECCN 12 |
74 | #define BM_BCH_FLASH0LAYOUT1_ECCN (0xf << BP_BCH_FLASH0LAYOUT1_ECCN) | 85 | #define BM_BCH_FLASH0LAYOUT1_ECCN (0xf << BP_BCH_FLASH0LAYOUT1_ECCN) |
75 | #define BF_BCH_FLASH0LAYOUT1_ECCN(v) \ | 86 | #define MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN 11 |
76 | (((v) << BP_BCH_FLASH0LAYOUT1_ECCN) & BM_BCH_FLASH0LAYOUT1_ECCN) | 87 | #define MX6Q_BM_BCH_FLASH0LAYOUT1_ECCN (0x1f << MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN) |
88 | #define BF_BCH_FLASH0LAYOUT1_ECCN(v, x) \ | ||
89 | (GPMI_IS_MX6Q(x) \ | ||
90 | ? (((v) << MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN) \ | ||
91 | & MX6Q_BM_BCH_FLASH0LAYOUT1_ECCN) \ | ||
92 | : (((v) << BP_BCH_FLASH0LAYOUT1_ECCN) \ | ||
93 | & BM_BCH_FLASH0LAYOUT1_ECCN) \ | ||
94 | ) | ||
77 | 95 | ||
78 | #define BP_BCH_FLASH0LAYOUT1_DATAN_SIZE 0 | 96 | #define BP_BCH_FLASH0LAYOUT1_DATAN_SIZE 0 |
79 | #define BM_BCH_FLASH0LAYOUT1_DATAN_SIZE \ | 97 | #define BM_BCH_FLASH0LAYOUT1_DATAN_SIZE \ |
80 | (0xfff << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE) | 98 | (0xfff << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE) |
81 | #define BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(v) \ | 99 | #define MX6Q_BM_BCH_FLASH0LAYOUT1_DATAN_SIZE \ |
82 | (((v) << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE) \ | 100 | (0x3ff << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE) |
83 | & BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) | 101 | #define BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(v, x) \ |
102 | (GPMI_IS_MX6Q(x) \ | ||
103 | ? (((v) >> 2) & MX6Q_BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) \ | ||
104 | : ((v) & BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) \ | ||
105 | ) | ||
84 | #endif | 106 | #endif |
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index e8ea7107932e..a1f43329ad43 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/mtd/gpmi-nand.h> | 21 | #include <linux/mtd/gpmi-nand.h> |
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
24 | #include <mach/mxs.h> | ||
25 | 24 | ||
26 | #include "gpmi-nand.h" | 25 | #include "gpmi-nand.h" |
27 | #include "gpmi-regs.h" | 26 | #include "gpmi-regs.h" |
@@ -37,6 +36,8 @@ struct timing_threshod timing_default_threshold = { | |||
37 | .max_dll_delay_in_ns = 16, | 36 | .max_dll_delay_in_ns = 16, |
38 | }; | 37 | }; |
39 | 38 | ||
39 | #define MXS_SET_ADDR 0x4 | ||
40 | #define MXS_CLR_ADDR 0x8 | ||
40 | /* | 41 | /* |
41 | * Clear the bit and poll it cleared. This is usually called with | 42 | * Clear the bit and poll it cleared. This is usually called with |
42 | * a reset address and mask being either SFTRST(bit 31) or CLKGATE | 43 | * a reset address and mask being either SFTRST(bit 31) or CLKGATE |
@@ -47,7 +48,7 @@ static int clear_poll_bit(void __iomem *addr, u32 mask) | |||
47 | int timeout = 0x400; | 48 | int timeout = 0x400; |
48 | 49 | ||
49 | /* clear the bit */ | 50 | /* clear the bit */ |
50 | __mxs_clrl(mask, addr); | 51 | writel(mask, addr + MXS_CLR_ADDR); |
51 | 52 | ||
52 | /* | 53 | /* |
53 | * SFTRST needs 3 GPMI clocks to settle, the reference manual | 54 | * SFTRST needs 3 GPMI clocks to settle, the reference manual |
@@ -92,11 +93,11 @@ static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable) | |||
92 | goto error; | 93 | goto error; |
93 | 94 | ||
94 | /* clear CLKGATE */ | 95 | /* clear CLKGATE */ |
95 | __mxs_clrl(MODULE_CLKGATE, reset_addr); | 96 | writel(MODULE_CLKGATE, reset_addr + MXS_CLR_ADDR); |
96 | 97 | ||
97 | if (!just_enable) { | 98 | if (!just_enable) { |
98 | /* set SFTRST to reset the block */ | 99 | /* set SFTRST to reset the block */ |
99 | __mxs_setl(MODULE_SFTRST, reset_addr); | 100 | writel(MODULE_SFTRST, reset_addr + MXS_SET_ADDR); |
100 | udelay(1); | 101 | udelay(1); |
101 | 102 | ||
102 | /* poll CLKGATE becoming set */ | 103 | /* poll CLKGATE becoming set */ |
@@ -223,13 +224,13 @@ int bch_set_geometry(struct gpmi_nand_data *this) | |||
223 | /* Configure layout 0. */ | 224 | /* Configure layout 0. */ |
224 | writel(BF_BCH_FLASH0LAYOUT0_NBLOCKS(block_count) | 225 | writel(BF_BCH_FLASH0LAYOUT0_NBLOCKS(block_count) |
225 | | BF_BCH_FLASH0LAYOUT0_META_SIZE(metadata_size) | 226 | | BF_BCH_FLASH0LAYOUT0_META_SIZE(metadata_size) |
226 | | BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength) | 227 | | BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength, this) |
227 | | BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size), | 228 | | BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size, this), |
228 | r->bch_regs + HW_BCH_FLASH0LAYOUT0); | 229 | r->bch_regs + HW_BCH_FLASH0LAYOUT0); |
229 | 230 | ||
230 | writel(BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size) | 231 | writel(BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size) |
231 | | BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength) | 232 | | BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength, this) |
232 | | BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size), | 233 | | BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size, this), |
233 | r->bch_regs + HW_BCH_FLASH0LAYOUT1); | 234 | r->bch_regs + HW_BCH_FLASH0LAYOUT1); |
234 | 235 | ||
235 | /* Set *all* chip selects to use layout 0. */ | 236 | /* Set *all* chip selects to use layout 0. */ |
@@ -255,11 +256,12 @@ static unsigned int ns_to_cycles(unsigned int time, | |||
255 | return max(k, min); | 256 | return max(k, min); |
256 | } | 257 | } |
257 | 258 | ||
259 | #define DEF_MIN_PROP_DELAY 5 | ||
260 | #define DEF_MAX_PROP_DELAY 9 | ||
258 | /* Apply timing to current hardware conditions. */ | 261 | /* Apply timing to current hardware conditions. */ |
259 | static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this, | 262 | static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this, |
260 | struct gpmi_nfc_hardware_timing *hw) | 263 | struct gpmi_nfc_hardware_timing *hw) |
261 | { | 264 | { |
262 | struct gpmi_nand_platform_data *pdata = this->pdata; | ||
263 | struct timing_threshod *nfc = &timing_default_threshold; | 265 | struct timing_threshod *nfc = &timing_default_threshold; |
264 | struct nand_chip *nand = &this->nand; | 266 | struct nand_chip *nand = &this->nand; |
265 | struct nand_timing target = this->timing; | 267 | struct nand_timing target = this->timing; |
@@ -276,8 +278,8 @@ static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this, | |||
276 | int ideal_sample_delay_in_ns; | 278 | int ideal_sample_delay_in_ns; |
277 | unsigned int sample_delay_factor; | 279 | unsigned int sample_delay_factor; |
278 | int tEYE; | 280 | int tEYE; |
279 | unsigned int min_prop_delay_in_ns = pdata->min_prop_delay_in_ns; | 281 | unsigned int min_prop_delay_in_ns = DEF_MIN_PROP_DELAY; |
280 | unsigned int max_prop_delay_in_ns = pdata->max_prop_delay_in_ns; | 282 | unsigned int max_prop_delay_in_ns = DEF_MAX_PROP_DELAY; |
281 | 283 | ||
282 | /* | 284 | /* |
283 | * If there are multiple chips, we need to relax the timings to allow | 285 | * If there are multiple chips, we need to relax the timings to allow |
@@ -803,7 +805,8 @@ int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip) | |||
803 | if (GPMI_IS_MX23(this)) { | 805 | if (GPMI_IS_MX23(this)) { |
804 | mask = MX23_BM_GPMI_DEBUG_READY0 << chip; | 806 | mask = MX23_BM_GPMI_DEBUG_READY0 << chip; |
805 | reg = readl(r->gpmi_regs + HW_GPMI_DEBUG); | 807 | reg = readl(r->gpmi_regs + HW_GPMI_DEBUG); |
806 | } else if (GPMI_IS_MX28(this)) { | 808 | } else if (GPMI_IS_MX28(this) || GPMI_IS_MX6Q(this)) { |
809 | /* MX28 shares the same R/B register as MX6Q. */ | ||
807 | mask = MX28_BF_GPMI_STAT_READY_BUSY(1 << chip); | 810 | mask = MX28_BF_GPMI_STAT_READY_BUSY(1 << chip); |
808 | reg = readl(r->gpmi_regs + HW_GPMI_STAT); | 811 | reg = readl(r->gpmi_regs + HW_GPMI_STAT); |
809 | } else | 812 | } else |
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index b68e04310bd8..a05b7b444d4f 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c | |||
@@ -25,6 +25,8 @@ | |||
25 | #include <linux/mtd/gpmi-nand.h> | 25 | #include <linux/mtd/gpmi-nand.h> |
26 | #include <linux/mtd/partitions.h> | 26 | #include <linux/mtd/partitions.h> |
27 | #include <linux/pinctrl/consumer.h> | 27 | #include <linux/pinctrl/consumer.h> |
28 | #include <linux/of.h> | ||
29 | #include <linux/of_device.h> | ||
28 | #include "gpmi-nand.h" | 30 | #include "gpmi-nand.h" |
29 | 31 | ||
30 | /* add our owner bbt descriptor */ | 32 | /* add our owner bbt descriptor */ |
@@ -387,7 +389,7 @@ static void release_bch_irq(struct gpmi_nand_data *this) | |||
387 | static bool gpmi_dma_filter(struct dma_chan *chan, void *param) | 389 | static bool gpmi_dma_filter(struct dma_chan *chan, void *param) |
388 | { | 390 | { |
389 | struct gpmi_nand_data *this = param; | 391 | struct gpmi_nand_data *this = param; |
390 | struct resource *r = this->private; | 392 | int dma_channel = (int)this->private; |
391 | 393 | ||
392 | if (!mxs_dma_is_apbh(chan)) | 394 | if (!mxs_dma_is_apbh(chan)) |
393 | return false; | 395 | return false; |
@@ -399,7 +401,7 @@ static bool gpmi_dma_filter(struct dma_chan *chan, void *param) | |||
399 | * for mx28 : MX28_DMA_GPMI0 ~ MX28_DMA_GPMI7 | 401 | * for mx28 : MX28_DMA_GPMI0 ~ MX28_DMA_GPMI7 |
400 | * (These eight channels share the same IRQ!) | 402 | * (These eight channels share the same IRQ!) |
401 | */ | 403 | */ |
402 | if (r->start <= chan->chan_id && chan->chan_id <= r->end) { | 404 | if (dma_channel == chan->chan_id) { |
403 | chan->private = &this->dma_data; | 405 | chan->private = &this->dma_data; |
404 | return true; | 406 | return true; |
405 | } | 407 | } |
@@ -419,57 +421,45 @@ static void release_dma_channels(struct gpmi_nand_data *this) | |||
419 | static int __devinit acquire_dma_channels(struct gpmi_nand_data *this) | 421 | static int __devinit acquire_dma_channels(struct gpmi_nand_data *this) |
420 | { | 422 | { |
421 | struct platform_device *pdev = this->pdev; | 423 | struct platform_device *pdev = this->pdev; |
422 | struct gpmi_nand_platform_data *pdata = this->pdata; | 424 | struct resource *r_dma; |
423 | struct resources *res = &this->resources; | 425 | struct device_node *dn; |
424 | struct resource *r, *r_dma; | 426 | int dma_channel; |
425 | unsigned int i; | 427 | unsigned int ret; |
428 | struct dma_chan *dma_chan; | ||
429 | dma_cap_mask_t mask; | ||
430 | |||
431 | /* dma channel, we only use the first one. */ | ||
432 | dn = pdev->dev.of_node; | ||
433 | ret = of_property_read_u32(dn, "fsl,gpmi-dma-channel", &dma_channel); | ||
434 | if (ret) { | ||
435 | pr_err("unable to get DMA channel from dt.\n"); | ||
436 | goto acquire_err; | ||
437 | } | ||
438 | this->private = (void *)dma_channel; | ||
426 | 439 | ||
427 | r = platform_get_resource_byname(pdev, IORESOURCE_DMA, | 440 | /* gpmi dma interrupt */ |
428 | GPMI_NAND_DMA_CHANNELS_RES_NAME); | ||
429 | r_dma = platform_get_resource_byname(pdev, IORESOURCE_IRQ, | 441 | r_dma = platform_get_resource_byname(pdev, IORESOURCE_IRQ, |
430 | GPMI_NAND_DMA_INTERRUPT_RES_NAME); | 442 | GPMI_NAND_DMA_INTERRUPT_RES_NAME); |
431 | if (!r || !r_dma) { | 443 | if (!r_dma) { |
432 | pr_err("Can't get resource for DMA\n"); | 444 | pr_err("Can't get resource for DMA\n"); |
433 | return -ENXIO; | 445 | goto acquire_err; |
434 | } | 446 | } |
447 | this->dma_data.chan_irq = r_dma->start; | ||
435 | 448 | ||
436 | /* used in gpmi_dma_filter() */ | 449 | /* request dma channel */ |
437 | this->private = r; | 450 | dma_cap_zero(mask); |
438 | 451 | dma_cap_set(DMA_SLAVE, mask); | |
439 | for (i = r->start; i <= r->end; i++) { | ||
440 | struct dma_chan *dma_chan; | ||
441 | dma_cap_mask_t mask; | ||
442 | 452 | ||
443 | if (i - r->start >= pdata->max_chip_count) | 453 | dma_chan = dma_request_channel(mask, gpmi_dma_filter, this); |
444 | break; | 454 | if (!dma_chan) { |
445 | 455 | pr_err("dma_request_channel failed.\n"); | |
446 | dma_cap_zero(mask); | 456 | goto acquire_err; |
447 | dma_cap_set(DMA_SLAVE, mask); | ||
448 | |||
449 | /* get the DMA interrupt */ | ||
450 | if (r_dma->start == r_dma->end) { | ||
451 | /* only register the first. */ | ||
452 | if (i == r->start) | ||
453 | this->dma_data.chan_irq = r_dma->start; | ||
454 | else | ||
455 | this->dma_data.chan_irq = NO_IRQ; | ||
456 | } else | ||
457 | this->dma_data.chan_irq = r_dma->start + (i - r->start); | ||
458 | |||
459 | dma_chan = dma_request_channel(mask, gpmi_dma_filter, this); | ||
460 | if (!dma_chan) | ||
461 | goto acquire_err; | ||
462 | |||
463 | /* fill the first empty item */ | ||
464 | this->dma_chans[i - r->start] = dma_chan; | ||
465 | } | 457 | } |
466 | 458 | ||
467 | res->dma_low_channel = r->start; | 459 | this->dma_chans[0] = dma_chan; |
468 | res->dma_high_channel = i; | ||
469 | return 0; | 460 | return 0; |
470 | 461 | ||
471 | acquire_err: | 462 | acquire_err: |
472 | pr_err("Can't acquire DMA channel %u\n", i); | ||
473 | release_dma_channels(this); | 463 | release_dma_channels(this); |
474 | return -EINVAL; | 464 | return -EINVAL; |
475 | } | 465 | } |
@@ -851,7 +841,7 @@ static void block_mark_swapping(struct gpmi_nand_data *this, | |||
851 | } | 841 | } |
852 | 842 | ||
853 | static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, | 843 | static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, |
854 | uint8_t *buf, int page) | 844 | uint8_t *buf, int oob_required, int page) |
855 | { | 845 | { |
856 | struct gpmi_nand_data *this = chip->priv; | 846 | struct gpmi_nand_data *this = chip->priv; |
857 | struct bch_geometry *nfc_geo = &this->bch_geometry; | 847 | struct bch_geometry *nfc_geo = &this->bch_geometry; |
@@ -917,28 +907,31 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
917 | mtd->ecc_stats.corrected += corrected; | 907 | mtd->ecc_stats.corrected += corrected; |
918 | } | 908 | } |
919 | 909 | ||
920 | /* | 910 | if (oob_required) { |
921 | * It's time to deliver the OOB bytes. See gpmi_ecc_read_oob() for | 911 | /* |
922 | * details about our policy for delivering the OOB. | 912 | * It's time to deliver the OOB bytes. See gpmi_ecc_read_oob() |
923 | * | 913 | * for details about our policy for delivering the OOB. |
924 | * We fill the caller's buffer with set bits, and then copy the block | 914 | * |
925 | * mark to th caller's buffer. Note that, if block mark swapping was | 915 | * We fill the caller's buffer with set bits, and then copy the |
926 | * necessary, it has already been done, so we can rely on the first | 916 | * block mark to th caller's buffer. Note that, if block mark |
927 | * byte of the auxiliary buffer to contain the block mark. | 917 | * swapping was necessary, it has already been done, so we can |
928 | */ | 918 | * rely on the first byte of the auxiliary buffer to contain |
929 | memset(chip->oob_poi, ~0, mtd->oobsize); | 919 | * the block mark. |
930 | chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0]; | 920 | */ |
921 | memset(chip->oob_poi, ~0, mtd->oobsize); | ||
922 | chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0]; | ||
931 | 923 | ||
932 | read_page_swap_end(this, buf, mtd->writesize, | 924 | read_page_swap_end(this, buf, mtd->writesize, |
933 | this->payload_virt, this->payload_phys, | 925 | this->payload_virt, this->payload_phys, |
934 | nfc_geo->payload_size, | 926 | nfc_geo->payload_size, |
935 | payload_virt, payload_phys); | 927 | payload_virt, payload_phys); |
928 | } | ||
936 | exit_nfc: | 929 | exit_nfc: |
937 | return ret; | 930 | return ret; |
938 | } | 931 | } |
939 | 932 | ||
940 | static void gpmi_ecc_write_page(struct mtd_info *mtd, | 933 | static void gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, |
941 | struct nand_chip *chip, const uint8_t *buf) | 934 | const uint8_t *buf, int oob_required) |
942 | { | 935 | { |
943 | struct gpmi_nand_data *this = chip->priv; | 936 | struct gpmi_nand_data *this = chip->priv; |
944 | struct bch_geometry *nfc_geo = &this->bch_geometry; | 937 | struct bch_geometry *nfc_geo = &this->bch_geometry; |
@@ -1077,7 +1070,7 @@ exit_auxiliary: | |||
1077 | * this driver. | 1070 | * this driver. |
1078 | */ | 1071 | */ |
1079 | static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, | 1072 | static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, |
1080 | int page, int sndcmd) | 1073 | int page) |
1081 | { | 1074 | { |
1082 | struct gpmi_nand_data *this = chip->priv; | 1075 | struct gpmi_nand_data *this = chip->priv; |
1083 | 1076 | ||
@@ -1100,11 +1093,7 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, | |||
1100 | chip->oob_poi[0] = chip->read_byte(mtd); | 1093 | chip->oob_poi[0] = chip->read_byte(mtd); |
1101 | } | 1094 | } |
1102 | 1095 | ||
1103 | /* | 1096 | return 0; |
1104 | * Return true, indicating that the next call to this function must send | ||
1105 | * a command. | ||
1106 | */ | ||
1107 | return true; | ||
1108 | } | 1097 | } |
1109 | 1098 | ||
1110 | static int | 1099 | static int |
@@ -1318,7 +1307,7 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this) | |||
1318 | /* Write the first page of the current stride. */ | 1307 | /* Write the first page of the current stride. */ |
1319 | dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page); | 1308 | dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page); |
1320 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); | 1309 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); |
1321 | chip->ecc.write_page_raw(mtd, chip, buffer); | 1310 | chip->ecc.write_page_raw(mtd, chip, buffer, 0); |
1322 | chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); | 1311 | chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); |
1323 | 1312 | ||
1324 | /* Wait for the write to finish. */ | 1313 | /* Wait for the write to finish. */ |
@@ -1444,6 +1433,10 @@ static int gpmi_pre_bbt_scan(struct gpmi_nand_data *this) | |||
1444 | if (ret) | 1433 | if (ret) |
1445 | return ret; | 1434 | return ret; |
1446 | 1435 | ||
1436 | /* Adjust the ECC strength according to the chip. */ | ||
1437 | this->nand.ecc.strength = this->bch_geometry.ecc_strength; | ||
1438 | this->mtd.ecc_strength = this->bch_geometry.ecc_strength; | ||
1439 | |||
1447 | /* NAND boot init, depends on the gpmi_set_geometry(). */ | 1440 | /* NAND boot init, depends on the gpmi_set_geometry(). */ |
1448 | return nand_boot_init(this); | 1441 | return nand_boot_init(this); |
1449 | } | 1442 | } |
@@ -1471,9 +1464,9 @@ void gpmi_nfc_exit(struct gpmi_nand_data *this) | |||
1471 | 1464 | ||
1472 | static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this) | 1465 | static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this) |
1473 | { | 1466 | { |
1474 | struct gpmi_nand_platform_data *pdata = this->pdata; | ||
1475 | struct mtd_info *mtd = &this->mtd; | 1467 | struct mtd_info *mtd = &this->mtd; |
1476 | struct nand_chip *chip = &this->nand; | 1468 | struct nand_chip *chip = &this->nand; |
1469 | struct mtd_part_parser_data ppdata = {}; | ||
1477 | int ret; | 1470 | int ret; |
1478 | 1471 | ||
1479 | /* init current chip */ | 1472 | /* init current chip */ |
@@ -1502,6 +1495,7 @@ static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this) | |||
1502 | chip->options |= NAND_NO_SUBPAGE_WRITE; | 1495 | chip->options |= NAND_NO_SUBPAGE_WRITE; |
1503 | chip->ecc.mode = NAND_ECC_HW; | 1496 | chip->ecc.mode = NAND_ECC_HW; |
1504 | chip->ecc.size = 1; | 1497 | chip->ecc.size = 1; |
1498 | chip->ecc.strength = 8; | ||
1505 | chip->ecc.layout = &gpmi_hw_ecclayout; | 1499 | chip->ecc.layout = &gpmi_hw_ecclayout; |
1506 | 1500 | ||
1507 | /* Allocate a temporary DMA buffer for reading ID in the nand_scan() */ | 1501 | /* Allocate a temporary DMA buffer for reading ID in the nand_scan() */ |
@@ -1511,14 +1505,14 @@ static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this) | |||
1511 | if (ret) | 1505 | if (ret) |
1512 | goto err_out; | 1506 | goto err_out; |
1513 | 1507 | ||
1514 | ret = nand_scan(mtd, pdata->max_chip_count); | 1508 | ret = nand_scan(mtd, 1); |
1515 | if (ret) { | 1509 | if (ret) { |
1516 | pr_err("Chip scan failed\n"); | 1510 | pr_err("Chip scan failed\n"); |
1517 | goto err_out; | 1511 | goto err_out; |
1518 | } | 1512 | } |
1519 | 1513 | ||
1520 | ret = mtd_device_parse_register(mtd, NULL, NULL, | 1514 | ppdata.of_node = this->pdev->dev.of_node; |
1521 | pdata->partitions, pdata->partition_count); | 1515 | ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); |
1522 | if (ret) | 1516 | if (ret) |
1523 | goto err_out; | 1517 | goto err_out; |
1524 | return 0; | 1518 | return 0; |
@@ -1528,12 +1522,41 @@ err_out: | |||
1528 | return ret; | 1522 | return ret; |
1529 | } | 1523 | } |
1530 | 1524 | ||
1525 | static const struct platform_device_id gpmi_ids[] = { | ||
1526 | { .name = "imx23-gpmi-nand", .driver_data = IS_MX23, }, | ||
1527 | { .name = "imx28-gpmi-nand", .driver_data = IS_MX28, }, | ||
1528 | { .name = "imx6q-gpmi-nand", .driver_data = IS_MX6Q, }, | ||
1529 | {}, | ||
1530 | }; | ||
1531 | |||
1532 | static const struct of_device_id gpmi_nand_id_table[] = { | ||
1533 | { | ||
1534 | .compatible = "fsl,imx23-gpmi-nand", | ||
1535 | .data = (void *)&gpmi_ids[IS_MX23] | ||
1536 | }, { | ||
1537 | .compatible = "fsl,imx28-gpmi-nand", | ||
1538 | .data = (void *)&gpmi_ids[IS_MX28] | ||
1539 | }, { | ||
1540 | .compatible = "fsl,imx6q-gpmi-nand", | ||
1541 | .data = (void *)&gpmi_ids[IS_MX6Q] | ||
1542 | }, {} | ||
1543 | }; | ||
1544 | MODULE_DEVICE_TABLE(of, gpmi_nand_id_table); | ||
1545 | |||
1531 | static int __devinit gpmi_nand_probe(struct platform_device *pdev) | 1546 | static int __devinit gpmi_nand_probe(struct platform_device *pdev) |
1532 | { | 1547 | { |
1533 | struct gpmi_nand_platform_data *pdata = pdev->dev.platform_data; | ||
1534 | struct gpmi_nand_data *this; | 1548 | struct gpmi_nand_data *this; |
1549 | const struct of_device_id *of_id; | ||
1535 | int ret; | 1550 | int ret; |
1536 | 1551 | ||
1552 | of_id = of_match_device(gpmi_nand_id_table, &pdev->dev); | ||
1553 | if (of_id) { | ||
1554 | pdev->id_entry = of_id->data; | ||
1555 | } else { | ||
1556 | pr_err("Failed to find the right device id.\n"); | ||
1557 | return -ENOMEM; | ||
1558 | } | ||
1559 | |||
1537 | this = kzalloc(sizeof(*this), GFP_KERNEL); | 1560 | this = kzalloc(sizeof(*this), GFP_KERNEL); |
1538 | if (!this) { | 1561 | if (!this) { |
1539 | pr_err("Failed to allocate per-device memory\n"); | 1562 | pr_err("Failed to allocate per-device memory\n"); |
@@ -1543,13 +1566,6 @@ static int __devinit gpmi_nand_probe(struct platform_device *pdev) | |||
1543 | platform_set_drvdata(pdev, this); | 1566 | platform_set_drvdata(pdev, this); |
1544 | this->pdev = pdev; | 1567 | this->pdev = pdev; |
1545 | this->dev = &pdev->dev; | 1568 | this->dev = &pdev->dev; |
1546 | this->pdata = pdata; | ||
1547 | |||
1548 | if (pdata->platform_init) { | ||
1549 | ret = pdata->platform_init(); | ||
1550 | if (ret) | ||
1551 | goto platform_init_error; | ||
1552 | } | ||
1553 | 1569 | ||
1554 | ret = acquire_resources(this); | 1570 | ret = acquire_resources(this); |
1555 | if (ret) | 1571 | if (ret) |
@@ -1567,7 +1583,6 @@ static int __devinit gpmi_nand_probe(struct platform_device *pdev) | |||
1567 | 1583 | ||
1568 | exit_nfc_init: | 1584 | exit_nfc_init: |
1569 | release_resources(this); | 1585 | release_resources(this); |
1570 | platform_init_error: | ||
1571 | exit_acquire_resources: | 1586 | exit_acquire_resources: |
1572 | platform_set_drvdata(pdev, NULL); | 1587 | platform_set_drvdata(pdev, NULL); |
1573 | kfree(this); | 1588 | kfree(this); |
@@ -1585,19 +1600,10 @@ static int __exit gpmi_nand_remove(struct platform_device *pdev) | |||
1585 | return 0; | 1600 | return 0; |
1586 | } | 1601 | } |
1587 | 1602 | ||
1588 | static const struct platform_device_id gpmi_ids[] = { | ||
1589 | { | ||
1590 | .name = "imx23-gpmi-nand", | ||
1591 | .driver_data = IS_MX23, | ||
1592 | }, { | ||
1593 | .name = "imx28-gpmi-nand", | ||
1594 | .driver_data = IS_MX28, | ||
1595 | }, {}, | ||
1596 | }; | ||
1597 | |||
1598 | static struct platform_driver gpmi_nand_driver = { | 1603 | static struct platform_driver gpmi_nand_driver = { |
1599 | .driver = { | 1604 | .driver = { |
1600 | .name = "gpmi-nand", | 1605 | .name = "gpmi-nand", |
1606 | .of_match_table = gpmi_nand_id_table, | ||
1601 | }, | 1607 | }, |
1602 | .probe = gpmi_nand_probe, | 1608 | .probe = gpmi_nand_probe, |
1603 | .remove = __exit_p(gpmi_nand_remove), | 1609 | .remove = __exit_p(gpmi_nand_remove), |
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h index ec6180d4ff8f..ce5daa160920 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h | |||
@@ -266,8 +266,10 @@ extern int gpmi_read_page(struct gpmi_nand_data *, | |||
266 | #define STATUS_UNCORRECTABLE 0xfe | 266 | #define STATUS_UNCORRECTABLE 0xfe |
267 | 267 | ||
268 | /* Use the platform_id to distinguish different Archs. */ | 268 | /* Use the platform_id to distinguish different Archs. */ |
269 | #define IS_MX23 0x1 | 269 | #define IS_MX23 0x0 |
270 | #define IS_MX28 0x2 | 270 | #define IS_MX28 0x1 |
271 | #define IS_MX6Q 0x2 | ||
271 | #define GPMI_IS_MX23(x) ((x)->pdev->id_entry->driver_data == IS_MX23) | 272 | #define GPMI_IS_MX23(x) ((x)->pdev->id_entry->driver_data == IS_MX23) |
272 | #define GPMI_IS_MX28(x) ((x)->pdev->id_entry->driver_data == IS_MX28) | 273 | #define GPMI_IS_MX28(x) ((x)->pdev->id_entry->driver_data == IS_MX28) |
274 | #define GPMI_IS_MX6Q(x) ((x)->pdev->id_entry->driver_data == IS_MX6Q) | ||
273 | #endif | 275 | #endif |
diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c index 9bf5ce5fa22d..50166e93ba96 100644 --- a/drivers/mtd/nand/h1910.c +++ b/drivers/mtd/nand/h1910.c | |||
@@ -124,7 +124,6 @@ static int __init h1910_init(void) | |||
124 | /* 15 us command delay time */ | 124 | /* 15 us command delay time */ |
125 | this->chip_delay = 50; | 125 | this->chip_delay = 50; |
126 | this->ecc.mode = NAND_ECC_SOFT; | 126 | this->ecc.mode = NAND_ECC_SOFT; |
127 | this->options = NAND_NO_AUTOINCR; | ||
128 | 127 | ||
129 | /* Scan to find existence of the device */ | 128 | /* Scan to find existence of the device */ |
130 | if (nand_scan(h1910_nand_mtd, 1)) { | 129 | if (nand_scan(h1910_nand_mtd, 1)) { |
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index e4147e8acb7c..a6fa884ae49b 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c | |||
@@ -332,11 +332,7 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) | |||
332 | chip->ecc.mode = NAND_ECC_HW_OOB_FIRST; | 332 | chip->ecc.mode = NAND_ECC_HW_OOB_FIRST; |
333 | chip->ecc.size = 512; | 333 | chip->ecc.size = 512; |
334 | chip->ecc.bytes = 9; | 334 | chip->ecc.bytes = 9; |
335 | chip->ecc.strength = 2; | 335 | chip->ecc.strength = 4; |
336 | /* | ||
337 | * FIXME: ecc_strength value of 2 bits per 512 bytes of data is a | ||
338 | * conservative guess, given 9 ecc bytes and reed-solomon alg. | ||
339 | */ | ||
340 | 336 | ||
341 | if (pdata) | 337 | if (pdata) |
342 | chip->ecc.layout = pdata->ecc_layout; | 338 | chip->ecc.layout = pdata->ecc_layout; |
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index c240cf1af961..c259c24d7986 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c | |||
@@ -734,7 +734,6 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op) | |||
734 | chip->write_buf = mpc5121_nfc_write_buf; | 734 | chip->write_buf = mpc5121_nfc_write_buf; |
735 | chip->verify_buf = mpc5121_nfc_verify_buf; | 735 | chip->verify_buf = mpc5121_nfc_verify_buf; |
736 | chip->select_chip = mpc5121_nfc_select_chip; | 736 | chip->select_chip = mpc5121_nfc_select_chip; |
737 | chip->options = NAND_NO_AUTOINCR; | ||
738 | chip->bbt_options = NAND_BBT_USE_FLASH; | 737 | chip->bbt_options = NAND_BBT_USE_FLASH; |
739 | chip->ecc.mode = NAND_ECC_SOFT; | 738 | chip->ecc.mode = NAND_ECC_SOFT; |
740 | 739 | ||
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 9e374e9bd296..c58e6a93f445 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
33 | #include <linux/irq.h> | 33 | #include <linux/irq.h> |
34 | #include <linux/completion.h> | 34 | #include <linux/completion.h> |
35 | #include <linux/of_device.h> | ||
36 | #include <linux/of_mtd.h> | ||
35 | 37 | ||
36 | #include <asm/mach/flash.h> | 38 | #include <asm/mach/flash.h> |
37 | #include <mach/mxc_nand.h> | 39 | #include <mach/mxc_nand.h> |
@@ -140,13 +142,47 @@ | |||
140 | 142 | ||
141 | #define NFC_V3_DELAY_LINE (host->regs_ip + 0x34) | 143 | #define NFC_V3_DELAY_LINE (host->regs_ip + 0x34) |
142 | 144 | ||
145 | struct mxc_nand_host; | ||
146 | |||
147 | struct mxc_nand_devtype_data { | ||
148 | void (*preset)(struct mtd_info *); | ||
149 | void (*send_cmd)(struct mxc_nand_host *, uint16_t, int); | ||
150 | void (*send_addr)(struct mxc_nand_host *, uint16_t, int); | ||
151 | void (*send_page)(struct mtd_info *, unsigned int); | ||
152 | void (*send_read_id)(struct mxc_nand_host *); | ||
153 | uint16_t (*get_dev_status)(struct mxc_nand_host *); | ||
154 | int (*check_int)(struct mxc_nand_host *); | ||
155 | void (*irq_control)(struct mxc_nand_host *, int); | ||
156 | u32 (*get_ecc_status)(struct mxc_nand_host *); | ||
157 | struct nand_ecclayout *ecclayout_512, *ecclayout_2k, *ecclayout_4k; | ||
158 | void (*select_chip)(struct mtd_info *mtd, int chip); | ||
159 | int (*correct_data)(struct mtd_info *mtd, u_char *dat, | ||
160 | u_char *read_ecc, u_char *calc_ecc); | ||
161 | |||
162 | /* | ||
163 | * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked | ||
164 | * (CONFIG1:INT_MSK is set). To handle this the driver uses | ||
165 | * enable_irq/disable_irq_nosync instead of CONFIG1:INT_MSK | ||
166 | */ | ||
167 | int irqpending_quirk; | ||
168 | int needs_ip; | ||
169 | |||
170 | size_t regs_offset; | ||
171 | size_t spare0_offset; | ||
172 | size_t axi_offset; | ||
173 | |||
174 | int spare_len; | ||
175 | int eccbytes; | ||
176 | int eccsize; | ||
177 | }; | ||
178 | |||
143 | struct mxc_nand_host { | 179 | struct mxc_nand_host { |
144 | struct mtd_info mtd; | 180 | struct mtd_info mtd; |
145 | struct nand_chip nand; | 181 | struct nand_chip nand; |
146 | struct device *dev; | 182 | struct device *dev; |
147 | 183 | ||
148 | void *spare0; | 184 | void __iomem *spare0; |
149 | void *main_area0; | 185 | void __iomem *main_area0; |
150 | 186 | ||
151 | void __iomem *base; | 187 | void __iomem *base; |
152 | void __iomem *regs; | 188 | void __iomem *regs; |
@@ -163,16 +199,9 @@ struct mxc_nand_host { | |||
163 | 199 | ||
164 | uint8_t *data_buf; | 200 | uint8_t *data_buf; |
165 | unsigned int buf_start; | 201 | unsigned int buf_start; |
166 | int spare_len; | 202 | |
167 | 203 | const struct mxc_nand_devtype_data *devtype_data; | |
168 | void (*preset)(struct mtd_info *); | 204 | struct mxc_nand_platform_data pdata; |
169 | void (*send_cmd)(struct mxc_nand_host *, uint16_t, int); | ||
170 | void (*send_addr)(struct mxc_nand_host *, uint16_t, int); | ||
171 | void (*send_page)(struct mtd_info *, unsigned int); | ||
172 | void (*send_read_id)(struct mxc_nand_host *); | ||
173 | uint16_t (*get_dev_status)(struct mxc_nand_host *); | ||
174 | int (*check_int)(struct mxc_nand_host *); | ||
175 | void (*irq_control)(struct mxc_nand_host *, int); | ||
176 | }; | 205 | }; |
177 | 206 | ||
178 | /* OOB placement block for use with hardware ecc generation */ | 207 | /* OOB placement block for use with hardware ecc generation */ |
@@ -242,21 +271,7 @@ static struct nand_ecclayout nandv2_hw_eccoob_4k = { | |||
242 | } | 271 | } |
243 | }; | 272 | }; |
244 | 273 | ||
245 | static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL }; | 274 | static const char *part_probes[] = { "RedBoot", "cmdlinepart", "ofpart", NULL }; |
246 | |||
247 | static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) | ||
248 | { | ||
249 | struct mxc_nand_host *host = dev_id; | ||
250 | |||
251 | if (!host->check_int(host)) | ||
252 | return IRQ_NONE; | ||
253 | |||
254 | host->irq_control(host, 0); | ||
255 | |||
256 | complete(&host->op_completion); | ||
257 | |||
258 | return IRQ_HANDLED; | ||
259 | } | ||
260 | 275 | ||
261 | static int check_int_v3(struct mxc_nand_host *host) | 276 | static int check_int_v3(struct mxc_nand_host *host) |
262 | { | 277 | { |
@@ -280,26 +295,12 @@ static int check_int_v1_v2(struct mxc_nand_host *host) | |||
280 | if (!(tmp & NFC_V1_V2_CONFIG2_INT)) | 295 | if (!(tmp & NFC_V1_V2_CONFIG2_INT)) |
281 | return 0; | 296 | return 0; |
282 | 297 | ||
283 | if (!cpu_is_mx21()) | 298 | if (!host->devtype_data->irqpending_quirk) |
284 | writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2); | 299 | writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2); |
285 | 300 | ||
286 | return 1; | 301 | return 1; |
287 | } | 302 | } |
288 | 303 | ||
289 | /* | ||
290 | * It has been observed that the i.MX21 cannot read the CONFIG2:INT bit | ||
291 | * if interrupts are masked (CONFIG1:INT_MSK is set). To handle this, the | ||
292 | * driver can enable/disable the irq line rather than simply masking the | ||
293 | * interrupts. | ||
294 | */ | ||
295 | static void irq_control_mx21(struct mxc_nand_host *host, int activate) | ||
296 | { | ||
297 | if (activate) | ||
298 | enable_irq(host->irq); | ||
299 | else | ||
300 | disable_irq_nosync(host->irq); | ||
301 | } | ||
302 | |||
303 | static void irq_control_v1_v2(struct mxc_nand_host *host, int activate) | 304 | static void irq_control_v1_v2(struct mxc_nand_host *host, int activate) |
304 | { | 305 | { |
305 | uint16_t tmp; | 306 | uint16_t tmp; |
@@ -328,6 +329,47 @@ static void irq_control_v3(struct mxc_nand_host *host, int activate) | |||
328 | writel(tmp, NFC_V3_CONFIG2); | 329 | writel(tmp, NFC_V3_CONFIG2); |
329 | } | 330 | } |
330 | 331 | ||
332 | static void irq_control(struct mxc_nand_host *host, int activate) | ||
333 | { | ||
334 | if (host->devtype_data->irqpending_quirk) { | ||
335 | if (activate) | ||
336 | enable_irq(host->irq); | ||
337 | else | ||
338 | disable_irq_nosync(host->irq); | ||
339 | } else { | ||
340 | host->devtype_data->irq_control(host, activate); | ||
341 | } | ||
342 | } | ||
343 | |||
344 | static u32 get_ecc_status_v1(struct mxc_nand_host *host) | ||
345 | { | ||
346 | return readw(NFC_V1_V2_ECC_STATUS_RESULT); | ||
347 | } | ||
348 | |||
349 | static u32 get_ecc_status_v2(struct mxc_nand_host *host) | ||
350 | { | ||
351 | return readl(NFC_V1_V2_ECC_STATUS_RESULT); | ||
352 | } | ||
353 | |||
354 | static u32 get_ecc_status_v3(struct mxc_nand_host *host) | ||
355 | { | ||
356 | return readl(NFC_V3_ECC_STATUS_RESULT); | ||
357 | } | ||
358 | |||
359 | static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) | ||
360 | { | ||
361 | struct mxc_nand_host *host = dev_id; | ||
362 | |||
363 | if (!host->devtype_data->check_int(host)) | ||
364 | return IRQ_NONE; | ||
365 | |||
366 | irq_control(host, 0); | ||
367 | |||
368 | complete(&host->op_completion); | ||
369 | |||
370 | return IRQ_HANDLED; | ||
371 | } | ||
372 | |||
331 | /* This function polls the NANDFC to wait for the basic operation to | 373 | /* This function polls the NANDFC to wait for the basic operation to |
332 | * complete by checking the INT bit of config2 register. | 374 | * complete by checking the INT bit of config2 register. |
333 | */ | 375 | */ |
@@ -336,14 +378,14 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq) | |||
336 | int max_retries = 8000; | 378 | int max_retries = 8000; |
337 | 379 | ||
338 | if (useirq) { | 380 | if (useirq) { |
339 | if (!host->check_int(host)) { | 381 | if (!host->devtype_data->check_int(host)) { |
340 | INIT_COMPLETION(host->op_completion); | 382 | INIT_COMPLETION(host->op_completion); |
341 | host->irq_control(host, 1); | 383 | irq_control(host, 1); |
342 | wait_for_completion(&host->op_completion); | 384 | wait_for_completion(&host->op_completion); |
343 | } | 385 | } |
344 | } else { | 386 | } else { |
345 | while (max_retries-- > 0) { | 387 | while (max_retries-- > 0) { |
346 | if (host->check_int(host)) | 388 | if (host->devtype_data->check_int(host)) |
347 | break; | 389 | break; |
348 | 390 | ||
349 | udelay(1); | 391 | udelay(1); |
@@ -374,7 +416,7 @@ static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq) | |||
374 | writew(cmd, NFC_V1_V2_FLASH_CMD); | 416 | writew(cmd, NFC_V1_V2_FLASH_CMD); |
375 | writew(NFC_CMD, NFC_V1_V2_CONFIG2); | 417 | writew(NFC_CMD, NFC_V1_V2_CONFIG2); |
376 | 418 | ||
377 | if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) { | 419 | if (host->devtype_data->irqpending_quirk && (cmd == NAND_CMD_RESET)) { |
378 | int max_retries = 100; | 420 | int max_retries = 100; |
379 | /* Reset completion is indicated by NFC_CONFIG2 */ | 421 | /* Reset completion is indicated by NFC_CONFIG2 */ |
380 | /* being set to 0 */ | 422 | /* being set to 0 */ |
@@ -433,13 +475,27 @@ static void send_page_v3(struct mtd_info *mtd, unsigned int ops) | |||
433 | wait_op_done(host, false); | 475 | wait_op_done(host, false); |
434 | } | 476 | } |
435 | 477 | ||
436 | static void send_page_v1_v2(struct mtd_info *mtd, unsigned int ops) | 478 | static void send_page_v2(struct mtd_info *mtd, unsigned int ops) |
479 | { | ||
480 | struct nand_chip *nand_chip = mtd->priv; | ||
481 | struct mxc_nand_host *host = nand_chip->priv; | ||
482 | |||
483 | /* NANDFC buffer 0 is used for page read/write */ | ||
484 | writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); | ||
485 | |||
486 | writew(ops, NFC_V1_V2_CONFIG2); | ||
487 | |||
488 | /* Wait for operation to complete */ | ||
489 | wait_op_done(host, true); | ||
490 | } | ||
491 | |||
492 | static void send_page_v1(struct mtd_info *mtd, unsigned int ops) | ||
437 | { | 493 | { |
438 | struct nand_chip *nand_chip = mtd->priv; | 494 | struct nand_chip *nand_chip = mtd->priv; |
439 | struct mxc_nand_host *host = nand_chip->priv; | 495 | struct mxc_nand_host *host = nand_chip->priv; |
440 | int bufs, i; | 496 | int bufs, i; |
441 | 497 | ||
442 | if (nfc_is_v1() && mtd->writesize > 512) | 498 | if (mtd->writesize > 512) |
443 | bufs = 4; | 499 | bufs = 4; |
444 | else | 500 | else |
445 | bufs = 1; | 501 | bufs = 1; |
@@ -463,7 +519,7 @@ static void send_read_id_v3(struct mxc_nand_host *host) | |||
463 | 519 | ||
464 | wait_op_done(host, true); | 520 | wait_op_done(host, true); |
465 | 521 | ||
466 | memcpy(host->data_buf, host->main_area0, 16); | 522 | memcpy_fromio(host->data_buf, host->main_area0, 16); |
467 | } | 523 | } |
468 | 524 | ||
469 | /* Request the NANDFC to perform a read of the NAND device ID. */ | 525 | /* Request the NANDFC to perform a read of the NAND device ID. */ |
@@ -479,7 +535,7 @@ static void send_read_id_v1_v2(struct mxc_nand_host *host) | |||
479 | /* Wait for operation to complete */ | 535 | /* Wait for operation to complete */ |
480 | wait_op_done(host, true); | 536 | wait_op_done(host, true); |
481 | 537 | ||
482 | memcpy(host->data_buf, host->main_area0, 16); | 538 | memcpy_fromio(host->data_buf, host->main_area0, 16); |
483 | 539 | ||
484 | if (this->options & NAND_BUSWIDTH_16) { | 540 | if (this->options & NAND_BUSWIDTH_16) { |
485 | /* compress the ID info */ | 541 | /* compress the ID info */ |
@@ -555,7 +611,7 @@ static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat, | |||
555 | * additional correction. 2-Bit errors cannot be corrected by | 611 | * additional correction. 2-Bit errors cannot be corrected by |
556 | * HW ECC, so we need to return failure | 612 | * HW ECC, so we need to return failure |
557 | */ | 613 | */ |
558 | uint16_t ecc_status = readw(NFC_V1_V2_ECC_STATUS_RESULT); | 614 | uint16_t ecc_status = get_ecc_status_v1(host); |
559 | 615 | ||
560 | if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { | 616 | if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { |
561 | pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n"); | 617 | pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n"); |
@@ -580,10 +636,7 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat, | |||
580 | 636 | ||
581 | no_subpages = mtd->writesize >> 9; | 637 | no_subpages = mtd->writesize >> 9; |
582 | 638 | ||
583 | if (nfc_is_v21()) | 639 | ecc_stat = host->devtype_data->get_ecc_status(host); |
584 | ecc_stat = readl(NFC_V1_V2_ECC_STATUS_RESULT); | ||
585 | else | ||
586 | ecc_stat = readl(NFC_V3_ECC_STATUS_RESULT); | ||
587 | 640 | ||
588 | do { | 641 | do { |
589 | err = ecc_stat & ecc_bit_mask; | 642 | err = ecc_stat & ecc_bit_mask; |
@@ -616,7 +669,7 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd) | |||
616 | 669 | ||
617 | /* Check for status request */ | 670 | /* Check for status request */ |
618 | if (host->status_request) | 671 | if (host->status_request) |
619 | return host->get_dev_status(host) & 0xFF; | 672 | return host->devtype_data->get_dev_status(host) & 0xFF; |
620 | 673 | ||
621 | ret = *(uint8_t *)(host->data_buf + host->buf_start); | 674 | ret = *(uint8_t *)(host->data_buf + host->buf_start); |
622 | host->buf_start++; | 675 | host->buf_start++; |
@@ -682,7 +735,7 @@ static int mxc_nand_verify_buf(struct mtd_info *mtd, | |||
682 | 735 | ||
683 | /* This function is used by upper layer for select and | 736 | /* This function is used by upper layer for select and |
684 | * deselect of the NAND chip */ | 737 | * deselect of the NAND chip */ |
685 | static void mxc_nand_select_chip(struct mtd_info *mtd, int chip) | 738 | static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip) |
686 | { | 739 | { |
687 | struct nand_chip *nand_chip = mtd->priv; | 740 | struct nand_chip *nand_chip = mtd->priv; |
688 | struct mxc_nand_host *host = nand_chip->priv; | 741 | struct mxc_nand_host *host = nand_chip->priv; |
@@ -701,11 +754,30 @@ static void mxc_nand_select_chip(struct mtd_info *mtd, int chip) | |||
701 | clk_prepare_enable(host->clk); | 754 | clk_prepare_enable(host->clk); |
702 | host->clk_act = 1; | 755 | host->clk_act = 1; |
703 | } | 756 | } |
757 | } | ||
704 | 758 | ||
705 | if (nfc_is_v21()) { | 759 | static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip) |
706 | host->active_cs = chip; | 760 | { |
707 | writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); | 761 | struct nand_chip *nand_chip = mtd->priv; |
762 | struct mxc_nand_host *host = nand_chip->priv; | ||
763 | |||
764 | if (chip == -1) { | ||
765 | /* Disable the NFC clock */ | ||
766 | if (host->clk_act) { | ||
767 | clk_disable(host->clk); | ||
768 | host->clk_act = 0; | ||
769 | } | ||
770 | return; | ||
771 | } | ||
772 | |||
773 | if (!host->clk_act) { | ||
774 | /* Enable the NFC clock */ | ||
775 | clk_enable(host->clk); | ||
776 | host->clk_act = 1; | ||
708 | } | 777 | } |
778 | |||
779 | host->active_cs = chip; | ||
780 | writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); | ||
709 | } | 781 | } |
710 | 782 | ||
711 | /* | 783 | /* |
@@ -718,23 +790,23 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom) | |||
718 | u16 i, j; | 790 | u16 i, j; |
719 | u16 n = mtd->writesize >> 9; | 791 | u16 n = mtd->writesize >> 9; |
720 | u8 *d = host->data_buf + mtd->writesize; | 792 | u8 *d = host->data_buf + mtd->writesize; |
721 | u8 *s = host->spare0; | 793 | u8 __iomem *s = host->spare0; |
722 | u16 t = host->spare_len; | 794 | u16 t = host->devtype_data->spare_len; |
723 | 795 | ||
724 | j = (mtd->oobsize / n >> 1) << 1; | 796 | j = (mtd->oobsize / n >> 1) << 1; |
725 | 797 | ||
726 | if (bfrom) { | 798 | if (bfrom) { |
727 | for (i = 0; i < n - 1; i++) | 799 | for (i = 0; i < n - 1; i++) |
728 | memcpy(d + i * j, s + i * t, j); | 800 | memcpy_fromio(d + i * j, s + i * t, j); |
729 | 801 | ||
730 | /* the last section */ | 802 | /* the last section */ |
731 | memcpy(d + i * j, s + i * t, mtd->oobsize - i * j); | 803 | memcpy_fromio(d + i * j, s + i * t, mtd->oobsize - i * j); |
732 | } else { | 804 | } else { |
733 | for (i = 0; i < n - 1; i++) | 805 | for (i = 0; i < n - 1; i++) |
734 | memcpy(&s[i * t], &d[i * j], j); | 806 | memcpy_toio(&s[i * t], &d[i * j], j); |
735 | 807 | ||
736 | /* the last section */ | 808 | /* the last section */ |
737 | memcpy(&s[i * t], &d[i * j], mtd->oobsize - i * j); | 809 | memcpy_toio(&s[i * t], &d[i * j], mtd->oobsize - i * j); |
738 | } | 810 | } |
739 | } | 811 | } |
740 | 812 | ||
@@ -751,34 +823,44 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) | |||
751 | * perform a read/write buf operation, the saved column | 823 | * perform a read/write buf operation, the saved column |
752 | * address is used to index into the full page. | 824 | * address is used to index into the full page. |
753 | */ | 825 | */ |
754 | host->send_addr(host, 0, page_addr == -1); | 826 | host->devtype_data->send_addr(host, 0, page_addr == -1); |
755 | if (mtd->writesize > 512) | 827 | if (mtd->writesize > 512) |
756 | /* another col addr cycle for 2k page */ | 828 | /* another col addr cycle for 2k page */ |
757 | host->send_addr(host, 0, false); | 829 | host->devtype_data->send_addr(host, 0, false); |
758 | } | 830 | } |
759 | 831 | ||
760 | /* Write out page address, if necessary */ | 832 | /* Write out page address, if necessary */ |
761 | if (page_addr != -1) { | 833 | if (page_addr != -1) { |
762 | /* paddr_0 - p_addr_7 */ | 834 | /* paddr_0 - p_addr_7 */ |
763 | host->send_addr(host, (page_addr & 0xff), false); | 835 | host->devtype_data->send_addr(host, (page_addr & 0xff), false); |
764 | 836 | ||
765 | if (mtd->writesize > 512) { | 837 | if (mtd->writesize > 512) { |
766 | if (mtd->size >= 0x10000000) { | 838 | if (mtd->size >= 0x10000000) { |
767 | /* paddr_8 - paddr_15 */ | 839 | /* paddr_8 - paddr_15 */ |
768 | host->send_addr(host, (page_addr >> 8) & 0xff, false); | 840 | host->devtype_data->send_addr(host, |
769 | host->send_addr(host, (page_addr >> 16) & 0xff, true); | 841 | (page_addr >> 8) & 0xff, |
842 | false); | ||
843 | host->devtype_data->send_addr(host, | ||
844 | (page_addr >> 16) & 0xff, | ||
845 | true); | ||
770 | } else | 846 | } else |
771 | /* paddr_8 - paddr_15 */ | 847 | /* paddr_8 - paddr_15 */ |
772 | host->send_addr(host, (page_addr >> 8) & 0xff, true); | 848 | host->devtype_data->send_addr(host, |
849 | (page_addr >> 8) & 0xff, true); | ||
773 | } else { | 850 | } else { |
774 | /* One more address cycle for higher density devices */ | 851 | /* One more address cycle for higher density devices */ |
775 | if (mtd->size >= 0x4000000) { | 852 | if (mtd->size >= 0x4000000) { |
776 | /* paddr_8 - paddr_15 */ | 853 | /* paddr_8 - paddr_15 */ |
777 | host->send_addr(host, (page_addr >> 8) & 0xff, false); | 854 | host->devtype_data->send_addr(host, |
778 | host->send_addr(host, (page_addr >> 16) & 0xff, true); | 855 | (page_addr >> 8) & 0xff, |
856 | false); | ||
857 | host->devtype_data->send_addr(host, | ||
858 | (page_addr >> 16) & 0xff, | ||
859 | true); | ||
779 | } else | 860 | } else |
780 | /* paddr_8 - paddr_15 */ | 861 | /* paddr_8 - paddr_15 */ |
781 | host->send_addr(host, (page_addr >> 8) & 0xff, true); | 862 | host->devtype_data->send_addr(host, |
863 | (page_addr >> 8) & 0xff, true); | ||
782 | } | 864 | } |
783 | } | 865 | } |
784 | } | 866 | } |
@@ -800,7 +882,35 @@ static int get_eccsize(struct mtd_info *mtd) | |||
800 | return 8; | 882 | return 8; |
801 | } | 883 | } |
802 | 884 | ||
803 | static void preset_v1_v2(struct mtd_info *mtd) | 885 | static void preset_v1(struct mtd_info *mtd) |
886 | { | ||
887 | struct nand_chip *nand_chip = mtd->priv; | ||
888 | struct mxc_nand_host *host = nand_chip->priv; | ||
889 | uint16_t config1 = 0; | ||
890 | |||
891 | if (nand_chip->ecc.mode == NAND_ECC_HW) | ||
892 | config1 |= NFC_V1_V2_CONFIG1_ECC_EN; | ||
893 | |||
894 | if (!host->devtype_data->irqpending_quirk) | ||
895 | config1 |= NFC_V1_V2_CONFIG1_INT_MSK; | ||
896 | |||
897 | host->eccsize = 1; | ||
898 | |||
899 | writew(config1, NFC_V1_V2_CONFIG1); | ||
900 | /* preset operation */ | ||
901 | |||
902 | /* Unlock the internal RAM Buffer */ | ||
903 | writew(0x2, NFC_V1_V2_CONFIG); | ||
904 | |||
905 | /* Blocks to be unlocked */ | ||
906 | writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR); | ||
907 | writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR); | ||
908 | |||
909 | /* Unlock Block Command for given address range */ | ||
910 | writew(0x4, NFC_V1_V2_WRPROT); | ||
911 | } | ||
912 | |||
913 | static void preset_v2(struct mtd_info *mtd) | ||
804 | { | 914 | { |
805 | struct nand_chip *nand_chip = mtd->priv; | 915 | struct nand_chip *nand_chip = mtd->priv; |
806 | struct mxc_nand_host *host = nand_chip->priv; | 916 | struct mxc_nand_host *host = nand_chip->priv; |
@@ -809,13 +919,12 @@ static void preset_v1_v2(struct mtd_info *mtd) | |||
809 | if (nand_chip->ecc.mode == NAND_ECC_HW) | 919 | if (nand_chip->ecc.mode == NAND_ECC_HW) |
810 | config1 |= NFC_V1_V2_CONFIG1_ECC_EN; | 920 | config1 |= NFC_V1_V2_CONFIG1_ECC_EN; |
811 | 921 | ||
812 | if (nfc_is_v21()) | 922 | config1 |= NFC_V2_CONFIG1_FP_INT; |
813 | config1 |= NFC_V2_CONFIG1_FP_INT; | ||
814 | 923 | ||
815 | if (!cpu_is_mx21()) | 924 | if (!host->devtype_data->irqpending_quirk) |
816 | config1 |= NFC_V1_V2_CONFIG1_INT_MSK; | 925 | config1 |= NFC_V1_V2_CONFIG1_INT_MSK; |
817 | 926 | ||
818 | if (nfc_is_v21() && mtd->writesize) { | 927 | if (mtd->writesize) { |
819 | uint16_t pages_per_block = mtd->erasesize / mtd->writesize; | 928 | uint16_t pages_per_block = mtd->erasesize / mtd->writesize; |
820 | 929 | ||
821 | host->eccsize = get_eccsize(mtd); | 930 | host->eccsize = get_eccsize(mtd); |
@@ -834,20 +943,14 @@ static void preset_v1_v2(struct mtd_info *mtd) | |||
834 | writew(0x2, NFC_V1_V2_CONFIG); | 943 | writew(0x2, NFC_V1_V2_CONFIG); |
835 | 944 | ||
836 | /* Blocks to be unlocked */ | 945 | /* Blocks to be unlocked */ |
837 | if (nfc_is_v21()) { | 946 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0); |
838 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0); | 947 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1); |
839 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1); | 948 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2); |
840 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2); | 949 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3); |
841 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3); | 950 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0); |
842 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0); | 951 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1); |
843 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1); | 952 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2); |
844 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2); | 953 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3); |
845 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3); | ||
846 | } else if (nfc_is_v1()) { | ||
847 | writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR); | ||
848 | writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR); | ||
849 | } else | ||
850 | BUG(); | ||
851 | 954 | ||
852 | /* Unlock Block Command for given address range */ | 955 | /* Unlock Block Command for given address range */ |
853 | writew(0x4, NFC_V1_V2_WRPROT); | 956 | writew(0x4, NFC_V1_V2_WRPROT); |
@@ -937,15 +1040,15 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
937 | /* Command pre-processing step */ | 1040 | /* Command pre-processing step */ |
938 | switch (command) { | 1041 | switch (command) { |
939 | case NAND_CMD_RESET: | 1042 | case NAND_CMD_RESET: |
940 | host->preset(mtd); | 1043 | host->devtype_data->preset(mtd); |
941 | host->send_cmd(host, command, false); | 1044 | host->devtype_data->send_cmd(host, command, false); |
942 | break; | 1045 | break; |
943 | 1046 | ||
944 | case NAND_CMD_STATUS: | 1047 | case NAND_CMD_STATUS: |
945 | host->buf_start = 0; | 1048 | host->buf_start = 0; |
946 | host->status_request = true; | 1049 | host->status_request = true; |
947 | 1050 | ||
948 | host->send_cmd(host, command, true); | 1051 | host->devtype_data->send_cmd(host, command, true); |
949 | mxc_do_addr_cycle(mtd, column, page_addr); | 1052 | mxc_do_addr_cycle(mtd, column, page_addr); |
950 | break; | 1053 | break; |
951 | 1054 | ||
@@ -958,15 +1061,16 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
958 | 1061 | ||
959 | command = NAND_CMD_READ0; /* only READ0 is valid */ | 1062 | command = NAND_CMD_READ0; /* only READ0 is valid */ |
960 | 1063 | ||
961 | host->send_cmd(host, command, false); | 1064 | host->devtype_data->send_cmd(host, command, false); |
962 | mxc_do_addr_cycle(mtd, column, page_addr); | 1065 | mxc_do_addr_cycle(mtd, column, page_addr); |
963 | 1066 | ||
964 | if (mtd->writesize > 512) | 1067 | if (mtd->writesize > 512) |
965 | host->send_cmd(host, NAND_CMD_READSTART, true); | 1068 | host->devtype_data->send_cmd(host, |
1069 | NAND_CMD_READSTART, true); | ||
966 | 1070 | ||
967 | host->send_page(mtd, NFC_OUTPUT); | 1071 | host->devtype_data->send_page(mtd, NFC_OUTPUT); |
968 | 1072 | ||
969 | memcpy(host->data_buf, host->main_area0, mtd->writesize); | 1073 | memcpy_fromio(host->data_buf, host->main_area0, mtd->writesize); |
970 | copy_spare(mtd, true); | 1074 | copy_spare(mtd, true); |
971 | break; | 1075 | break; |
972 | 1076 | ||
@@ -977,28 +1081,28 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
977 | 1081 | ||
978 | host->buf_start = column; | 1082 | host->buf_start = column; |
979 | 1083 | ||
980 | host->send_cmd(host, command, false); | 1084 | host->devtype_data->send_cmd(host, command, false); |
981 | mxc_do_addr_cycle(mtd, column, page_addr); | 1085 | mxc_do_addr_cycle(mtd, column, page_addr); |
982 | break; | 1086 | break; |
983 | 1087 | ||
984 | case NAND_CMD_PAGEPROG: | 1088 | case NAND_CMD_PAGEPROG: |
985 | memcpy(host->main_area0, host->data_buf, mtd->writesize); | 1089 | memcpy_toio(host->main_area0, host->data_buf, mtd->writesize); |
986 | copy_spare(mtd, false); | 1090 | copy_spare(mtd, false); |
987 | host->send_page(mtd, NFC_INPUT); | 1091 | host->devtype_data->send_page(mtd, NFC_INPUT); |
988 | host->send_cmd(host, command, true); | 1092 | host->devtype_data->send_cmd(host, command, true); |
989 | mxc_do_addr_cycle(mtd, column, page_addr); | 1093 | mxc_do_addr_cycle(mtd, column, page_addr); |
990 | break; | 1094 | break; |
991 | 1095 | ||
992 | case NAND_CMD_READID: | 1096 | case NAND_CMD_READID: |
993 | host->send_cmd(host, command, true); | 1097 | host->devtype_data->send_cmd(host, command, true); |
994 | mxc_do_addr_cycle(mtd, column, page_addr); | 1098 | mxc_do_addr_cycle(mtd, column, page_addr); |
995 | host->send_read_id(host); | 1099 | host->devtype_data->send_read_id(host); |
996 | host->buf_start = column; | 1100 | host->buf_start = column; |
997 | break; | 1101 | break; |
998 | 1102 | ||
999 | case NAND_CMD_ERASE1: | 1103 | case NAND_CMD_ERASE1: |
1000 | case NAND_CMD_ERASE2: | 1104 | case NAND_CMD_ERASE2: |
1001 | host->send_cmd(host, command, false); | 1105 | host->devtype_data->send_cmd(host, command, false); |
1002 | mxc_do_addr_cycle(mtd, column, page_addr); | 1106 | mxc_do_addr_cycle(mtd, column, page_addr); |
1003 | 1107 | ||
1004 | break; | 1108 | break; |
@@ -1032,15 +1136,191 @@ static struct nand_bbt_descr bbt_mirror_descr = { | |||
1032 | .pattern = mirror_pattern, | 1136 | .pattern = mirror_pattern, |
1033 | }; | 1137 | }; |
1034 | 1138 | ||
1139 | /* v1 + irqpending_quirk: i.MX21 */ | ||
1140 | static const struct mxc_nand_devtype_data imx21_nand_devtype_data = { | ||
1141 | .preset = preset_v1, | ||
1142 | .send_cmd = send_cmd_v1_v2, | ||
1143 | .send_addr = send_addr_v1_v2, | ||
1144 | .send_page = send_page_v1, | ||
1145 | .send_read_id = send_read_id_v1_v2, | ||
1146 | .get_dev_status = get_dev_status_v1_v2, | ||
1147 | .check_int = check_int_v1_v2, | ||
1148 | .irq_control = irq_control_v1_v2, | ||
1149 | .get_ecc_status = get_ecc_status_v1, | ||
1150 | .ecclayout_512 = &nandv1_hw_eccoob_smallpage, | ||
1151 | .ecclayout_2k = &nandv1_hw_eccoob_largepage, | ||
1152 | .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */ | ||
1153 | .select_chip = mxc_nand_select_chip_v1_v3, | ||
1154 | .correct_data = mxc_nand_correct_data_v1, | ||
1155 | .irqpending_quirk = 1, | ||
1156 | .needs_ip = 0, | ||
1157 | .regs_offset = 0xe00, | ||
1158 | .spare0_offset = 0x800, | ||
1159 | .spare_len = 16, | ||
1160 | .eccbytes = 3, | ||
1161 | .eccsize = 1, | ||
1162 | }; | ||
1163 | |||
1164 | /* v1 + !irqpending_quirk: i.MX27, i.MX31 */ | ||
1165 | static const struct mxc_nand_devtype_data imx27_nand_devtype_data = { | ||
1166 | .preset = preset_v1, | ||
1167 | .send_cmd = send_cmd_v1_v2, | ||
1168 | .send_addr = send_addr_v1_v2, | ||
1169 | .send_page = send_page_v1, | ||
1170 | .send_read_id = send_read_id_v1_v2, | ||
1171 | .get_dev_status = get_dev_status_v1_v2, | ||
1172 | .check_int = check_int_v1_v2, | ||
1173 | .irq_control = irq_control_v1_v2, | ||
1174 | .get_ecc_status = get_ecc_status_v1, | ||
1175 | .ecclayout_512 = &nandv1_hw_eccoob_smallpage, | ||
1176 | .ecclayout_2k = &nandv1_hw_eccoob_largepage, | ||
1177 | .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */ | ||
1178 | .select_chip = mxc_nand_select_chip_v1_v3, | ||
1179 | .correct_data = mxc_nand_correct_data_v1, | ||
1180 | .irqpending_quirk = 0, | ||
1181 | .needs_ip = 0, | ||
1182 | .regs_offset = 0xe00, | ||
1183 | .spare0_offset = 0x800, | ||
1184 | .axi_offset = 0, | ||
1185 | .spare_len = 16, | ||
1186 | .eccbytes = 3, | ||
1187 | .eccsize = 1, | ||
1188 | }; | ||
1189 | |||
1190 | /* v21: i.MX25, i.MX35 */ | ||
1191 | static const struct mxc_nand_devtype_data imx25_nand_devtype_data = { | ||
1192 | .preset = preset_v2, | ||
1193 | .send_cmd = send_cmd_v1_v2, | ||
1194 | .send_addr = send_addr_v1_v2, | ||
1195 | .send_page = send_page_v2, | ||
1196 | .send_read_id = send_read_id_v1_v2, | ||
1197 | .get_dev_status = get_dev_status_v1_v2, | ||
1198 | .check_int = check_int_v1_v2, | ||
1199 | .irq_control = irq_control_v1_v2, | ||
1200 | .get_ecc_status = get_ecc_status_v2, | ||
1201 | .ecclayout_512 = &nandv2_hw_eccoob_smallpage, | ||
1202 | .ecclayout_2k = &nandv2_hw_eccoob_largepage, | ||
1203 | .ecclayout_4k = &nandv2_hw_eccoob_4k, | ||
1204 | .select_chip = mxc_nand_select_chip_v2, | ||
1205 | .correct_data = mxc_nand_correct_data_v2_v3, | ||
1206 | .irqpending_quirk = 0, | ||
1207 | .needs_ip = 0, | ||
1208 | .regs_offset = 0x1e00, | ||
1209 | .spare0_offset = 0x1000, | ||
1210 | .axi_offset = 0, | ||
1211 | .spare_len = 64, | ||
1212 | .eccbytes = 9, | ||
1213 | .eccsize = 0, | ||
1214 | }; | ||
1215 | |||
1216 | /* v3: i.MX51, i.MX53 */ | ||
1217 | static const struct mxc_nand_devtype_data imx51_nand_devtype_data = { | ||
1218 | .preset = preset_v3, | ||
1219 | .send_cmd = send_cmd_v3, | ||
1220 | .send_addr = send_addr_v3, | ||
1221 | .send_page = send_page_v3, | ||
1222 | .send_read_id = send_read_id_v3, | ||
1223 | .get_dev_status = get_dev_status_v3, | ||
1224 | .check_int = check_int_v3, | ||
1225 | .irq_control = irq_control_v3, | ||
1226 | .get_ecc_status = get_ecc_status_v3, | ||
1227 | .ecclayout_512 = &nandv2_hw_eccoob_smallpage, | ||
1228 | .ecclayout_2k = &nandv2_hw_eccoob_largepage, | ||
1229 | .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */ | ||
1230 | .select_chip = mxc_nand_select_chip_v1_v3, | ||
1231 | .correct_data = mxc_nand_correct_data_v2_v3, | ||
1232 | .irqpending_quirk = 0, | ||
1233 | .needs_ip = 1, | ||
1234 | .regs_offset = 0, | ||
1235 | .spare0_offset = 0x1000, | ||
1236 | .axi_offset = 0x1e00, | ||
1237 | .spare_len = 64, | ||
1238 | .eccbytes = 0, | ||
1239 | .eccsize = 0, | ||
1240 | }; | ||
1241 | |||
1242 | #ifdef CONFIG_OF_MTD | ||
1243 | static const struct of_device_id mxcnd_dt_ids[] = { | ||
1244 | { | ||
1245 | .compatible = "fsl,imx21-nand", | ||
1246 | .data = &imx21_nand_devtype_data, | ||
1247 | }, { | ||
1248 | .compatible = "fsl,imx27-nand", | ||
1249 | .data = &imx27_nand_devtype_data, | ||
1250 | }, { | ||
1251 | .compatible = "fsl,imx25-nand", | ||
1252 | .data = &imx25_nand_devtype_data, | ||
1253 | }, { | ||
1254 | .compatible = "fsl,imx51-nand", | ||
1255 | .data = &imx51_nand_devtype_data, | ||
1256 | }, | ||
1257 | { /* sentinel */ } | ||
1258 | }; | ||
1259 | |||
1260 | static int __init mxcnd_probe_dt(struct mxc_nand_host *host) | ||
1261 | { | ||
1262 | struct device_node *np = host->dev->of_node; | ||
1263 | struct mxc_nand_platform_data *pdata = &host->pdata; | ||
1264 | const struct of_device_id *of_id = | ||
1265 | of_match_device(mxcnd_dt_ids, host->dev); | ||
1266 | int buswidth; | ||
1267 | |||
1268 | if (!np) | ||
1269 | return 1; | ||
1270 | |||
1271 | if (of_get_nand_ecc_mode(np) >= 0) | ||
1272 | pdata->hw_ecc = 1; | ||
1273 | |||
1274 | pdata->flash_bbt = of_get_nand_on_flash_bbt(np); | ||
1275 | |||
1276 | buswidth = of_get_nand_bus_width(np); | ||
1277 | if (buswidth < 0) | ||
1278 | return buswidth; | ||
1279 | |||
1280 | pdata->width = buswidth / 8; | ||
1281 | |||
1282 | host->devtype_data = of_id->data; | ||
1283 | |||
1284 | return 0; | ||
1285 | } | ||
1286 | #else | ||
1287 | static int __init mxcnd_probe_dt(struct mxc_nand_host *host) | ||
1288 | { | ||
1289 | return 1; | ||
1290 | } | ||
1291 | #endif | ||
1292 | |||
1293 | static int __init mxcnd_probe_pdata(struct mxc_nand_host *host) | ||
1294 | { | ||
1295 | struct mxc_nand_platform_data *pdata = host->dev->platform_data; | ||
1296 | |||
1297 | if (!pdata) | ||
1298 | return -ENODEV; | ||
1299 | |||
1300 | host->pdata = *pdata; | ||
1301 | |||
1302 | if (nfc_is_v1()) { | ||
1303 | if (cpu_is_mx21()) | ||
1304 | host->devtype_data = &imx21_nand_devtype_data; | ||
1305 | else | ||
1306 | host->devtype_data = &imx27_nand_devtype_data; | ||
1307 | } else if (nfc_is_v21()) { | ||
1308 | host->devtype_data = &imx25_nand_devtype_data; | ||
1309 | } else if (nfc_is_v3_2()) { | ||
1310 | host->devtype_data = &imx51_nand_devtype_data; | ||
1311 | } else | ||
1312 | BUG(); | ||
1313 | |||
1314 | return 0; | ||
1315 | } | ||
1316 | |||
1035 | static int __init mxcnd_probe(struct platform_device *pdev) | 1317 | static int __init mxcnd_probe(struct platform_device *pdev) |
1036 | { | 1318 | { |
1037 | struct nand_chip *this; | 1319 | struct nand_chip *this; |
1038 | struct mtd_info *mtd; | 1320 | struct mtd_info *mtd; |
1039 | struct mxc_nand_platform_data *pdata = pdev->dev.platform_data; | ||
1040 | struct mxc_nand_host *host; | 1321 | struct mxc_nand_host *host; |
1041 | struct resource *res; | 1322 | struct resource *res; |
1042 | int err = 0; | 1323 | int err = 0; |
1043 | struct nand_ecclayout *oob_smallpage, *oob_largepage; | ||
1044 | 1324 | ||
1045 | /* Allocate memory for MTD device structure and private data */ | 1325 | /* Allocate memory for MTD device structure and private data */ |
1046 | host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE + | 1326 | host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE + |
@@ -1065,7 +1345,6 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1065 | this->priv = host; | 1345 | this->priv = host; |
1066 | this->dev_ready = mxc_nand_dev_ready; | 1346 | this->dev_ready = mxc_nand_dev_ready; |
1067 | this->cmdfunc = mxc_nand_command; | 1347 | this->cmdfunc = mxc_nand_command; |
1068 | this->select_chip = mxc_nand_select_chip; | ||
1069 | this->read_byte = mxc_nand_read_byte; | 1348 | this->read_byte = mxc_nand_read_byte; |
1070 | this->read_word = mxc_nand_read_word; | 1349 | this->read_word = mxc_nand_read_word; |
1071 | this->write_buf = mxc_nand_write_buf; | 1350 | this->write_buf = mxc_nand_write_buf; |
@@ -1095,36 +1374,26 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1095 | 1374 | ||
1096 | host->main_area0 = host->base; | 1375 | host->main_area0 = host->base; |
1097 | 1376 | ||
1098 | if (nfc_is_v1() || nfc_is_v21()) { | 1377 | err = mxcnd_probe_dt(host); |
1099 | host->preset = preset_v1_v2; | 1378 | if (err > 0) |
1100 | host->send_cmd = send_cmd_v1_v2; | 1379 | err = mxcnd_probe_pdata(host); |
1101 | host->send_addr = send_addr_v1_v2; | 1380 | if (err < 0) |
1102 | host->send_page = send_page_v1_v2; | 1381 | goto eirq; |
1103 | host->send_read_id = send_read_id_v1_v2; | ||
1104 | host->get_dev_status = get_dev_status_v1_v2; | ||
1105 | host->check_int = check_int_v1_v2; | ||
1106 | if (cpu_is_mx21()) | ||
1107 | host->irq_control = irq_control_mx21; | ||
1108 | else | ||
1109 | host->irq_control = irq_control_v1_v2; | ||
1110 | } | ||
1111 | 1382 | ||
1112 | if (nfc_is_v21()) { | 1383 | if (host->devtype_data->regs_offset) |
1113 | host->regs = host->base + 0x1e00; | 1384 | host->regs = host->base + host->devtype_data->regs_offset; |
1114 | host->spare0 = host->base + 0x1000; | 1385 | host->spare0 = host->base + host->devtype_data->spare0_offset; |
1115 | host->spare_len = 64; | 1386 | if (host->devtype_data->axi_offset) |
1116 | oob_smallpage = &nandv2_hw_eccoob_smallpage; | 1387 | host->regs_axi = host->base + host->devtype_data->axi_offset; |
1117 | oob_largepage = &nandv2_hw_eccoob_largepage; | 1388 | |
1118 | this->ecc.bytes = 9; | 1389 | this->ecc.bytes = host->devtype_data->eccbytes; |
1119 | } else if (nfc_is_v1()) { | 1390 | host->eccsize = host->devtype_data->eccsize; |
1120 | host->regs = host->base + 0xe00; | 1391 | |
1121 | host->spare0 = host->base + 0x800; | 1392 | this->select_chip = host->devtype_data->select_chip; |
1122 | host->spare_len = 16; | 1393 | this->ecc.size = 512; |
1123 | oob_smallpage = &nandv1_hw_eccoob_smallpage; | 1394 | this->ecc.layout = host->devtype_data->ecclayout_512; |
1124 | oob_largepage = &nandv1_hw_eccoob_largepage; | 1395 | |
1125 | this->ecc.bytes = 3; | 1396 | if (host->devtype_data->needs_ip) { |
1126 | host->eccsize = 1; | ||
1127 | } else if (nfc_is_v3_2()) { | ||
1128 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 1397 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
1129 | if (!res) { | 1398 | if (!res) { |
1130 | err = -ENODEV; | 1399 | err = -ENODEV; |
@@ -1135,42 +1404,22 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1135 | err = -ENOMEM; | 1404 | err = -ENOMEM; |
1136 | goto eirq; | 1405 | goto eirq; |
1137 | } | 1406 | } |
1138 | host->regs_axi = host->base + 0x1e00; | 1407 | } |
1139 | host->spare0 = host->base + 0x1000; | ||
1140 | host->spare_len = 64; | ||
1141 | host->preset = preset_v3; | ||
1142 | host->send_cmd = send_cmd_v3; | ||
1143 | host->send_addr = send_addr_v3; | ||
1144 | host->send_page = send_page_v3; | ||
1145 | host->send_read_id = send_read_id_v3; | ||
1146 | host->check_int = check_int_v3; | ||
1147 | host->get_dev_status = get_dev_status_v3; | ||
1148 | host->irq_control = irq_control_v3; | ||
1149 | oob_smallpage = &nandv2_hw_eccoob_smallpage; | ||
1150 | oob_largepage = &nandv2_hw_eccoob_largepage; | ||
1151 | } else | ||
1152 | BUG(); | ||
1153 | |||
1154 | this->ecc.size = 512; | ||
1155 | this->ecc.layout = oob_smallpage; | ||
1156 | 1408 | ||
1157 | if (pdata->hw_ecc) { | 1409 | if (host->pdata.hw_ecc) { |
1158 | this->ecc.calculate = mxc_nand_calculate_ecc; | 1410 | this->ecc.calculate = mxc_nand_calculate_ecc; |
1159 | this->ecc.hwctl = mxc_nand_enable_hwecc; | 1411 | this->ecc.hwctl = mxc_nand_enable_hwecc; |
1160 | if (nfc_is_v1()) | 1412 | this->ecc.correct = host->devtype_data->correct_data; |
1161 | this->ecc.correct = mxc_nand_correct_data_v1; | ||
1162 | else | ||
1163 | this->ecc.correct = mxc_nand_correct_data_v2_v3; | ||
1164 | this->ecc.mode = NAND_ECC_HW; | 1413 | this->ecc.mode = NAND_ECC_HW; |
1165 | } else { | 1414 | } else { |
1166 | this->ecc.mode = NAND_ECC_SOFT; | 1415 | this->ecc.mode = NAND_ECC_SOFT; |
1167 | } | 1416 | } |
1168 | 1417 | ||
1169 | /* NAND bus width determines access funtions used by upper layer */ | 1418 | /* NAND bus width determines access functions used by upper layer */ |
1170 | if (pdata->width == 2) | 1419 | if (host->pdata.width == 2) |
1171 | this->options |= NAND_BUSWIDTH_16; | 1420 | this->options |= NAND_BUSWIDTH_16; |
1172 | 1421 | ||
1173 | if (pdata->flash_bbt) { | 1422 | if (host->pdata.flash_bbt) { |
1174 | this->bbt_td = &bbt_main_descr; | 1423 | this->bbt_td = &bbt_main_descr; |
1175 | this->bbt_md = &bbt_mirror_descr; | 1424 | this->bbt_md = &bbt_mirror_descr; |
1176 | /* update flash based bbt */ | 1425 | /* update flash based bbt */ |
@@ -1182,28 +1431,25 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1182 | host->irq = platform_get_irq(pdev, 0); | 1431 | host->irq = platform_get_irq(pdev, 0); |
1183 | 1432 | ||
1184 | /* | 1433 | /* |
1185 | * mask the interrupt. For i.MX21 explicitely call | 1434 | * Use host->devtype_data->irq_control() here instead of irq_control() |
1186 | * irq_control_v1_v2 to use the mask bit. We can't call | 1435 | * because we must not disable_irq_nosync without having requested the |
1187 | * disable_irq_nosync() for an interrupt we do not own yet. | 1436 | * irq. |
1188 | */ | 1437 | */ |
1189 | if (cpu_is_mx21()) | 1438 | host->devtype_data->irq_control(host, 0); |
1190 | irq_control_v1_v2(host, 0); | ||
1191 | else | ||
1192 | host->irq_control(host, 0); | ||
1193 | 1439 | ||
1194 | err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host); | 1440 | err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host); |
1195 | if (err) | 1441 | if (err) |
1196 | goto eirq; | 1442 | goto eirq; |
1197 | 1443 | ||
1198 | host->irq_control(host, 0); | ||
1199 | |||
1200 | /* | 1444 | /* |
1201 | * Now that the interrupt is disabled make sure the interrupt | 1445 | * Now that we "own" the interrupt make sure the interrupt mask bit is |
1202 | * mask bit is cleared on i.MX21. Otherwise we can't read | 1446 | * cleared on i.MX21. Otherwise we can't read the interrupt status bit |
1203 | * the interrupt status bit on this machine. | 1447 | * on this machine. |
1204 | */ | 1448 | */ |
1205 | if (cpu_is_mx21()) | 1449 | if (host->devtype_data->irqpending_quirk) { |
1206 | irq_control_v1_v2(host, 1); | 1450 | disable_irq_nosync(host->irq); |
1451 | host->devtype_data->irq_control(host, 1); | ||
1452 | } | ||
1207 | 1453 | ||
1208 | /* first scan to find the device and get the page size */ | 1454 | /* first scan to find the device and get the page size */ |
1209 | if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) { | 1455 | if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) { |
@@ -1212,18 +1458,12 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1212 | } | 1458 | } |
1213 | 1459 | ||
1214 | /* Call preset again, with correct writesize this time */ | 1460 | /* Call preset again, with correct writesize this time */ |
1215 | host->preset(mtd); | 1461 | host->devtype_data->preset(mtd); |
1216 | 1462 | ||
1217 | if (mtd->writesize == 2048) | 1463 | if (mtd->writesize == 2048) |
1218 | this->ecc.layout = oob_largepage; | 1464 | this->ecc.layout = host->devtype_data->ecclayout_2k; |
1219 | if (nfc_is_v21() && mtd->writesize == 4096) | 1465 | else if (mtd->writesize == 4096) |
1220 | this->ecc.layout = &nandv2_hw_eccoob_4k; | 1466 | this->ecc.layout = host->devtype_data->ecclayout_4k; |
1221 | |||
1222 | /* second phase scan */ | ||
1223 | if (nand_scan_tail(mtd)) { | ||
1224 | err = -ENXIO; | ||
1225 | goto escan; | ||
1226 | } | ||
1227 | 1467 | ||
1228 | if (this->ecc.mode == NAND_ECC_HW) { | 1468 | if (this->ecc.mode == NAND_ECC_HW) { |
1229 | if (nfc_is_v1()) | 1469 | if (nfc_is_v1()) |
@@ -1232,9 +1472,19 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1232 | this->ecc.strength = (host->eccsize == 4) ? 4 : 8; | 1472 | this->ecc.strength = (host->eccsize == 4) ? 4 : 8; |
1233 | } | 1473 | } |
1234 | 1474 | ||
1475 | /* second phase scan */ | ||
1476 | if (nand_scan_tail(mtd)) { | ||
1477 | err = -ENXIO; | ||
1478 | goto escan; | ||
1479 | } | ||
1480 | |||
1235 | /* Register the partitions */ | 1481 | /* Register the partitions */ |
1236 | mtd_device_parse_register(mtd, part_probes, NULL, pdata->parts, | 1482 | mtd_device_parse_register(mtd, part_probes, |
1237 | pdata->nr_parts); | 1483 | &(struct mtd_part_parser_data){ |
1484 | .of_node = pdev->dev.of_node, | ||
1485 | }, | ||
1486 | host->pdata.parts, | ||
1487 | host->pdata.nr_parts); | ||
1238 | 1488 | ||
1239 | platform_set_drvdata(pdev, host); | 1489 | platform_set_drvdata(pdev, host); |
1240 | 1490 | ||
@@ -1275,6 +1525,8 @@ static int __devexit mxcnd_remove(struct platform_device *pdev) | |||
1275 | static struct platform_driver mxcnd_driver = { | 1525 | static struct platform_driver mxcnd_driver = { |
1276 | .driver = { | 1526 | .driver = { |
1277 | .name = DRIVER_NAME, | 1527 | .name = DRIVER_NAME, |
1528 | .owner = THIS_MODULE, | ||
1529 | .of_match_table = of_match_ptr(mxcnd_dt_ids), | ||
1278 | }, | 1530 | }, |
1279 | .remove = __devexit_p(mxcnd_remove), | 1531 | .remove = __devexit_p(mxcnd_remove), |
1280 | }; | 1532 | }; |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 47b19c0bb070..d47586cf64ce 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -1066,15 +1066,17 @@ EXPORT_SYMBOL(nand_lock); | |||
1066 | * @mtd: mtd info structure | 1066 | * @mtd: mtd info structure |
1067 | * @chip: nand chip info structure | 1067 | * @chip: nand chip info structure |
1068 | * @buf: buffer to store read data | 1068 | * @buf: buffer to store read data |
1069 | * @oob_required: caller requires OOB data read to chip->oob_poi | ||
1069 | * @page: page number to read | 1070 | * @page: page number to read |
1070 | * | 1071 | * |
1071 | * Not for syndrome calculating ECC controllers, which use a special oob layout. | 1072 | * Not for syndrome calculating ECC controllers, which use a special oob layout. |
1072 | */ | 1073 | */ |
1073 | static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | 1074 | static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, |
1074 | uint8_t *buf, int page) | 1075 | uint8_t *buf, int oob_required, int page) |
1075 | { | 1076 | { |
1076 | chip->read_buf(mtd, buf, mtd->writesize); | 1077 | chip->read_buf(mtd, buf, mtd->writesize); |
1077 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | 1078 | if (oob_required) |
1079 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
1078 | return 0; | 1080 | return 0; |
1079 | } | 1081 | } |
1080 | 1082 | ||
@@ -1083,13 +1085,14 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | |||
1083 | * @mtd: mtd info structure | 1085 | * @mtd: mtd info structure |
1084 | * @chip: nand chip info structure | 1086 | * @chip: nand chip info structure |
1085 | * @buf: buffer to store read data | 1087 | * @buf: buffer to store read data |
1088 | * @oob_required: caller requires OOB data read to chip->oob_poi | ||
1086 | * @page: page number to read | 1089 | * @page: page number to read |
1087 | * | 1090 | * |
1088 | * We need a special oob layout and handling even when OOB isn't used. | 1091 | * We need a special oob layout and handling even when OOB isn't used. |
1089 | */ | 1092 | */ |
1090 | static int nand_read_page_raw_syndrome(struct mtd_info *mtd, | 1093 | static int nand_read_page_raw_syndrome(struct mtd_info *mtd, |
1091 | struct nand_chip *chip, | 1094 | struct nand_chip *chip, uint8_t *buf, |
1092 | uint8_t *buf, int page) | 1095 | int oob_required, int page) |
1093 | { | 1096 | { |
1094 | int eccsize = chip->ecc.size; | 1097 | int eccsize = chip->ecc.size; |
1095 | int eccbytes = chip->ecc.bytes; | 1098 | int eccbytes = chip->ecc.bytes; |
@@ -1126,10 +1129,11 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd, | |||
1126 | * @mtd: mtd info structure | 1129 | * @mtd: mtd info structure |
1127 | * @chip: nand chip info structure | 1130 | * @chip: nand chip info structure |
1128 | * @buf: buffer to store read data | 1131 | * @buf: buffer to store read data |
1132 | * @oob_required: caller requires OOB data read to chip->oob_poi | ||
1129 | * @page: page number to read | 1133 | * @page: page number to read |
1130 | */ | 1134 | */ |
1131 | static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | 1135 | static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, |
1132 | uint8_t *buf, int page) | 1136 | uint8_t *buf, int oob_required, int page) |
1133 | { | 1137 | { |
1134 | int i, eccsize = chip->ecc.size; | 1138 | int i, eccsize = chip->ecc.size; |
1135 | int eccbytes = chip->ecc.bytes; | 1139 | int eccbytes = chip->ecc.bytes; |
@@ -1138,8 +1142,9 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1138 | uint8_t *ecc_calc = chip->buffers->ecccalc; | 1142 | uint8_t *ecc_calc = chip->buffers->ecccalc; |
1139 | uint8_t *ecc_code = chip->buffers->ecccode; | 1143 | uint8_t *ecc_code = chip->buffers->ecccode; |
1140 | uint32_t *eccpos = chip->ecc.layout->eccpos; | 1144 | uint32_t *eccpos = chip->ecc.layout->eccpos; |
1145 | unsigned int max_bitflips = 0; | ||
1141 | 1146 | ||
1142 | chip->ecc.read_page_raw(mtd, chip, buf, page); | 1147 | chip->ecc.read_page_raw(mtd, chip, buf, 1, page); |
1143 | 1148 | ||
1144 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) | 1149 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) |
1145 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); | 1150 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); |
@@ -1154,12 +1159,14 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1154 | int stat; | 1159 | int stat; |
1155 | 1160 | ||
1156 | stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); | 1161 | stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); |
1157 | if (stat < 0) | 1162 | if (stat < 0) { |
1158 | mtd->ecc_stats.failed++; | 1163 | mtd->ecc_stats.failed++; |
1159 | else | 1164 | } else { |
1160 | mtd->ecc_stats.corrected += stat; | 1165 | mtd->ecc_stats.corrected += stat; |
1166 | max_bitflips = max_t(unsigned int, max_bitflips, stat); | ||
1167 | } | ||
1161 | } | 1168 | } |
1162 | return 0; | 1169 | return max_bitflips; |
1163 | } | 1170 | } |
1164 | 1171 | ||
1165 | /** | 1172 | /** |
@@ -1180,6 +1187,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
1180 | int datafrag_len, eccfrag_len, aligned_len, aligned_pos; | 1187 | int datafrag_len, eccfrag_len, aligned_len, aligned_pos; |
1181 | int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; | 1188 | int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; |
1182 | int index = 0; | 1189 | int index = 0; |
1190 | unsigned int max_bitflips = 0; | ||
1183 | 1191 | ||
1184 | /* Column address within the page aligned to ECC size (256bytes) */ | 1192 | /* Column address within the page aligned to ECC size (256bytes) */ |
1185 | start_step = data_offs / chip->ecc.size; | 1193 | start_step = data_offs / chip->ecc.size; |
@@ -1244,12 +1252,14 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
1244 | 1252 | ||
1245 | stat = chip->ecc.correct(mtd, p, | 1253 | stat = chip->ecc.correct(mtd, p, |
1246 | &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]); | 1254 | &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]); |
1247 | if (stat < 0) | 1255 | if (stat < 0) { |
1248 | mtd->ecc_stats.failed++; | 1256 | mtd->ecc_stats.failed++; |
1249 | else | 1257 | } else { |
1250 | mtd->ecc_stats.corrected += stat; | 1258 | mtd->ecc_stats.corrected += stat; |
1259 | max_bitflips = max_t(unsigned int, max_bitflips, stat); | ||
1260 | } | ||
1251 | } | 1261 | } |
1252 | return 0; | 1262 | return max_bitflips; |
1253 | } | 1263 | } |
1254 | 1264 | ||
1255 | /** | 1265 | /** |
@@ -1257,12 +1267,13 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
1257 | * @mtd: mtd info structure | 1267 | * @mtd: mtd info structure |
1258 | * @chip: nand chip info structure | 1268 | * @chip: nand chip info structure |
1259 | * @buf: buffer to store read data | 1269 | * @buf: buffer to store read data |
1270 | * @oob_required: caller requires OOB data read to chip->oob_poi | ||
1260 | * @page: page number to read | 1271 | * @page: page number to read |
1261 | * | 1272 | * |
1262 | * Not for syndrome calculating ECC controllers which need a special oob layout. | 1273 | * Not for syndrome calculating ECC controllers which need a special oob layout. |
1263 | */ | 1274 | */ |
1264 | static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | 1275 | static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, |
1265 | uint8_t *buf, int page) | 1276 | uint8_t *buf, int oob_required, int page) |
1266 | { | 1277 | { |
1267 | int i, eccsize = chip->ecc.size; | 1278 | int i, eccsize = chip->ecc.size; |
1268 | int eccbytes = chip->ecc.bytes; | 1279 | int eccbytes = chip->ecc.bytes; |
@@ -1271,6 +1282,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1271 | uint8_t *ecc_calc = chip->buffers->ecccalc; | 1282 | uint8_t *ecc_calc = chip->buffers->ecccalc; |
1272 | uint8_t *ecc_code = chip->buffers->ecccode; | 1283 | uint8_t *ecc_code = chip->buffers->ecccode; |
1273 | uint32_t *eccpos = chip->ecc.layout->eccpos; | 1284 | uint32_t *eccpos = chip->ecc.layout->eccpos; |
1285 | unsigned int max_bitflips = 0; | ||
1274 | 1286 | ||
1275 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { | 1287 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { |
1276 | chip->ecc.hwctl(mtd, NAND_ECC_READ); | 1288 | chip->ecc.hwctl(mtd, NAND_ECC_READ); |
@@ -1289,12 +1301,14 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1289 | int stat; | 1301 | int stat; |
1290 | 1302 | ||
1291 | stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); | 1303 | stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); |
1292 | if (stat < 0) | 1304 | if (stat < 0) { |
1293 | mtd->ecc_stats.failed++; | 1305 | mtd->ecc_stats.failed++; |
1294 | else | 1306 | } else { |
1295 | mtd->ecc_stats.corrected += stat; | 1307 | mtd->ecc_stats.corrected += stat; |
1308 | max_bitflips = max_t(unsigned int, max_bitflips, stat); | ||
1309 | } | ||
1296 | } | 1310 | } |
1297 | return 0; | 1311 | return max_bitflips; |
1298 | } | 1312 | } |
1299 | 1313 | ||
1300 | /** | 1314 | /** |
@@ -1302,6 +1316,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1302 | * @mtd: mtd info structure | 1316 | * @mtd: mtd info structure |
1303 | * @chip: nand chip info structure | 1317 | * @chip: nand chip info structure |
1304 | * @buf: buffer to store read data | 1318 | * @buf: buffer to store read data |
1319 | * @oob_required: caller requires OOB data read to chip->oob_poi | ||
1305 | * @page: page number to read | 1320 | * @page: page number to read |
1306 | * | 1321 | * |
1307 | * Hardware ECC for large page chips, require OOB to be read first. For this | 1322 | * Hardware ECC for large page chips, require OOB to be read first. For this |
@@ -1311,7 +1326,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1311 | * the data area, by overwriting the NAND manufacturer bad block markings. | 1326 | * the data area, by overwriting the NAND manufacturer bad block markings. |
1312 | */ | 1327 | */ |
1313 | static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, | 1328 | static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, |
1314 | struct nand_chip *chip, uint8_t *buf, int page) | 1329 | struct nand_chip *chip, uint8_t *buf, int oob_required, int page) |
1315 | { | 1330 | { |
1316 | int i, eccsize = chip->ecc.size; | 1331 | int i, eccsize = chip->ecc.size; |
1317 | int eccbytes = chip->ecc.bytes; | 1332 | int eccbytes = chip->ecc.bytes; |
@@ -1320,6 +1335,7 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, | |||
1320 | uint8_t *ecc_code = chip->buffers->ecccode; | 1335 | uint8_t *ecc_code = chip->buffers->ecccode; |
1321 | uint32_t *eccpos = chip->ecc.layout->eccpos; | 1336 | uint32_t *eccpos = chip->ecc.layout->eccpos; |
1322 | uint8_t *ecc_calc = chip->buffers->ecccalc; | 1337 | uint8_t *ecc_calc = chip->buffers->ecccalc; |
1338 | unsigned int max_bitflips = 0; | ||
1323 | 1339 | ||
1324 | /* Read the OOB area first */ | 1340 | /* Read the OOB area first */ |
1325 | chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); | 1341 | chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); |
@@ -1337,12 +1353,14 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, | |||
1337 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); | 1353 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); |
1338 | 1354 | ||
1339 | stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL); | 1355 | stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL); |
1340 | if (stat < 0) | 1356 | if (stat < 0) { |
1341 | mtd->ecc_stats.failed++; | 1357 | mtd->ecc_stats.failed++; |
1342 | else | 1358 | } else { |
1343 | mtd->ecc_stats.corrected += stat; | 1359 | mtd->ecc_stats.corrected += stat; |
1360 | max_bitflips = max_t(unsigned int, max_bitflips, stat); | ||
1361 | } | ||
1344 | } | 1362 | } |
1345 | return 0; | 1363 | return max_bitflips; |
1346 | } | 1364 | } |
1347 | 1365 | ||
1348 | /** | 1366 | /** |
@@ -1350,19 +1368,21 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, | |||
1350 | * @mtd: mtd info structure | 1368 | * @mtd: mtd info structure |
1351 | * @chip: nand chip info structure | 1369 | * @chip: nand chip info structure |
1352 | * @buf: buffer to store read data | 1370 | * @buf: buffer to store read data |
1371 | * @oob_required: caller requires OOB data read to chip->oob_poi | ||
1353 | * @page: page number to read | 1372 | * @page: page number to read |
1354 | * | 1373 | * |
1355 | * The hw generator calculates the error syndrome automatically. Therefore we | 1374 | * The hw generator calculates the error syndrome automatically. Therefore we |
1356 | * need a special oob layout and handling. | 1375 | * need a special oob layout and handling. |
1357 | */ | 1376 | */ |
1358 | static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | 1377 | static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, |
1359 | uint8_t *buf, int page) | 1378 | uint8_t *buf, int oob_required, int page) |
1360 | { | 1379 | { |
1361 | int i, eccsize = chip->ecc.size; | 1380 | int i, eccsize = chip->ecc.size; |
1362 | int eccbytes = chip->ecc.bytes; | 1381 | int eccbytes = chip->ecc.bytes; |
1363 | int eccsteps = chip->ecc.steps; | 1382 | int eccsteps = chip->ecc.steps; |
1364 | uint8_t *p = buf; | 1383 | uint8_t *p = buf; |
1365 | uint8_t *oob = chip->oob_poi; | 1384 | uint8_t *oob = chip->oob_poi; |
1385 | unsigned int max_bitflips = 0; | ||
1366 | 1386 | ||
1367 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { | 1387 | for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { |
1368 | int stat; | 1388 | int stat; |
@@ -1379,10 +1399,12 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | |||
1379 | chip->read_buf(mtd, oob, eccbytes); | 1399 | chip->read_buf(mtd, oob, eccbytes); |
1380 | stat = chip->ecc.correct(mtd, p, oob, NULL); | 1400 | stat = chip->ecc.correct(mtd, p, oob, NULL); |
1381 | 1401 | ||
1382 | if (stat < 0) | 1402 | if (stat < 0) { |
1383 | mtd->ecc_stats.failed++; | 1403 | mtd->ecc_stats.failed++; |
1384 | else | 1404 | } else { |
1385 | mtd->ecc_stats.corrected += stat; | 1405 | mtd->ecc_stats.corrected += stat; |
1406 | max_bitflips = max_t(unsigned int, max_bitflips, stat); | ||
1407 | } | ||
1386 | 1408 | ||
1387 | oob += eccbytes; | 1409 | oob += eccbytes; |
1388 | 1410 | ||
@@ -1397,7 +1419,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | |||
1397 | if (i) | 1419 | if (i) |
1398 | chip->read_buf(mtd, oob, i); | 1420 | chip->read_buf(mtd, oob, i); |
1399 | 1421 | ||
1400 | return 0; | 1422 | return max_bitflips; |
1401 | } | 1423 | } |
1402 | 1424 | ||
1403 | /** | 1425 | /** |
@@ -1459,11 +1481,9 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, | |||
1459 | static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | 1481 | static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, |
1460 | struct mtd_oob_ops *ops) | 1482 | struct mtd_oob_ops *ops) |
1461 | { | 1483 | { |
1462 | int chipnr, page, realpage, col, bytes, aligned; | 1484 | int chipnr, page, realpage, col, bytes, aligned, oob_required; |
1463 | struct nand_chip *chip = mtd->priv; | 1485 | struct nand_chip *chip = mtd->priv; |
1464 | struct mtd_ecc_stats stats; | 1486 | struct mtd_ecc_stats stats; |
1465 | int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; | ||
1466 | int sndcmd = 1; | ||
1467 | int ret = 0; | 1487 | int ret = 0; |
1468 | uint32_t readlen = ops->len; | 1488 | uint32_t readlen = ops->len; |
1469 | uint32_t oobreadlen = ops->ooblen; | 1489 | uint32_t oobreadlen = ops->ooblen; |
@@ -1471,6 +1491,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1471 | mtd->oobavail : mtd->oobsize; | 1491 | mtd->oobavail : mtd->oobsize; |
1472 | 1492 | ||
1473 | uint8_t *bufpoi, *oob, *buf; | 1493 | uint8_t *bufpoi, *oob, *buf; |
1494 | unsigned int max_bitflips = 0; | ||
1474 | 1495 | ||
1475 | stats = mtd->ecc_stats; | 1496 | stats = mtd->ecc_stats; |
1476 | 1497 | ||
@@ -1484,6 +1505,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1484 | 1505 | ||
1485 | buf = ops->datbuf; | 1506 | buf = ops->datbuf; |
1486 | oob = ops->oobbuf; | 1507 | oob = ops->oobbuf; |
1508 | oob_required = oob ? 1 : 0; | ||
1487 | 1509 | ||
1488 | while (1) { | 1510 | while (1) { |
1489 | bytes = min(mtd->writesize - col, readlen); | 1511 | bytes = min(mtd->writesize - col, readlen); |
@@ -1493,21 +1515,22 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1493 | if (realpage != chip->pagebuf || oob) { | 1515 | if (realpage != chip->pagebuf || oob) { |
1494 | bufpoi = aligned ? buf : chip->buffers->databuf; | 1516 | bufpoi = aligned ? buf : chip->buffers->databuf; |
1495 | 1517 | ||
1496 | if (likely(sndcmd)) { | 1518 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); |
1497 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); | ||
1498 | sndcmd = 0; | ||
1499 | } | ||
1500 | 1519 | ||
1501 | /* Now read the page into the buffer */ | 1520 | /* |
1521 | * Now read the page into the buffer. Absent an error, | ||
1522 | * the read methods return max bitflips per ecc step. | ||
1523 | */ | ||
1502 | if (unlikely(ops->mode == MTD_OPS_RAW)) | 1524 | if (unlikely(ops->mode == MTD_OPS_RAW)) |
1503 | ret = chip->ecc.read_page_raw(mtd, chip, | 1525 | ret = chip->ecc.read_page_raw(mtd, chip, bufpoi, |
1504 | bufpoi, page); | 1526 | oob_required, |
1527 | page); | ||
1505 | else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob) | 1528 | else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob) |
1506 | ret = chip->ecc.read_subpage(mtd, chip, | 1529 | ret = chip->ecc.read_subpage(mtd, chip, |
1507 | col, bytes, bufpoi); | 1530 | col, bytes, bufpoi); |
1508 | else | 1531 | else |
1509 | ret = chip->ecc.read_page(mtd, chip, bufpoi, | 1532 | ret = chip->ecc.read_page(mtd, chip, bufpoi, |
1510 | page); | 1533 | oob_required, page); |
1511 | if (ret < 0) { | 1534 | if (ret < 0) { |
1512 | if (!aligned) | 1535 | if (!aligned) |
1513 | /* Invalidate page cache */ | 1536 | /* Invalidate page cache */ |
@@ -1515,22 +1538,25 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1515 | break; | 1538 | break; |
1516 | } | 1539 | } |
1517 | 1540 | ||
1541 | max_bitflips = max_t(unsigned int, max_bitflips, ret); | ||
1542 | |||
1518 | /* Transfer not aligned data */ | 1543 | /* Transfer not aligned data */ |
1519 | if (!aligned) { | 1544 | if (!aligned) { |
1520 | if (!NAND_SUBPAGE_READ(chip) && !oob && | 1545 | if (!NAND_SUBPAGE_READ(chip) && !oob && |
1521 | !(mtd->ecc_stats.failed - stats.failed) && | 1546 | !(mtd->ecc_stats.failed - stats.failed) && |
1522 | (ops->mode != MTD_OPS_RAW)) | 1547 | (ops->mode != MTD_OPS_RAW)) { |
1523 | chip->pagebuf = realpage; | 1548 | chip->pagebuf = realpage; |
1524 | else | 1549 | chip->pagebuf_bitflips = ret; |
1550 | } else { | ||
1525 | /* Invalidate page cache */ | 1551 | /* Invalidate page cache */ |
1526 | chip->pagebuf = -1; | 1552 | chip->pagebuf = -1; |
1553 | } | ||
1527 | memcpy(buf, chip->buffers->databuf + col, bytes); | 1554 | memcpy(buf, chip->buffers->databuf + col, bytes); |
1528 | } | 1555 | } |
1529 | 1556 | ||
1530 | buf += bytes; | 1557 | buf += bytes; |
1531 | 1558 | ||
1532 | if (unlikely(oob)) { | 1559 | if (unlikely(oob)) { |
1533 | |||
1534 | int toread = min(oobreadlen, max_oobsize); | 1560 | int toread = min(oobreadlen, max_oobsize); |
1535 | 1561 | ||
1536 | if (toread) { | 1562 | if (toread) { |
@@ -1541,13 +1567,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1541 | } | 1567 | } |
1542 | 1568 | ||
1543 | if (!(chip->options & NAND_NO_READRDY)) { | 1569 | if (!(chip->options & NAND_NO_READRDY)) { |
1544 | /* | 1570 | /* Apply delay or wait for ready/busy pin */ |
1545 | * Apply delay or wait for ready/busy pin. Do | ||
1546 | * this before the AUTOINCR check, so no | ||
1547 | * problems arise if a chip which does auto | ||
1548 | * increment is marked as NOAUTOINCR by the | ||
1549 | * board driver. | ||
1550 | */ | ||
1551 | if (!chip->dev_ready) | 1571 | if (!chip->dev_ready) |
1552 | udelay(chip->chip_delay); | 1572 | udelay(chip->chip_delay); |
1553 | else | 1573 | else |
@@ -1556,6 +1576,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1556 | } else { | 1576 | } else { |
1557 | memcpy(buf, chip->buffers->databuf + col, bytes); | 1577 | memcpy(buf, chip->buffers->databuf + col, bytes); |
1558 | buf += bytes; | 1578 | buf += bytes; |
1579 | max_bitflips = max_t(unsigned int, max_bitflips, | ||
1580 | chip->pagebuf_bitflips); | ||
1559 | } | 1581 | } |
1560 | 1582 | ||
1561 | readlen -= bytes; | 1583 | readlen -= bytes; |
@@ -1575,26 +1597,19 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1575 | chip->select_chip(mtd, -1); | 1597 | chip->select_chip(mtd, -1); |
1576 | chip->select_chip(mtd, chipnr); | 1598 | chip->select_chip(mtd, chipnr); |
1577 | } | 1599 | } |
1578 | |||
1579 | /* | ||
1580 | * Check, if the chip supports auto page increment or if we | ||
1581 | * have hit a block boundary. | ||
1582 | */ | ||
1583 | if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck)) | ||
1584 | sndcmd = 1; | ||
1585 | } | 1600 | } |
1586 | 1601 | ||
1587 | ops->retlen = ops->len - (size_t) readlen; | 1602 | ops->retlen = ops->len - (size_t) readlen; |
1588 | if (oob) | 1603 | if (oob) |
1589 | ops->oobretlen = ops->ooblen - oobreadlen; | 1604 | ops->oobretlen = ops->ooblen - oobreadlen; |
1590 | 1605 | ||
1591 | if (ret) | 1606 | if (ret < 0) |
1592 | return ret; | 1607 | return ret; |
1593 | 1608 | ||
1594 | if (mtd->ecc_stats.failed - stats.failed) | 1609 | if (mtd->ecc_stats.failed - stats.failed) |
1595 | return -EBADMSG; | 1610 | return -EBADMSG; |
1596 | 1611 | ||
1597 | return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; | 1612 | return max_bitflips; |
1598 | } | 1613 | } |
1599 | 1614 | ||
1600 | /** | 1615 | /** |
@@ -1630,17 +1645,13 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
1630 | * @mtd: mtd info structure | 1645 | * @mtd: mtd info structure |
1631 | * @chip: nand chip info structure | 1646 | * @chip: nand chip info structure |
1632 | * @page: page number to read | 1647 | * @page: page number to read |
1633 | * @sndcmd: flag whether to issue read command or not | ||
1634 | */ | 1648 | */ |
1635 | static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, | 1649 | static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, |
1636 | int page, int sndcmd) | 1650 | int page) |
1637 | { | 1651 | { |
1638 | if (sndcmd) { | 1652 | chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); |
1639 | chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); | ||
1640 | sndcmd = 0; | ||
1641 | } | ||
1642 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | 1653 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |
1643 | return sndcmd; | 1654 | return 0; |
1644 | } | 1655 | } |
1645 | 1656 | ||
1646 | /** | 1657 | /** |
@@ -1649,10 +1660,9 @@ static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, | |||
1649 | * @mtd: mtd info structure | 1660 | * @mtd: mtd info structure |
1650 | * @chip: nand chip info structure | 1661 | * @chip: nand chip info structure |
1651 | * @page: page number to read | 1662 | * @page: page number to read |
1652 | * @sndcmd: flag whether to issue read command or not | ||
1653 | */ | 1663 | */ |
1654 | static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | 1664 | static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, |
1655 | int page, int sndcmd) | 1665 | int page) |
1656 | { | 1666 | { |
1657 | uint8_t *buf = chip->oob_poi; | 1667 | uint8_t *buf = chip->oob_poi; |
1658 | int length = mtd->oobsize; | 1668 | int length = mtd->oobsize; |
@@ -1679,7 +1689,7 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | |||
1679 | if (length > 0) | 1689 | if (length > 0) |
1680 | chip->read_buf(mtd, bufpoi, length); | 1690 | chip->read_buf(mtd, bufpoi, length); |
1681 | 1691 | ||
1682 | return 1; | 1692 | return 0; |
1683 | } | 1693 | } |
1684 | 1694 | ||
1685 | /** | 1695 | /** |
@@ -1775,13 +1785,13 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd, | |||
1775 | static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, | 1785 | static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, |
1776 | struct mtd_oob_ops *ops) | 1786 | struct mtd_oob_ops *ops) |
1777 | { | 1787 | { |
1778 | int page, realpage, chipnr, sndcmd = 1; | 1788 | int page, realpage, chipnr; |
1779 | struct nand_chip *chip = mtd->priv; | 1789 | struct nand_chip *chip = mtd->priv; |
1780 | struct mtd_ecc_stats stats; | 1790 | struct mtd_ecc_stats stats; |
1781 | int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; | ||
1782 | int readlen = ops->ooblen; | 1791 | int readlen = ops->ooblen; |
1783 | int len; | 1792 | int len; |
1784 | uint8_t *buf = ops->oobbuf; | 1793 | uint8_t *buf = ops->oobbuf; |
1794 | int ret = 0; | ||
1785 | 1795 | ||
1786 | pr_debug("%s: from = 0x%08Lx, len = %i\n", | 1796 | pr_debug("%s: from = 0x%08Lx, len = %i\n", |
1787 | __func__, (unsigned long long)from, readlen); | 1797 | __func__, (unsigned long long)from, readlen); |
@@ -1817,20 +1827,18 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, | |||
1817 | 1827 | ||
1818 | while (1) { | 1828 | while (1) { |
1819 | if (ops->mode == MTD_OPS_RAW) | 1829 | if (ops->mode == MTD_OPS_RAW) |
1820 | sndcmd = chip->ecc.read_oob_raw(mtd, chip, page, sndcmd); | 1830 | ret = chip->ecc.read_oob_raw(mtd, chip, page); |
1821 | else | 1831 | else |
1822 | sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); | 1832 | ret = chip->ecc.read_oob(mtd, chip, page); |
1833 | |||
1834 | if (ret < 0) | ||
1835 | break; | ||
1823 | 1836 | ||
1824 | len = min(len, readlen); | 1837 | len = min(len, readlen); |
1825 | buf = nand_transfer_oob(chip, buf, ops, len); | 1838 | buf = nand_transfer_oob(chip, buf, ops, len); |
1826 | 1839 | ||
1827 | if (!(chip->options & NAND_NO_READRDY)) { | 1840 | if (!(chip->options & NAND_NO_READRDY)) { |
1828 | /* | 1841 | /* Apply delay or wait for ready/busy pin */ |
1829 | * Apply delay or wait for ready/busy pin. Do this | ||
1830 | * before the AUTOINCR check, so no problems arise if a | ||
1831 | * chip which does auto increment is marked as | ||
1832 | * NOAUTOINCR by the board driver. | ||
1833 | */ | ||
1834 | if (!chip->dev_ready) | 1842 | if (!chip->dev_ready) |
1835 | udelay(chip->chip_delay); | 1843 | udelay(chip->chip_delay); |
1836 | else | 1844 | else |
@@ -1851,16 +1859,12 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, | |||
1851 | chip->select_chip(mtd, -1); | 1859 | chip->select_chip(mtd, -1); |
1852 | chip->select_chip(mtd, chipnr); | 1860 | chip->select_chip(mtd, chipnr); |
1853 | } | 1861 | } |
1854 | |||
1855 | /* | ||
1856 | * Check, if the chip supports auto page increment or if we | ||
1857 | * have hit a block boundary. | ||
1858 | */ | ||
1859 | if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck)) | ||
1860 | sndcmd = 1; | ||
1861 | } | 1862 | } |
1862 | 1863 | ||
1863 | ops->oobretlen = ops->ooblen; | 1864 | ops->oobretlen = ops->ooblen - readlen; |
1865 | |||
1866 | if (ret < 0) | ||
1867 | return ret; | ||
1864 | 1868 | ||
1865 | if (mtd->ecc_stats.failed - stats.failed) | 1869 | if (mtd->ecc_stats.failed - stats.failed) |
1866 | return -EBADMSG; | 1870 | return -EBADMSG; |
@@ -1919,14 +1923,16 @@ out: | |||
1919 | * @mtd: mtd info structure | 1923 | * @mtd: mtd info structure |
1920 | * @chip: nand chip info structure | 1924 | * @chip: nand chip info structure |
1921 | * @buf: data buffer | 1925 | * @buf: data buffer |
1926 | * @oob_required: must write chip->oob_poi to OOB | ||
1922 | * | 1927 | * |
1923 | * Not for syndrome calculating ECC controllers, which use a special oob layout. | 1928 | * Not for syndrome calculating ECC controllers, which use a special oob layout. |
1924 | */ | 1929 | */ |
1925 | static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | 1930 | static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, |
1926 | const uint8_t *buf) | 1931 | const uint8_t *buf, int oob_required) |
1927 | { | 1932 | { |
1928 | chip->write_buf(mtd, buf, mtd->writesize); | 1933 | chip->write_buf(mtd, buf, mtd->writesize); |
1929 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); | 1934 | if (oob_required) |
1935 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
1930 | } | 1936 | } |
1931 | 1937 | ||
1932 | /** | 1938 | /** |
@@ -1934,12 +1940,13 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | |||
1934 | * @mtd: mtd info structure | 1940 | * @mtd: mtd info structure |
1935 | * @chip: nand chip info structure | 1941 | * @chip: nand chip info structure |
1936 | * @buf: data buffer | 1942 | * @buf: data buffer |
1943 | * @oob_required: must write chip->oob_poi to OOB | ||
1937 | * | 1944 | * |
1938 | * We need a special oob layout and handling even when ECC isn't checked. | 1945 | * We need a special oob layout and handling even when ECC isn't checked. |
1939 | */ | 1946 | */ |
1940 | static void nand_write_page_raw_syndrome(struct mtd_info *mtd, | 1947 | static void nand_write_page_raw_syndrome(struct mtd_info *mtd, |
1941 | struct nand_chip *chip, | 1948 | struct nand_chip *chip, |
1942 | const uint8_t *buf) | 1949 | const uint8_t *buf, int oob_required) |
1943 | { | 1950 | { |
1944 | int eccsize = chip->ecc.size; | 1951 | int eccsize = chip->ecc.size; |
1945 | int eccbytes = chip->ecc.bytes; | 1952 | int eccbytes = chip->ecc.bytes; |
@@ -1973,9 +1980,10 @@ static void nand_write_page_raw_syndrome(struct mtd_info *mtd, | |||
1973 | * @mtd: mtd info structure | 1980 | * @mtd: mtd info structure |
1974 | * @chip: nand chip info structure | 1981 | * @chip: nand chip info structure |
1975 | * @buf: data buffer | 1982 | * @buf: data buffer |
1983 | * @oob_required: must write chip->oob_poi to OOB | ||
1976 | */ | 1984 | */ |
1977 | static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | 1985 | static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, |
1978 | const uint8_t *buf) | 1986 | const uint8_t *buf, int oob_required) |
1979 | { | 1987 | { |
1980 | int i, eccsize = chip->ecc.size; | 1988 | int i, eccsize = chip->ecc.size; |
1981 | int eccbytes = chip->ecc.bytes; | 1989 | int eccbytes = chip->ecc.bytes; |
@@ -1991,7 +1999,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1991 | for (i = 0; i < chip->ecc.total; i++) | 1999 | for (i = 0; i < chip->ecc.total; i++) |
1992 | chip->oob_poi[eccpos[i]] = ecc_calc[i]; | 2000 | chip->oob_poi[eccpos[i]] = ecc_calc[i]; |
1993 | 2001 | ||
1994 | chip->ecc.write_page_raw(mtd, chip, buf); | 2002 | chip->ecc.write_page_raw(mtd, chip, buf, 1); |
1995 | } | 2003 | } |
1996 | 2004 | ||
1997 | /** | 2005 | /** |
@@ -1999,9 +2007,10 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1999 | * @mtd: mtd info structure | 2007 | * @mtd: mtd info structure |
2000 | * @chip: nand chip info structure | 2008 | * @chip: nand chip info structure |
2001 | * @buf: data buffer | 2009 | * @buf: data buffer |
2010 | * @oob_required: must write chip->oob_poi to OOB | ||
2002 | */ | 2011 | */ |
2003 | static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | 2012 | static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, |
2004 | const uint8_t *buf) | 2013 | const uint8_t *buf, int oob_required) |
2005 | { | 2014 | { |
2006 | int i, eccsize = chip->ecc.size; | 2015 | int i, eccsize = chip->ecc.size; |
2007 | int eccbytes = chip->ecc.bytes; | 2016 | int eccbytes = chip->ecc.bytes; |
@@ -2027,12 +2036,14 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
2027 | * @mtd: mtd info structure | 2036 | * @mtd: mtd info structure |
2028 | * @chip: nand chip info structure | 2037 | * @chip: nand chip info structure |
2029 | * @buf: data buffer | 2038 | * @buf: data buffer |
2039 | * @oob_required: must write chip->oob_poi to OOB | ||
2030 | * | 2040 | * |
2031 | * The hw generator calculates the error syndrome automatically. Therefore we | 2041 | * The hw generator calculates the error syndrome automatically. Therefore we |
2032 | * need a special oob layout and handling. | 2042 | * need a special oob layout and handling. |
2033 | */ | 2043 | */ |
2034 | static void nand_write_page_syndrome(struct mtd_info *mtd, | 2044 | static void nand_write_page_syndrome(struct mtd_info *mtd, |
2035 | struct nand_chip *chip, const uint8_t *buf) | 2045 | struct nand_chip *chip, |
2046 | const uint8_t *buf, int oob_required) | ||
2036 | { | 2047 | { |
2037 | int i, eccsize = chip->ecc.size; | 2048 | int i, eccsize = chip->ecc.size; |
2038 | int eccbytes = chip->ecc.bytes; | 2049 | int eccbytes = chip->ecc.bytes; |
@@ -2071,21 +2082,23 @@ static void nand_write_page_syndrome(struct mtd_info *mtd, | |||
2071 | * @mtd: MTD device structure | 2082 | * @mtd: MTD device structure |
2072 | * @chip: NAND chip descriptor | 2083 | * @chip: NAND chip descriptor |
2073 | * @buf: the data to write | 2084 | * @buf: the data to write |
2085 | * @oob_required: must write chip->oob_poi to OOB | ||
2074 | * @page: page number to write | 2086 | * @page: page number to write |
2075 | * @cached: cached programming | 2087 | * @cached: cached programming |
2076 | * @raw: use _raw version of write_page | 2088 | * @raw: use _raw version of write_page |
2077 | */ | 2089 | */ |
2078 | static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, | 2090 | static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, |
2079 | const uint8_t *buf, int page, int cached, int raw) | 2091 | const uint8_t *buf, int oob_required, int page, |
2092 | int cached, int raw) | ||
2080 | { | 2093 | { |
2081 | int status; | 2094 | int status; |
2082 | 2095 | ||
2083 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); | 2096 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); |
2084 | 2097 | ||
2085 | if (unlikely(raw)) | 2098 | if (unlikely(raw)) |
2086 | chip->ecc.write_page_raw(mtd, chip, buf); | 2099 | chip->ecc.write_page_raw(mtd, chip, buf, oob_required); |
2087 | else | 2100 | else |
2088 | chip->ecc.write_page(mtd, chip, buf); | 2101 | chip->ecc.write_page(mtd, chip, buf, oob_required); |
2089 | 2102 | ||
2090 | /* | 2103 | /* |
2091 | * Cached progamming disabled for now. Not sure if it's worth the | 2104 | * Cached progamming disabled for now. Not sure if it's worth the |
@@ -2118,6 +2131,9 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
2118 | 2131 | ||
2119 | if (chip->verify_buf(mtd, buf, mtd->writesize)) | 2132 | if (chip->verify_buf(mtd, buf, mtd->writesize)) |
2120 | return -EIO; | 2133 | return -EIO; |
2134 | |||
2135 | /* Make sure the next page prog is preceded by a status read */ | ||
2136 | chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); | ||
2121 | #endif | 2137 | #endif |
2122 | return 0; | 2138 | return 0; |
2123 | } | 2139 | } |
@@ -2202,6 +2218,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, | |||
2202 | uint8_t *oob = ops->oobbuf; | 2218 | uint8_t *oob = ops->oobbuf; |
2203 | uint8_t *buf = ops->datbuf; | 2219 | uint8_t *buf = ops->datbuf; |
2204 | int ret, subpage; | 2220 | int ret, subpage; |
2221 | int oob_required = oob ? 1 : 0; | ||
2205 | 2222 | ||
2206 | ops->retlen = 0; | 2223 | ops->retlen = 0; |
2207 | if (!writelen) | 2224 | if (!writelen) |
@@ -2264,8 +2281,8 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, | |||
2264 | memset(chip->oob_poi, 0xff, mtd->oobsize); | 2281 | memset(chip->oob_poi, 0xff, mtd->oobsize); |
2265 | } | 2282 | } |
2266 | 2283 | ||
2267 | ret = chip->write_page(mtd, chip, wbuf, page, cached, | 2284 | ret = chip->write_page(mtd, chip, wbuf, oob_required, page, |
2268 | (ops->mode == MTD_OPS_RAW)); | 2285 | cached, (ops->mode == MTD_OPS_RAW)); |
2269 | if (ret) | 2286 | if (ret) |
2270 | break; | 2287 | break; |
2271 | 2288 | ||
@@ -2898,8 +2915,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, | |||
2898 | *busw = NAND_BUSWIDTH_16; | 2915 | *busw = NAND_BUSWIDTH_16; |
2899 | 2916 | ||
2900 | chip->options &= ~NAND_CHIPOPTIONS_MSK; | 2917 | chip->options &= ~NAND_CHIPOPTIONS_MSK; |
2901 | chip->options |= (NAND_NO_READRDY | | 2918 | chip->options |= NAND_NO_READRDY & NAND_CHIPOPTIONS_MSK; |
2902 | NAND_NO_AUTOINCR) & NAND_CHIPOPTIONS_MSK; | ||
2903 | 2919 | ||
2904 | pr_info("ONFI flash detected\n"); | 2920 | pr_info("ONFI flash detected\n"); |
2905 | return 1; | 2921 | return 1; |
@@ -3076,11 +3092,6 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
3076 | chip->options &= ~NAND_SAMSUNG_LP_OPTIONS; | 3092 | chip->options &= ~NAND_SAMSUNG_LP_OPTIONS; |
3077 | ident_done: | 3093 | ident_done: |
3078 | 3094 | ||
3079 | /* | ||
3080 | * Set chip as a default. Board drivers can override it, if necessary. | ||
3081 | */ | ||
3082 | chip->options |= NAND_NO_AUTOINCR; | ||
3083 | |||
3084 | /* Try to identify manufacturer */ | 3095 | /* Try to identify manufacturer */ |
3085 | for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) { | 3096 | for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) { |
3086 | if (nand_manuf_ids[maf_idx].id == *maf_id) | 3097 | if (nand_manuf_ids[maf_idx].id == *maf_id) |
@@ -3154,10 +3165,11 @@ ident_done: | |||
3154 | if (mtd->writesize > 512 && chip->cmdfunc == nand_command) | 3165 | if (mtd->writesize > 512 && chip->cmdfunc == nand_command) |
3155 | chip->cmdfunc = nand_command_lp; | 3166 | chip->cmdfunc = nand_command_lp; |
3156 | 3167 | ||
3157 | pr_info("NAND device: Manufacturer ID:" | 3168 | pr_info("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s)," |
3158 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id, | 3169 | " page size: %d, OOB size: %d\n", |
3159 | nand_manuf_ids[maf_idx].name, | 3170 | *maf_id, *dev_id, nand_manuf_ids[maf_idx].name, |
3160 | chip->onfi_version ? chip->onfi_params.model : type->name); | 3171 | chip->onfi_version ? chip->onfi_params.model : type->name, |
3172 | mtd->writesize, mtd->oobsize); | ||
3161 | 3173 | ||
3162 | return type; | 3174 | return type; |
3163 | } | 3175 | } |
@@ -3329,8 +3341,13 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3329 | if (!chip->ecc.write_oob) | 3341 | if (!chip->ecc.write_oob) |
3330 | chip->ecc.write_oob = nand_write_oob_syndrome; | 3342 | chip->ecc.write_oob = nand_write_oob_syndrome; |
3331 | 3343 | ||
3332 | if (mtd->writesize >= chip->ecc.size) | 3344 | if (mtd->writesize >= chip->ecc.size) { |
3345 | if (!chip->ecc.strength) { | ||
3346 | pr_warn("Driver must set ecc.strength when using hardware ECC\n"); | ||
3347 | BUG(); | ||
3348 | } | ||
3333 | break; | 3349 | break; |
3350 | } | ||
3334 | pr_warn("%d byte HW ECC not possible on " | 3351 | pr_warn("%d byte HW ECC not possible on " |
3335 | "%d byte page size, fallback to SW ECC\n", | 3352 | "%d byte page size, fallback to SW ECC\n", |
3336 | chip->ecc.size, mtd->writesize); | 3353 | chip->ecc.size, mtd->writesize); |
@@ -3385,7 +3402,7 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3385 | BUG(); | 3402 | BUG(); |
3386 | } | 3403 | } |
3387 | chip->ecc.strength = | 3404 | chip->ecc.strength = |
3388 | chip->ecc.bytes*8 / fls(8*chip->ecc.size); | 3405 | chip->ecc.bytes * 8 / fls(8 * chip->ecc.size); |
3389 | break; | 3406 | break; |
3390 | 3407 | ||
3391 | case NAND_ECC_NONE: | 3408 | case NAND_ECC_NONE: |
@@ -3483,7 +3500,7 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3483 | 3500 | ||
3484 | /* propagate ecc info to mtd_info */ | 3501 | /* propagate ecc info to mtd_info */ |
3485 | mtd->ecclayout = chip->ecc.layout; | 3502 | mtd->ecclayout = chip->ecc.layout; |
3486 | mtd->ecc_strength = chip->ecc.strength * chip->ecc.steps; | 3503 | mtd->ecc_strength = chip->ecc.strength; |
3487 | 3504 | ||
3488 | /* Check, if we should skip the bad block table scan */ | 3505 | /* Check, if we should skip the bad block table scan */ |
3489 | if (chip->options & NAND_SKIP_BBTSCAN) | 3506 | if (chip->options & NAND_SKIP_BBTSCAN) |
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 20a112f591fe..30d1319ff065 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c | |||
@@ -324,6 +324,7 @@ static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs, | |||
324 | 324 | ||
325 | buf += mtd->oobsize + mtd->writesize; | 325 | buf += mtd->oobsize + mtd->writesize; |
326 | len -= mtd->writesize; | 326 | len -= mtd->writesize; |
327 | offs += mtd->writesize; | ||
327 | } | 328 | } |
328 | return 0; | 329 | return 0; |
329 | } | 330 | } |
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index af4fe8ca7b5e..621b70b7a159 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c | |||
@@ -70,7 +70,7 @@ struct nand_flash_dev nand_flash_ids[] = { | |||
70 | * These are the new chips with large page size. The pagesize and the | 70 | * These are the new chips with large page size. The pagesize and the |
71 | * erasesize is determined from the extended id bytes | 71 | * erasesize is determined from the extended id bytes |
72 | */ | 72 | */ |
73 | #define LP_OPTIONS (NAND_SAMSUNG_LP_OPTIONS | NAND_NO_READRDY | NAND_NO_AUTOINCR) | 73 | #define LP_OPTIONS (NAND_SAMSUNG_LP_OPTIONS | NAND_NO_READRDY) |
74 | #define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16) | 74 | #define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16) |
75 | 75 | ||
76 | /* 512 Megabit */ | 76 | /* 512 Megabit */ |
@@ -157,9 +157,7 @@ struct nand_flash_dev nand_flash_ids[] = { | |||
157 | * writes possible, but not implemented now | 157 | * writes possible, but not implemented now |
158 | */ | 158 | */ |
159 | {"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000, | 159 | {"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000, |
160 | NAND_IS_AND | NAND_NO_AUTOINCR |NAND_NO_READRDY | NAND_4PAGE_ARRAY | | 160 | NAND_IS_AND | NAND_NO_READRDY | NAND_4PAGE_ARRAY | BBT_AUTO_REFRESH}, |
161 | BBT_AUTO_REFRESH | ||
162 | }, | ||
163 | 161 | ||
164 | {NULL,} | 162 | {NULL,} |
165 | }; | 163 | }; |
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 261f478f8cc3..6cc8fbfabb8e 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c | |||
@@ -268,7 +268,6 @@ MODULE_PARM_DESC(bch, "Enable BCH ecc and set how many bits should " | |||
268 | #define OPT_PAGE512 0x00000002 /* 512-byte page chips */ | 268 | #define OPT_PAGE512 0x00000002 /* 512-byte page chips */ |
269 | #define OPT_PAGE2048 0x00000008 /* 2048-byte page chips */ | 269 | #define OPT_PAGE2048 0x00000008 /* 2048-byte page chips */ |
270 | #define OPT_SMARTMEDIA 0x00000010 /* SmartMedia technology chips */ | 270 | #define OPT_SMARTMEDIA 0x00000010 /* SmartMedia technology chips */ |
271 | #define OPT_AUTOINCR 0x00000020 /* page number auto incrementation is possible */ | ||
272 | #define OPT_PAGE512_8BIT 0x00000040 /* 512-byte page chips with 8-bit bus width */ | 271 | #define OPT_PAGE512_8BIT 0x00000040 /* 512-byte page chips with 8-bit bus width */ |
273 | #define OPT_PAGE4096 0x00000080 /* 4096-byte page chips */ | 272 | #define OPT_PAGE4096 0x00000080 /* 4096-byte page chips */ |
274 | #define OPT_LARGEPAGE (OPT_PAGE2048 | OPT_PAGE4096) /* 2048 & 4096-byte page chips */ | 273 | #define OPT_LARGEPAGE (OPT_PAGE2048 | OPT_PAGE4096) /* 2048 & 4096-byte page chips */ |
@@ -594,7 +593,7 @@ static int init_nandsim(struct mtd_info *mtd) | |||
594 | ns->options |= OPT_PAGE256; | 593 | ns->options |= OPT_PAGE256; |
595 | } | 594 | } |
596 | else if (ns->geom.pgsz == 512) { | 595 | else if (ns->geom.pgsz == 512) { |
597 | ns->options |= (OPT_PAGE512 | OPT_AUTOINCR); | 596 | ns->options |= OPT_PAGE512; |
598 | if (ns->busw == 8) | 597 | if (ns->busw == 8) |
599 | ns->options |= OPT_PAGE512_8BIT; | 598 | ns->options |= OPT_PAGE512_8BIT; |
600 | } else if (ns->geom.pgsz == 2048) { | 599 | } else if (ns->geom.pgsz == 2048) { |
@@ -663,8 +662,6 @@ static int init_nandsim(struct mtd_info *mtd) | |||
663 | for (i = 0; nand_flash_ids[i].name != NULL; i++) { | 662 | for (i = 0; nand_flash_ids[i].name != NULL; i++) { |
664 | if (second_id_byte != nand_flash_ids[i].id) | 663 | if (second_id_byte != nand_flash_ids[i].id) |
665 | continue; | 664 | continue; |
666 | if (!(nand_flash_ids[i].options & NAND_NO_AUTOINCR)) | ||
667 | ns->options |= OPT_AUTOINCR; | ||
668 | } | 665 | } |
669 | 666 | ||
670 | if (ns->busw == 16) | 667 | if (ns->busw == 16) |
@@ -1936,20 +1933,8 @@ static u_char ns_nand_read_byte(struct mtd_info *mtd) | |||
1936 | if (ns->regs.count == ns->regs.num) { | 1933 | if (ns->regs.count == ns->regs.num) { |
1937 | NS_DBG("read_byte: all bytes were read\n"); | 1934 | NS_DBG("read_byte: all bytes were read\n"); |
1938 | 1935 | ||
1939 | /* | 1936 | if (NS_STATE(ns->nxstate) == STATE_READY) |
1940 | * The OPT_AUTOINCR allows to read next consecutive pages without | ||
1941 | * new read operation cycle. | ||
1942 | */ | ||
1943 | if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) { | ||
1944 | ns->regs.count = 0; | ||
1945 | if (ns->regs.row + 1 < ns->geom.pgnum) | ||
1946 | ns->regs.row += 1; | ||
1947 | NS_DBG("read_byte: switch to the next page (%#x)\n", ns->regs.row); | ||
1948 | do_state_action(ns, ACTION_CPY); | ||
1949 | } | ||
1950 | else if (NS_STATE(ns->nxstate) == STATE_READY) | ||
1951 | switch_state(ns); | 1937 | switch_state(ns); |
1952 | |||
1953 | } | 1938 | } |
1954 | 1939 | ||
1955 | return outb; | 1940 | return outb; |
@@ -2203,14 +2188,7 @@ static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | |||
2203 | ns->regs.count += len; | 2188 | ns->regs.count += len; |
2204 | 2189 | ||
2205 | if (ns->regs.count == ns->regs.num) { | 2190 | if (ns->regs.count == ns->regs.num) { |
2206 | if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) { | 2191 | if (NS_STATE(ns->nxstate) == STATE_READY) |
2207 | ns->regs.count = 0; | ||
2208 | if (ns->regs.row + 1 < ns->geom.pgnum) | ||
2209 | ns->regs.row += 1; | ||
2210 | NS_DBG("read_buf: switch to the next page (%#x)\n", ns->regs.row); | ||
2211 | do_state_action(ns, ACTION_CPY); | ||
2212 | } | ||
2213 | else if (NS_STATE(ns->nxstate) == STATE_READY) | ||
2214 | switch_state(ns); | 2192 | switch_state(ns); |
2215 | } | 2193 | } |
2216 | 2194 | ||
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index c2b0bba9d8b3..d7f681d0c9b9 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
@@ -21,6 +21,10 @@ | |||
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | 23 | ||
24 | #ifdef CONFIG_MTD_NAND_OMAP_BCH | ||
25 | #include <linux/bch.h> | ||
26 | #endif | ||
27 | |||
24 | #include <plat/dma.h> | 28 | #include <plat/dma.h> |
25 | #include <plat/gpmc.h> | 29 | #include <plat/gpmc.h> |
26 | #include <plat/nand.h> | 30 | #include <plat/nand.h> |
@@ -127,6 +131,11 @@ struct omap_nand_info { | |||
127 | } iomode; | 131 | } iomode; |
128 | u_char *buf; | 132 | u_char *buf; |
129 | int buf_len; | 133 | int buf_len; |
134 | |||
135 | #ifdef CONFIG_MTD_NAND_OMAP_BCH | ||
136 | struct bch_control *bch; | ||
137 | struct nand_ecclayout ecclayout; | ||
138 | #endif | ||
130 | }; | 139 | }; |
131 | 140 | ||
132 | /** | 141 | /** |
@@ -402,7 +411,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, | |||
402 | PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write); | 411 | PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write); |
403 | if (ret) | 412 | if (ret) |
404 | /* PFPW engine is busy, use cpu copy method */ | 413 | /* PFPW engine is busy, use cpu copy method */ |
405 | goto out_copy; | 414 | goto out_copy_unmap; |
406 | 415 | ||
407 | init_completion(&info->comp); | 416 | init_completion(&info->comp); |
408 | 417 | ||
@@ -421,6 +430,8 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, | |||
421 | dma_unmap_single(&info->pdev->dev, dma_addr, len, dir); | 430 | dma_unmap_single(&info->pdev->dev, dma_addr, len, dir); |
422 | return 0; | 431 | return 0; |
423 | 432 | ||
433 | out_copy_unmap: | ||
434 | dma_unmap_single(&info->pdev->dev, dma_addr, len, dir); | ||
424 | out_copy: | 435 | out_copy: |
425 | if (info->nand.options & NAND_BUSWIDTH_16) | 436 | if (info->nand.options & NAND_BUSWIDTH_16) |
426 | is_write == 0 ? omap_read_buf16(mtd, (u_char *) addr, len) | 437 | is_write == 0 ? omap_read_buf16(mtd, (u_char *) addr, len) |
@@ -879,7 +890,7 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
879 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | 890 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, |
880 | mtd); | 891 | mtd); |
881 | unsigned long timeo = jiffies; | 892 | unsigned long timeo = jiffies; |
882 | int status = NAND_STATUS_FAIL, state = this->state; | 893 | int status, state = this->state; |
883 | 894 | ||
884 | if (state == FL_ERASING) | 895 | if (state == FL_ERASING) |
885 | timeo += (HZ * 400) / 1000; | 896 | timeo += (HZ * 400) / 1000; |
@@ -894,6 +905,8 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
894 | break; | 905 | break; |
895 | cond_resched(); | 906 | cond_resched(); |
896 | } | 907 | } |
908 | |||
909 | status = gpmc_nand_read(info->gpmc_cs, GPMC_NAND_DATA); | ||
897 | return status; | 910 | return status; |
898 | } | 911 | } |
899 | 912 | ||
@@ -925,6 +938,226 @@ static int omap_dev_ready(struct mtd_info *mtd) | |||
925 | return 1; | 938 | return 1; |
926 | } | 939 | } |
927 | 940 | ||
941 | #ifdef CONFIG_MTD_NAND_OMAP_BCH | ||
942 | |||
943 | /** | ||
944 | * omap3_enable_hwecc_bch - Program OMAP3 GPMC to perform BCH ECC correction | ||
945 | * @mtd: MTD device structure | ||
946 | * @mode: Read/Write mode | ||
947 | */ | ||
948 | static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode) | ||
949 | { | ||
950 | int nerrors; | ||
951 | unsigned int dev_width; | ||
952 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | ||
953 | mtd); | ||
954 | struct nand_chip *chip = mtd->priv; | ||
955 | |||
956 | nerrors = (info->nand.ecc.bytes == 13) ? 8 : 4; | ||
957 | dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0; | ||
958 | /* | ||
959 | * Program GPMC to perform correction on one 512-byte sector at a time. | ||
960 | * Using 4 sectors at a time (i.e. ecc.size = 2048) is also possible and | ||
961 | * gives a slight (5%) performance gain (but requires additional code). | ||
962 | */ | ||
963 | (void)gpmc_enable_hwecc_bch(info->gpmc_cs, mode, dev_width, 1, nerrors); | ||
964 | } | ||
965 | |||
966 | /** | ||
967 | * omap3_calculate_ecc_bch4 - Generate 7 bytes of ECC bytes | ||
968 | * @mtd: MTD device structure | ||
969 | * @dat: The pointer to data on which ecc is computed | ||
970 | * @ecc_code: The ecc_code buffer | ||
971 | */ | ||
972 | static int omap3_calculate_ecc_bch4(struct mtd_info *mtd, const u_char *dat, | ||
973 | u_char *ecc_code) | ||
974 | { | ||
975 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | ||
976 | mtd); | ||
977 | return gpmc_calculate_ecc_bch4(info->gpmc_cs, dat, ecc_code); | ||
978 | } | ||
979 | |||
980 | /** | ||
981 | * omap3_calculate_ecc_bch8 - Generate 13 bytes of ECC bytes | ||
982 | * @mtd: MTD device structure | ||
983 | * @dat: The pointer to data on which ecc is computed | ||
984 | * @ecc_code: The ecc_code buffer | ||
985 | */ | ||
986 | static int omap3_calculate_ecc_bch8(struct mtd_info *mtd, const u_char *dat, | ||
987 | u_char *ecc_code) | ||
988 | { | ||
989 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | ||
990 | mtd); | ||
991 | return gpmc_calculate_ecc_bch8(info->gpmc_cs, dat, ecc_code); | ||
992 | } | ||
993 | |||
994 | /** | ||
995 | * omap3_correct_data_bch - Decode received data and correct errors | ||
996 | * @mtd: MTD device structure | ||
997 | * @data: page data | ||
998 | * @read_ecc: ecc read from nand flash | ||
999 | * @calc_ecc: ecc read from HW ECC registers | ||
1000 | */ | ||
1001 | static int omap3_correct_data_bch(struct mtd_info *mtd, u_char *data, | ||
1002 | u_char *read_ecc, u_char *calc_ecc) | ||
1003 | { | ||
1004 | int i, count; | ||
1005 | /* cannot correct more than 8 errors */ | ||
1006 | unsigned int errloc[8]; | ||
1007 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | ||
1008 | mtd); | ||
1009 | |||
1010 | count = decode_bch(info->bch, NULL, 512, read_ecc, calc_ecc, NULL, | ||
1011 | errloc); | ||
1012 | if (count > 0) { | ||
1013 | /* correct errors */ | ||
1014 | for (i = 0; i < count; i++) { | ||
1015 | /* correct data only, not ecc bytes */ | ||
1016 | if (errloc[i] < 8*512) | ||
1017 | data[errloc[i]/8] ^= 1 << (errloc[i] & 7); | ||
1018 | pr_debug("corrected bitflip %u\n", errloc[i]); | ||
1019 | } | ||
1020 | } else if (count < 0) { | ||
1021 | pr_err("ecc unrecoverable error\n"); | ||
1022 | } | ||
1023 | return count; | ||
1024 | } | ||
1025 | |||
1026 | /** | ||
1027 | * omap3_free_bch - Release BCH ecc resources | ||
1028 | * @mtd: MTD device structure | ||
1029 | */ | ||
1030 | static void omap3_free_bch(struct mtd_info *mtd) | ||
1031 | { | ||
1032 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | ||
1033 | mtd); | ||
1034 | if (info->bch) { | ||
1035 | free_bch(info->bch); | ||
1036 | info->bch = NULL; | ||
1037 | } | ||
1038 | } | ||
1039 | |||
1040 | /** | ||
1041 | * omap3_init_bch - Initialize BCH ECC | ||
1042 | * @mtd: MTD device structure | ||
1043 | * @ecc_opt: OMAP ECC mode (OMAP_ECC_BCH4_CODE_HW or OMAP_ECC_BCH8_CODE_HW) | ||
1044 | */ | ||
1045 | static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt) | ||
1046 | { | ||
1047 | int ret, max_errors; | ||
1048 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | ||
1049 | mtd); | ||
1050 | #ifdef CONFIG_MTD_NAND_OMAP_BCH8 | ||
1051 | const int hw_errors = 8; | ||
1052 | #else | ||
1053 | const int hw_errors = 4; | ||
1054 | #endif | ||
1055 | info->bch = NULL; | ||
1056 | |||
1057 | max_errors = (ecc_opt == OMAP_ECC_BCH8_CODE_HW) ? 8 : 4; | ||
1058 | if (max_errors != hw_errors) { | ||
1059 | pr_err("cannot configure %d-bit BCH ecc, only %d-bit supported", | ||
1060 | max_errors, hw_errors); | ||
1061 | goto fail; | ||
1062 | } | ||
1063 | |||
1064 | /* initialize GPMC BCH engine */ | ||
1065 | ret = gpmc_init_hwecc_bch(info->gpmc_cs, 1, max_errors); | ||
1066 | if (ret) | ||
1067 | goto fail; | ||
1068 | |||
1069 | /* software bch library is only used to detect and locate errors */ | ||
1070 | info->bch = init_bch(13, max_errors, 0x201b /* hw polynomial */); | ||
1071 | if (!info->bch) | ||
1072 | goto fail; | ||
1073 | |||
1074 | info->nand.ecc.size = 512; | ||
1075 | info->nand.ecc.hwctl = omap3_enable_hwecc_bch; | ||
1076 | info->nand.ecc.correct = omap3_correct_data_bch; | ||
1077 | info->nand.ecc.mode = NAND_ECC_HW; | ||
1078 | |||
1079 | /* | ||
1080 | * The number of corrected errors in an ecc block that will trigger | ||
1081 | * block scrubbing defaults to the ecc strength (4 or 8). | ||
1082 | * Set mtd->bitflip_threshold here to define a custom threshold. | ||
1083 | */ | ||
1084 | |||
1085 | if (max_errors == 8) { | ||
1086 | info->nand.ecc.strength = 8; | ||
1087 | info->nand.ecc.bytes = 13; | ||
1088 | info->nand.ecc.calculate = omap3_calculate_ecc_bch8; | ||
1089 | } else { | ||
1090 | info->nand.ecc.strength = 4; | ||
1091 | info->nand.ecc.bytes = 7; | ||
1092 | info->nand.ecc.calculate = omap3_calculate_ecc_bch4; | ||
1093 | } | ||
1094 | |||
1095 | pr_info("enabling NAND BCH ecc with %d-bit correction\n", max_errors); | ||
1096 | return 0; | ||
1097 | fail: | ||
1098 | omap3_free_bch(mtd); | ||
1099 | return -1; | ||
1100 | } | ||
1101 | |||
1102 | /** | ||
1103 | * omap3_init_bch_tail - Build an oob layout for BCH ECC correction. | ||
1104 | * @mtd: MTD device structure | ||
1105 | */ | ||
1106 | static int omap3_init_bch_tail(struct mtd_info *mtd) | ||
1107 | { | ||
1108 | int i, steps; | ||
1109 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | ||
1110 | mtd); | ||
1111 | struct nand_ecclayout *layout = &info->ecclayout; | ||
1112 | |||
1113 | /* build oob layout */ | ||
1114 | steps = mtd->writesize/info->nand.ecc.size; | ||
1115 | layout->eccbytes = steps*info->nand.ecc.bytes; | ||
1116 | |||
1117 | /* do not bother creating special oob layouts for small page devices */ | ||
1118 | if (mtd->oobsize < 64) { | ||
1119 | pr_err("BCH ecc is not supported on small page devices\n"); | ||
1120 | goto fail; | ||
1121 | } | ||
1122 | |||
1123 | /* reserve 2 bytes for bad block marker */ | ||
1124 | if (layout->eccbytes+2 > mtd->oobsize) { | ||
1125 | pr_err("no oob layout available for oobsize %d eccbytes %u\n", | ||
1126 | mtd->oobsize, layout->eccbytes); | ||
1127 | goto fail; | ||
1128 | } | ||
1129 | |||
1130 | /* put ecc bytes at oob tail */ | ||
1131 | for (i = 0; i < layout->eccbytes; i++) | ||
1132 | layout->eccpos[i] = mtd->oobsize-layout->eccbytes+i; | ||
1133 | |||
1134 | layout->oobfree[0].offset = 2; | ||
1135 | layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes; | ||
1136 | info->nand.ecc.layout = layout; | ||
1137 | |||
1138 | if (!(info->nand.options & NAND_BUSWIDTH_16)) | ||
1139 | info->nand.badblock_pattern = &bb_descrip_flashbased; | ||
1140 | return 0; | ||
1141 | fail: | ||
1142 | omap3_free_bch(mtd); | ||
1143 | return -1; | ||
1144 | } | ||
1145 | |||
1146 | #else | ||
1147 | static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt) | ||
1148 | { | ||
1149 | pr_err("CONFIG_MTD_NAND_OMAP_BCH is not enabled\n"); | ||
1150 | return -1; | ||
1151 | } | ||
1152 | static int omap3_init_bch_tail(struct mtd_info *mtd) | ||
1153 | { | ||
1154 | return -1; | ||
1155 | } | ||
1156 | static void omap3_free_bch(struct mtd_info *mtd) | ||
1157 | { | ||
1158 | } | ||
1159 | #endif /* CONFIG_MTD_NAND_OMAP_BCH */ | ||
1160 | |||
928 | static int __devinit omap_nand_probe(struct platform_device *pdev) | 1161 | static int __devinit omap_nand_probe(struct platform_device *pdev) |
929 | { | 1162 | { |
930 | struct omap_nand_info *info; | 1163 | struct omap_nand_info *info; |
@@ -1063,6 +1296,13 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) | |||
1063 | info->nand.ecc.hwctl = omap_enable_hwecc; | 1296 | info->nand.ecc.hwctl = omap_enable_hwecc; |
1064 | info->nand.ecc.correct = omap_correct_data; | 1297 | info->nand.ecc.correct = omap_correct_data; |
1065 | info->nand.ecc.mode = NAND_ECC_HW; | 1298 | info->nand.ecc.mode = NAND_ECC_HW; |
1299 | } else if ((pdata->ecc_opt == OMAP_ECC_BCH4_CODE_HW) || | ||
1300 | (pdata->ecc_opt == OMAP_ECC_BCH8_CODE_HW)) { | ||
1301 | err = omap3_init_bch(&info->mtd, pdata->ecc_opt); | ||
1302 | if (err) { | ||
1303 | err = -EINVAL; | ||
1304 | goto out_release_mem_region; | ||
1305 | } | ||
1066 | } | 1306 | } |
1067 | 1307 | ||
1068 | /* DIP switches on some boards change between 8 and 16 bit | 1308 | /* DIP switches on some boards change between 8 and 16 bit |
@@ -1094,6 +1334,14 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) | |||
1094 | (offset + omap_oobinfo.eccbytes); | 1334 | (offset + omap_oobinfo.eccbytes); |
1095 | 1335 | ||
1096 | info->nand.ecc.layout = &omap_oobinfo; | 1336 | info->nand.ecc.layout = &omap_oobinfo; |
1337 | } else if ((pdata->ecc_opt == OMAP_ECC_BCH4_CODE_HW) || | ||
1338 | (pdata->ecc_opt == OMAP_ECC_BCH8_CODE_HW)) { | ||
1339 | /* build OOB layout for BCH ECC correction */ | ||
1340 | err = omap3_init_bch_tail(&info->mtd); | ||
1341 | if (err) { | ||
1342 | err = -EINVAL; | ||
1343 | goto out_release_mem_region; | ||
1344 | } | ||
1097 | } | 1345 | } |
1098 | 1346 | ||
1099 | /* second phase scan */ | 1347 | /* second phase scan */ |
@@ -1122,6 +1370,7 @@ static int omap_nand_remove(struct platform_device *pdev) | |||
1122 | struct mtd_info *mtd = platform_get_drvdata(pdev); | 1370 | struct mtd_info *mtd = platform_get_drvdata(pdev); |
1123 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, | 1371 | struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, |
1124 | mtd); | 1372 | mtd); |
1373 | omap3_free_bch(&info->mtd); | ||
1125 | 1374 | ||
1126 | platform_set_drvdata(pdev, NULL); | 1375 | platform_set_drvdata(pdev, NULL); |
1127 | if (info->dma_ch != -1) | 1376 | if (info->dma_ch != -1) |
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index 974dbf8251c9..1440e51cedcc 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c | |||
@@ -155,7 +155,6 @@ static int __devinit pasemi_nand_probe(struct platform_device *ofdev) | |||
155 | chip->ecc.mode = NAND_ECC_SOFT; | 155 | chip->ecc.mode = NAND_ECC_SOFT; |
156 | 156 | ||
157 | /* Enable the following for a flash based bad block table */ | 157 | /* Enable the following for a flash based bad block table */ |
158 | chip->options = NAND_NO_AUTOINCR; | ||
159 | chip->bbt_options = NAND_BBT_USE_FLASH; | 158 | chip->bbt_options = NAND_BBT_USE_FLASH; |
160 | 159 | ||
161 | /* Scan to find existence of the device */ | 160 | /* Scan to find existence of the device */ |
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index 6404e6e81b10..1bcb52040422 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c | |||
@@ -23,14 +23,18 @@ struct plat_nand_data { | |||
23 | void __iomem *io_base; | 23 | void __iomem *io_base; |
24 | }; | 24 | }; |
25 | 25 | ||
26 | static const char *part_probe_types[] = { "cmdlinepart", NULL }; | ||
27 | |||
26 | /* | 28 | /* |
27 | * Probe for the NAND device. | 29 | * Probe for the NAND device. |
28 | */ | 30 | */ |
29 | static int __devinit plat_nand_probe(struct platform_device *pdev) | 31 | static int __devinit plat_nand_probe(struct platform_device *pdev) |
30 | { | 32 | { |
31 | struct platform_nand_data *pdata = pdev->dev.platform_data; | 33 | struct platform_nand_data *pdata = pdev->dev.platform_data; |
34 | struct mtd_part_parser_data ppdata; | ||
32 | struct plat_nand_data *data; | 35 | struct plat_nand_data *data; |
33 | struct resource *res; | 36 | struct resource *res; |
37 | const char **part_types; | ||
34 | int err = 0; | 38 | int err = 0; |
35 | 39 | ||
36 | if (pdata->chip.nr_chips < 1) { | 40 | if (pdata->chip.nr_chips < 1) { |
@@ -75,6 +79,7 @@ static int __devinit plat_nand_probe(struct platform_device *pdev) | |||
75 | data->chip.select_chip = pdata->ctrl.select_chip; | 79 | data->chip.select_chip = pdata->ctrl.select_chip; |
76 | data->chip.write_buf = pdata->ctrl.write_buf; | 80 | data->chip.write_buf = pdata->ctrl.write_buf; |
77 | data->chip.read_buf = pdata->ctrl.read_buf; | 81 | data->chip.read_buf = pdata->ctrl.read_buf; |
82 | data->chip.read_byte = pdata->ctrl.read_byte; | ||
78 | data->chip.chip_delay = pdata->chip.chip_delay; | 83 | data->chip.chip_delay = pdata->chip.chip_delay; |
79 | data->chip.options |= pdata->chip.options; | 84 | data->chip.options |= pdata->chip.options; |
80 | data->chip.bbt_options |= pdata->chip.bbt_options; | 85 | data->chip.bbt_options |= pdata->chip.bbt_options; |
@@ -98,8 +103,10 @@ static int __devinit plat_nand_probe(struct platform_device *pdev) | |||
98 | goto out; | 103 | goto out; |
99 | } | 104 | } |
100 | 105 | ||
101 | err = mtd_device_parse_register(&data->mtd, | 106 | part_types = pdata->chip.part_probe_types ? : part_probe_types; |
102 | pdata->chip.part_probe_types, NULL, | 107 | |
108 | ppdata.of_node = pdev->dev.of_node; | ||
109 | err = mtd_device_parse_register(&data->mtd, part_types, &ppdata, | ||
103 | pdata->chip.partitions, | 110 | pdata->chip.partitions, |
104 | pdata->chip.nr_partitions); | 111 | pdata->chip.nr_partitions); |
105 | 112 | ||
@@ -140,12 +147,19 @@ static int __devexit plat_nand_remove(struct platform_device *pdev) | |||
140 | return 0; | 147 | return 0; |
141 | } | 148 | } |
142 | 149 | ||
150 | static const struct of_device_id plat_nand_match[] = { | ||
151 | { .compatible = "gen_nand" }, | ||
152 | {}, | ||
153 | }; | ||
154 | MODULE_DEVICE_TABLE(of, plat_nand_match); | ||
155 | |||
143 | static struct platform_driver plat_nand_driver = { | 156 | static struct platform_driver plat_nand_driver = { |
144 | .probe = plat_nand_probe, | 157 | .probe = plat_nand_probe, |
145 | .remove = __devexit_p(plat_nand_remove), | 158 | .remove = __devexit_p(plat_nand_remove), |
146 | .driver = { | 159 | .driver = { |
147 | .name = "gen_nand", | 160 | .name = "gen_nand", |
148 | .owner = THIS_MODULE, | 161 | .owner = THIS_MODULE, |
162 | .of_match_table = plat_nand_match, | ||
149 | }, | 163 | }, |
150 | }; | 164 | }; |
151 | 165 | ||
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index def50caa6f84..252aaefcacfa 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
@@ -682,14 +682,15 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
682 | } | 682 | } |
683 | 683 | ||
684 | static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, | 684 | static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, |
685 | struct nand_chip *chip, const uint8_t *buf) | 685 | struct nand_chip *chip, const uint8_t *buf, int oob_required) |
686 | { | 686 | { |
687 | chip->write_buf(mtd, buf, mtd->writesize); | 687 | chip->write_buf(mtd, buf, mtd->writesize); |
688 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); | 688 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); |
689 | } | 689 | } |
690 | 690 | ||
691 | static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, | 691 | static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, |
692 | struct nand_chip *chip, uint8_t *buf, int page) | 692 | struct nand_chip *chip, uint8_t *buf, int oob_required, |
693 | int page) | ||
693 | { | 694 | { |
694 | struct pxa3xx_nand_host *host = mtd->priv; | 695 | struct pxa3xx_nand_host *host = mtd->priv; |
695 | struct pxa3xx_nand_info *info = host->info_data; | 696 | struct pxa3xx_nand_info *info = host->info_data; |
@@ -1004,7 +1005,6 @@ KEEP_CONFIG: | |||
1004 | chip->ecc.size = host->page_size; | 1005 | chip->ecc.size = host->page_size; |
1005 | chip->ecc.strength = 1; | 1006 | chip->ecc.strength = 1; |
1006 | 1007 | ||
1007 | chip->options = NAND_NO_AUTOINCR; | ||
1008 | chip->options |= NAND_NO_READRDY; | 1008 | chip->options |= NAND_NO_READRDY; |
1009 | if (host->reg_ndcr & NDCR_DWIDTH_M) | 1009 | if (host->reg_ndcr & NDCR_DWIDTH_M) |
1010 | chip->options |= NAND_BUSWIDTH_16; | 1010 | chip->options |= NAND_BUSWIDTH_16; |
diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index c2040187c813..8cb627751c9c 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c | |||
@@ -539,14 +539,11 @@ exit: | |||
539 | * nand_read_oob_syndrome assumes we can send column address - we can't | 539 | * nand_read_oob_syndrome assumes we can send column address - we can't |
540 | */ | 540 | */ |
541 | static int r852_read_oob(struct mtd_info *mtd, struct nand_chip *chip, | 541 | static int r852_read_oob(struct mtd_info *mtd, struct nand_chip *chip, |
542 | int page, int sndcmd) | 542 | int page) |
543 | { | 543 | { |
544 | if (sndcmd) { | 544 | chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); |
545 | chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); | ||
546 | sndcmd = 0; | ||
547 | } | ||
548 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | 545 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |
549 | return sndcmd; | 546 | return 0; |
550 | } | 547 | } |
551 | 548 | ||
552 | /* | 549 | /* |
@@ -1104,18 +1101,7 @@ static struct pci_driver r852_pci_driver = { | |||
1104 | .driver.pm = &r852_pm_ops, | 1101 | .driver.pm = &r852_pm_ops, |
1105 | }; | 1102 | }; |
1106 | 1103 | ||
1107 | static __init int r852_module_init(void) | 1104 | module_pci_driver(r852_pci_driver); |
1108 | { | ||
1109 | return pci_register_driver(&r852_pci_driver); | ||
1110 | } | ||
1111 | |||
1112 | static void __exit r852_module_exit(void) | ||
1113 | { | ||
1114 | pci_unregister_driver(&r852_pci_driver); | ||
1115 | } | ||
1116 | |||
1117 | module_init(r852_module_init); | ||
1118 | module_exit(r852_module_exit); | ||
1119 | 1105 | ||
1120 | MODULE_LICENSE("GPL"); | 1106 | MODULE_LICENSE("GPL"); |
1121 | MODULE_AUTHOR("Maxim Levitsky <maximlevitsky@gmail.com>"); | 1107 | MODULE_AUTHOR("Maxim Levitsky <maximlevitsky@gmail.com>"); |
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c index e9b2b260de3a..aa9b8a5e0b8f 100644 --- a/drivers/mtd/nand/sh_flctl.c +++ b/drivers/mtd/nand/sh_flctl.c | |||
@@ -344,7 +344,7 @@ static void set_cmd_regs(struct mtd_info *mtd, uint32_t cmd, uint32_t flcmcdr_va | |||
344 | } | 344 | } |
345 | 345 | ||
346 | static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | 346 | static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, |
347 | uint8_t *buf, int page) | 347 | uint8_t *buf, int oob_required, int page) |
348 | { | 348 | { |
349 | int i, eccsize = chip->ecc.size; | 349 | int i, eccsize = chip->ecc.size; |
350 | int eccbytes = chip->ecc.bytes; | 350 | int eccbytes = chip->ecc.bytes; |
@@ -359,14 +359,14 @@ static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
359 | if (flctl->hwecc_cant_correct[i]) | 359 | if (flctl->hwecc_cant_correct[i]) |
360 | mtd->ecc_stats.failed++; | 360 | mtd->ecc_stats.failed++; |
361 | else | 361 | else |
362 | mtd->ecc_stats.corrected += 0; | 362 | mtd->ecc_stats.corrected += 0; /* FIXME */ |
363 | } | 363 | } |
364 | 364 | ||
365 | return 0; | 365 | return 0; |
366 | } | 366 | } |
367 | 367 | ||
368 | static void flctl_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | 368 | static void flctl_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, |
369 | const uint8_t *buf) | 369 | const uint8_t *buf, int oob_required) |
370 | { | 370 | { |
371 | int i, eccsize = chip->ecc.size; | 371 | int i, eccsize = chip->ecc.size; |
372 | int eccbytes = chip->ecc.bytes; | 372 | int eccbytes = chip->ecc.bytes; |
@@ -881,8 +881,6 @@ static int __devinit flctl_probe(struct platform_device *pdev) | |||
881 | flctl->hwecc = pdata->has_hwecc; | 881 | flctl->hwecc = pdata->has_hwecc; |
882 | flctl->holden = pdata->use_holden; | 882 | flctl->holden = pdata->use_holden; |
883 | 883 | ||
884 | nand->options = NAND_NO_AUTOINCR; | ||
885 | |||
886 | /* Set address of hardware control function */ | 884 | /* Set address of hardware control function */ |
887 | /* 20 us command delay time */ | 885 | /* 20 us command delay time */ |
888 | nand->chip_delay = 20; | 886 | nand->chip_delay = 20; |
diff --git a/drivers/mtd/nand/sm_common.c b/drivers/mtd/nand/sm_common.c index 774c3c266713..082bcdcd6bcf 100644 --- a/drivers/mtd/nand/sm_common.c +++ b/drivers/mtd/nand/sm_common.c | |||
@@ -94,17 +94,16 @@ static struct nand_flash_dev nand_smartmedia_flash_ids[] = { | |||
94 | {NULL,} | 94 | {NULL,} |
95 | }; | 95 | }; |
96 | 96 | ||
97 | #define XD_TYPEM (NAND_NO_AUTOINCR | NAND_BROKEN_XD) | ||
98 | static struct nand_flash_dev nand_xd_flash_ids[] = { | 97 | static struct nand_flash_dev nand_xd_flash_ids[] = { |
99 | 98 | ||
100 | {"xD 16MiB 3,3V", 0x73, 512, 16, 0x4000, 0}, | 99 | {"xD 16MiB 3,3V", 0x73, 512, 16, 0x4000, 0}, |
101 | {"xD 32MiB 3,3V", 0x75, 512, 32, 0x4000, 0}, | 100 | {"xD 32MiB 3,3V", 0x75, 512, 32, 0x4000, 0}, |
102 | {"xD 64MiB 3,3V", 0x76, 512, 64, 0x4000, 0}, | 101 | {"xD 64MiB 3,3V", 0x76, 512, 64, 0x4000, 0}, |
103 | {"xD 128MiB 3,3V", 0x79, 512, 128, 0x4000, 0}, | 102 | {"xD 128MiB 3,3V", 0x79, 512, 128, 0x4000, 0}, |
104 | {"xD 256MiB 3,3V", 0x71, 512, 256, 0x4000, XD_TYPEM}, | 103 | {"xD 256MiB 3,3V", 0x71, 512, 256, 0x4000, NAND_BROKEN_XD}, |
105 | {"xD 512MiB 3,3V", 0xdc, 512, 512, 0x4000, XD_TYPEM}, | 104 | {"xD 512MiB 3,3V", 0xdc, 512, 512, 0x4000, NAND_BROKEN_XD}, |
106 | {"xD 1GiB 3,3V", 0xd3, 512, 1024, 0x4000, XD_TYPEM}, | 105 | {"xD 1GiB 3,3V", 0xd3, 512, 1024, 0x4000, NAND_BROKEN_XD}, |
107 | {"xD 2GiB 3,3V", 0xd5, 512, 2048, 0x4000, XD_TYPEM}, | 106 | {"xD 2GiB 3,3V", 0xd5, 512, 2048, 0x4000, NAND_BROKEN_XD}, |
108 | {NULL,} | 107 | {NULL,} |
109 | }; | 108 | }; |
110 | 109 | ||
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index b3ce12ef359e..7153e0d27101 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c | |||
@@ -1201,7 +1201,8 @@ static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from, | |||
1201 | if (mtd->ecc_stats.failed - stats.failed) | 1201 | if (mtd->ecc_stats.failed - stats.failed) |
1202 | return -EBADMSG; | 1202 | return -EBADMSG; |
1203 | 1203 | ||
1204 | return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; | 1204 | /* return max bitflips per ecc step; ONENANDs correct 1 bit only */ |
1205 | return mtd->ecc_stats.corrected != stats.corrected ? 1 : 0; | ||
1205 | } | 1206 | } |
1206 | 1207 | ||
1207 | /** | 1208 | /** |
@@ -1333,7 +1334,8 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, | |||
1333 | if (mtd->ecc_stats.failed - stats.failed) | 1334 | if (mtd->ecc_stats.failed - stats.failed) |
1334 | return -EBADMSG; | 1335 | return -EBADMSG; |
1335 | 1336 | ||
1336 | return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; | 1337 | /* return max bitflips per ecc step; ONENANDs correct 1 bit only */ |
1338 | return mtd->ecc_stats.corrected != stats.corrected ? 1 : 0; | ||
1337 | } | 1339 | } |
1338 | 1340 | ||
1339 | /** | 1341 | /** |
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h index 44dca1f041c5..413ef89c2d1b 100644 --- a/fs/jffs2/jffs2_fs_sb.h +++ b/fs/jffs2/jffs2_fs_sb.h | |||
@@ -32,6 +32,13 @@ struct jffs2_inodirty; | |||
32 | struct jffs2_mount_opts { | 32 | struct jffs2_mount_opts { |
33 | bool override_compr; | 33 | bool override_compr; |
34 | unsigned int compr; | 34 | unsigned int compr; |
35 | |||
36 | /* The size of the reserved pool. The reserved pool is the JFFS2 flash | ||
37 | * space which may only be used by root cannot be used by the other | ||
38 | * users. This is implemented simply by means of not allowing the | ||
39 | * latter users to write to the file system if the amount if the | ||
40 | * available space is less then 'rp_size'. */ | ||
41 | unsigned int rp_size; | ||
35 | }; | 42 | }; |
36 | 43 | ||
37 | /* A struct for the overall file system control. Pointers to | 44 | /* A struct for the overall file system control. Pointers to |
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 6784d1e7a7eb..0c96eb52c797 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c | |||
@@ -18,6 +18,37 @@ | |||
18 | #include "nodelist.h" | 18 | #include "nodelist.h" |
19 | #include "debug.h" | 19 | #include "debug.h" |
20 | 20 | ||
21 | /* | ||
22 | * Check whether the user is allowed to write. | ||
23 | */ | ||
24 | static int jffs2_rp_can_write(struct jffs2_sb_info *c) | ||
25 | { | ||
26 | uint32_t avail; | ||
27 | struct jffs2_mount_opts *opts = &c->mount_opts; | ||
28 | |||
29 | avail = c->dirty_size + c->free_size + c->unchecked_size + | ||
30 | c->erasing_size - c->resv_blocks_write * c->sector_size | ||
31 | - c->nospc_dirty_size; | ||
32 | |||
33 | if (avail < 2 * opts->rp_size) | ||
34 | jffs2_dbg(1, "rpsize %u, dirty_size %u, free_size %u, " | ||
35 | "erasing_size %u, unchecked_size %u, " | ||
36 | "nr_erasing_blocks %u, avail %u, resrv %u\n", | ||
37 | opts->rp_size, c->dirty_size, c->free_size, | ||
38 | c->erasing_size, c->unchecked_size, | ||
39 | c->nr_erasing_blocks, avail, c->nospc_dirty_size); | ||
40 | |||
41 | if (avail > opts->rp_size) | ||
42 | return 1; | ||
43 | |||
44 | /* Always allow root */ | ||
45 | if (capable(CAP_SYS_RESOURCE)) | ||
46 | return 1; | ||
47 | |||
48 | jffs2_dbg(1, "forbid writing\n"); | ||
49 | return 0; | ||
50 | } | ||
51 | |||
21 | /** | 52 | /** |
22 | * jffs2_reserve_space - request physical space to write nodes to flash | 53 | * jffs2_reserve_space - request physical space to write nodes to flash |
23 | * @c: superblock info | 54 | * @c: superblock info |
@@ -55,6 +86,15 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, | |||
55 | 86 | ||
56 | spin_lock(&c->erase_completion_lock); | 87 | spin_lock(&c->erase_completion_lock); |
57 | 88 | ||
89 | /* | ||
90 | * Check if the free space is greater then size of the reserved pool. | ||
91 | * If not, only allow root to proceed with writing. | ||
92 | */ | ||
93 | if (prio != ALLOC_DELETION && !jffs2_rp_can_write(c)) { | ||
94 | ret = -ENOSPC; | ||
95 | goto out; | ||
96 | } | ||
97 | |||
58 | /* this needs a little more thought (true <tglx> :)) */ | 98 | /* this needs a little more thought (true <tglx> :)) */ |
59 | while(ret == -EAGAIN) { | 99 | while(ret == -EAGAIN) { |
60 | while(c->nr_free_blocks + c->nr_erasing_blocks < blocksneeded) { | 100 | while(c->nr_free_blocks + c->nr_erasing_blocks < blocksneeded) { |
@@ -158,6 +198,8 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, | |||
158 | jffs2_dbg(1, "%s(): ret is %d\n", __func__, ret); | 198 | jffs2_dbg(1, "%s(): ret is %d\n", __func__, ret); |
159 | } | 199 | } |
160 | } | 200 | } |
201 | |||
202 | out: | ||
161 | spin_unlock(&c->erase_completion_lock); | 203 | spin_unlock(&c->erase_completion_lock); |
162 | if (!ret) | 204 | if (!ret) |
163 | ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1); | 205 | ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1); |
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index dc0437e84763..1ea349fff68b 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c | |||
@@ -1266,19 +1266,25 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
1266 | /* Symlink's inode data is the target path. Read it and | 1266 | /* Symlink's inode data is the target path. Read it and |
1267 | * keep in RAM to facilitate quick follow symlink | 1267 | * keep in RAM to facilitate quick follow symlink |
1268 | * operation. */ | 1268 | * operation. */ |
1269 | f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL); | 1269 | uint32_t csize = je32_to_cpu(latest_node->csize); |
1270 | if (csize > JFFS2_MAX_NAME_LEN) { | ||
1271 | mutex_unlock(&f->sem); | ||
1272 | jffs2_do_clear_inode(c, f); | ||
1273 | return -ENAMETOOLONG; | ||
1274 | } | ||
1275 | f->target = kmalloc(csize + 1, GFP_KERNEL); | ||
1270 | if (!f->target) { | 1276 | if (!f->target) { |
1271 | JFFS2_ERROR("can't allocate %d bytes of memory for the symlink target path cache\n", je32_to_cpu(latest_node->csize)); | 1277 | JFFS2_ERROR("can't allocate %u bytes of memory for the symlink target path cache\n", csize); |
1272 | mutex_unlock(&f->sem); | 1278 | mutex_unlock(&f->sem); |
1273 | jffs2_do_clear_inode(c, f); | 1279 | jffs2_do_clear_inode(c, f); |
1274 | return -ENOMEM; | 1280 | return -ENOMEM; |
1275 | } | 1281 | } |
1276 | 1282 | ||
1277 | ret = jffs2_flash_read(c, ref_offset(rii.latest_ref) + sizeof(*latest_node), | 1283 | ret = jffs2_flash_read(c, ref_offset(rii.latest_ref) + sizeof(*latest_node), |
1278 | je32_to_cpu(latest_node->csize), &retlen, (char *)f->target); | 1284 | csize, &retlen, (char *)f->target); |
1279 | 1285 | ||
1280 | if (ret || retlen != je32_to_cpu(latest_node->csize)) { | 1286 | if (ret || retlen != csize) { |
1281 | if (retlen != je32_to_cpu(latest_node->csize)) | 1287 | if (retlen != csize) |
1282 | ret = -EIO; | 1288 | ret = -EIO; |
1283 | kfree(f->target); | 1289 | kfree(f->target); |
1284 | f->target = NULL; | 1290 | f->target = NULL; |
@@ -1287,7 +1293,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
1287 | return ret; | 1293 | return ret; |
1288 | } | 1294 | } |
1289 | 1295 | ||
1290 | f->target[je32_to_cpu(latest_node->csize)] = '\0'; | 1296 | f->target[csize] = '\0'; |
1291 | dbg_readinode("symlink's target '%s' cached\n", f->target); | 1297 | dbg_readinode("symlink's target '%s' cached\n", f->target); |
1292 | } | 1298 | } |
1293 | 1299 | ||
@@ -1415,6 +1421,7 @@ int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i | |||
1415 | mutex_unlock(&f->sem); | 1421 | mutex_unlock(&f->sem); |
1416 | jffs2_do_clear_inode(c, f); | 1422 | jffs2_do_clear_inode(c, f); |
1417 | } | 1423 | } |
1424 | jffs2_xattr_do_crccheck_inode(c, ic); | ||
1418 | kfree (f); | 1425 | kfree (f); |
1419 | return ret; | 1426 | return ret; |
1420 | } | 1427 | } |
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index bc586f204228..61ea41389f90 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c | |||
@@ -90,6 +90,8 @@ static int jffs2_show_options(struct seq_file *s, struct dentry *root) | |||
90 | 90 | ||
91 | if (opts->override_compr) | 91 | if (opts->override_compr) |
92 | seq_printf(s, ",compr=%s", jffs2_compr_name(opts->compr)); | 92 | seq_printf(s, ",compr=%s", jffs2_compr_name(opts->compr)); |
93 | if (opts->rp_size) | ||
94 | seq_printf(s, ",rp_size=%u", opts->rp_size / 1024); | ||
93 | 95 | ||
94 | return 0; | 96 | return 0; |
95 | } | 97 | } |
@@ -154,15 +156,18 @@ static const struct export_operations jffs2_export_ops = { | |||
154 | * JFFS2 mount options. | 156 | * JFFS2 mount options. |
155 | * | 157 | * |
156 | * Opt_override_compr: override default compressor | 158 | * Opt_override_compr: override default compressor |
159 | * Opt_rp_size: size of reserved pool in KiB | ||
157 | * Opt_err: just end of array marker | 160 | * Opt_err: just end of array marker |
158 | */ | 161 | */ |
159 | enum { | 162 | enum { |
160 | Opt_override_compr, | 163 | Opt_override_compr, |
164 | Opt_rp_size, | ||
161 | Opt_err, | 165 | Opt_err, |
162 | }; | 166 | }; |
163 | 167 | ||
164 | static const match_table_t tokens = { | 168 | static const match_table_t tokens = { |
165 | {Opt_override_compr, "compr=%s"}, | 169 | {Opt_override_compr, "compr=%s"}, |
170 | {Opt_rp_size, "rp_size=%u"}, | ||
166 | {Opt_err, NULL}, | 171 | {Opt_err, NULL}, |
167 | }; | 172 | }; |
168 | 173 | ||
@@ -170,6 +175,7 @@ static int jffs2_parse_options(struct jffs2_sb_info *c, char *data) | |||
170 | { | 175 | { |
171 | substring_t args[MAX_OPT_ARGS]; | 176 | substring_t args[MAX_OPT_ARGS]; |
172 | char *p, *name; | 177 | char *p, *name; |
178 | unsigned int opt; | ||
173 | 179 | ||
174 | if (!data) | 180 | if (!data) |
175 | return 0; | 181 | return 0; |
@@ -207,6 +213,17 @@ static int jffs2_parse_options(struct jffs2_sb_info *c, char *data) | |||
207 | kfree(name); | 213 | kfree(name); |
208 | c->mount_opts.override_compr = true; | 214 | c->mount_opts.override_compr = true; |
209 | break; | 215 | break; |
216 | case Opt_rp_size: | ||
217 | if (match_int(&args[0], &opt)) | ||
218 | return -EINVAL; | ||
219 | opt *= 1024; | ||
220 | if (opt > c->mtd->size) { | ||
221 | pr_warn("Too large reserve pool specified, max " | ||
222 | "is %llu KB\n", c->mtd->size / 1024); | ||
223 | return -EINVAL; | ||
224 | } | ||
225 | c->mount_opts.rp_size = opt; | ||
226 | break; | ||
210 | default: | 227 | default: |
211 | pr_err("Error: unrecognized mount option '%s' or missing value\n", | 228 | pr_err("Error: unrecognized mount option '%s' or missing value\n", |
212 | p); | 229 | p); |
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index b55b803eddcb..3034e970eb9a 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c | |||
@@ -11,6 +11,8 @@ | |||
11 | 11 | ||
12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
13 | 13 | ||
14 | #define JFFS2_XATTR_IS_CORRUPTED 1 | ||
15 | |||
14 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
15 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
16 | #include <linux/fs.h> | 18 | #include <linux/fs.h> |
@@ -153,7 +155,7 @@ static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_dat | |||
153 | JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", | 155 | JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", |
154 | offset, je32_to_cpu(rx.hdr_crc), crc); | 156 | offset, je32_to_cpu(rx.hdr_crc), crc); |
155 | xd->flags |= JFFS2_XFLAGS_INVALID; | 157 | xd->flags |= JFFS2_XFLAGS_INVALID; |
156 | return -EIO; | 158 | return JFFS2_XATTR_IS_CORRUPTED; |
157 | } | 159 | } |
158 | totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len)); | 160 | totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len)); |
159 | if (je16_to_cpu(rx.magic) != JFFS2_MAGIC_BITMASK | 161 | if (je16_to_cpu(rx.magic) != JFFS2_MAGIC_BITMASK |
@@ -169,7 +171,7 @@ static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_dat | |||
169 | je32_to_cpu(rx.xid), xd->xid, | 171 | je32_to_cpu(rx.xid), xd->xid, |
170 | je32_to_cpu(rx.version), xd->version); | 172 | je32_to_cpu(rx.version), xd->version); |
171 | xd->flags |= JFFS2_XFLAGS_INVALID; | 173 | xd->flags |= JFFS2_XFLAGS_INVALID; |
172 | return -EIO; | 174 | return JFFS2_XATTR_IS_CORRUPTED; |
173 | } | 175 | } |
174 | xd->xprefix = rx.xprefix; | 176 | xd->xprefix = rx.xprefix; |
175 | xd->name_len = rx.name_len; | 177 | xd->name_len = rx.name_len; |
@@ -227,12 +229,12 @@ static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum | |||
227 | data[xd->name_len] = '\0'; | 229 | data[xd->name_len] = '\0'; |
228 | crc = crc32(0, data, length); | 230 | crc = crc32(0, data, length); |
229 | if (crc != xd->data_crc) { | 231 | if (crc != xd->data_crc) { |
230 | JFFS2_WARNING("node CRC failed (JFFS2_NODETYPE_XREF)" | 232 | JFFS2_WARNING("node CRC failed (JFFS2_NODETYPE_XATTR)" |
231 | " at %#08x, read: 0x%08x calculated: 0x%08x\n", | 233 | " at %#08x, read: 0x%08x calculated: 0x%08x\n", |
232 | ref_offset(xd->node), xd->data_crc, crc); | 234 | ref_offset(xd->node), xd->data_crc, crc); |
233 | kfree(data); | 235 | kfree(data); |
234 | xd->flags |= JFFS2_XFLAGS_INVALID; | 236 | xd->flags |= JFFS2_XFLAGS_INVALID; |
235 | return -EIO; | 237 | return JFFS2_XATTR_IS_CORRUPTED; |
236 | } | 238 | } |
237 | 239 | ||
238 | xd->flags |= JFFS2_XFLAGS_HOT; | 240 | xd->flags |= JFFS2_XFLAGS_HOT; |
@@ -270,7 +272,7 @@ static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x | |||
270 | if (xd->xname) | 272 | if (xd->xname) |
271 | return 0; | 273 | return 0; |
272 | if (xd->flags & JFFS2_XFLAGS_INVALID) | 274 | if (xd->flags & JFFS2_XFLAGS_INVALID) |
273 | return -EIO; | 275 | return JFFS2_XATTR_IS_CORRUPTED; |
274 | if (unlikely(is_xattr_datum_unchecked(c, xd))) | 276 | if (unlikely(is_xattr_datum_unchecked(c, xd))) |
275 | rc = do_verify_xattr_datum(c, xd); | 277 | rc = do_verify_xattr_datum(c, xd); |
276 | if (!rc) | 278 | if (!rc) |
@@ -435,6 +437,8 @@ static void unrefer_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datu | |||
435 | * is called to release xattr related objects when unmounting. | 437 | * is called to release xattr related objects when unmounting. |
436 | * check_xattr_ref_inode(c, ic) | 438 | * check_xattr_ref_inode(c, ic) |
437 | * is used to confirm inode does not have duplicate xattr name/value pair. | 439 | * is used to confirm inode does not have duplicate xattr name/value pair. |
440 | * jffs2_xattr_do_crccheck_inode(c, ic) | ||
441 | * is used to force xattr data integrity check during the initial gc scan. | ||
438 | * -------------------------------------------------- */ | 442 | * -------------------------------------------------- */ |
439 | static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) | 443 | static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) |
440 | { | 444 | { |
@@ -462,7 +466,7 @@ static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref | |||
462 | if (crc != je32_to_cpu(rr.node_crc)) { | 466 | if (crc != je32_to_cpu(rr.node_crc)) { |
463 | JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", | 467 | JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", |
464 | offset, je32_to_cpu(rr.node_crc), crc); | 468 | offset, je32_to_cpu(rr.node_crc), crc); |
465 | return -EIO; | 469 | return JFFS2_XATTR_IS_CORRUPTED; |
466 | } | 470 | } |
467 | if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK | 471 | if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK |
468 | || je16_to_cpu(rr.nodetype) != JFFS2_NODETYPE_XREF | 472 | || je16_to_cpu(rr.nodetype) != JFFS2_NODETYPE_XREF |
@@ -472,7 +476,7 @@ static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref | |||
472 | offset, je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK, | 476 | offset, je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK, |
473 | je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF, | 477 | je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF, |
474 | je32_to_cpu(rr.totlen), PAD(sizeof(rr))); | 478 | je32_to_cpu(rr.totlen), PAD(sizeof(rr))); |
475 | return -EIO; | 479 | return JFFS2_XATTR_IS_CORRUPTED; |
476 | } | 480 | } |
477 | ref->ino = je32_to_cpu(rr.ino); | 481 | ref->ino = je32_to_cpu(rr.ino); |
478 | ref->xid = je32_to_cpu(rr.xid); | 482 | ref->xid = je32_to_cpu(rr.xid); |
@@ -682,6 +686,11 @@ static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cac | |||
682 | return rc; | 686 | return rc; |
683 | } | 687 | } |
684 | 688 | ||
689 | void jffs2_xattr_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) | ||
690 | { | ||
691 | check_xattr_ref_inode(c, ic); | ||
692 | } | ||
693 | |||
685 | /* -------- xattr subsystem functions --------------- | 694 | /* -------- xattr subsystem functions --------------- |
686 | * jffs2_init_xattr_subsystem(c) | 695 | * jffs2_init_xattr_subsystem(c) |
687 | * is used to initialize semaphore and list_head, and some variables. | 696 | * is used to initialize semaphore and list_head, and some variables. |
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h index 7be4beb306f3..467ff376ee26 100644 --- a/fs/jffs2/xattr.h +++ b/fs/jffs2/xattr.h | |||
@@ -77,6 +77,7 @@ extern void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c); | |||
77 | extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c, | 77 | extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c, |
78 | uint32_t xid, uint32_t version); | 78 | uint32_t xid, uint32_t version); |
79 | 79 | ||
80 | extern void jffs2_xattr_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); | ||
80 | extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); | 81 | extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); |
81 | extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); | 82 | extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); |
82 | 83 | ||
@@ -108,6 +109,7 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t); | |||
108 | #define jffs2_build_xattr_subsystem(c) | 109 | #define jffs2_build_xattr_subsystem(c) |
109 | #define jffs2_clear_xattr_subsystem(c) | 110 | #define jffs2_clear_xattr_subsystem(c) |
110 | 111 | ||
112 | #define jffs2_xattr_do_crccheck_inode(c, ic) | ||
111 | #define jffs2_xattr_delete_inode(c, ic) | 113 | #define jffs2_xattr_delete_inode(c, ic) |
112 | #define jffs2_xattr_free_inode(c, ic) | 114 | #define jffs2_xattr_free_inode(c, ic) |
113 | #define jffs2_verify_xattr(c) (1) | 115 | #define jffs2_verify_xattr(c) (1) |
diff --git a/include/linux/mtd/gpmi-nand.h b/include/linux/mtd/gpmi-nand.h index 69b6dbf46b5e..ed3c4e09f3d1 100644 --- a/include/linux/mtd/gpmi-nand.h +++ b/include/linux/mtd/gpmi-nand.h | |||
@@ -23,12 +23,12 @@ | |||
23 | #define GPMI_NAND_RES_SIZE 6 | 23 | #define GPMI_NAND_RES_SIZE 6 |
24 | 24 | ||
25 | /* Resource names for the GPMI NAND driver. */ | 25 | /* Resource names for the GPMI NAND driver. */ |
26 | #define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME "GPMI NAND GPMI Registers" | 26 | #define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME "gpmi-nand" |
27 | #define GPMI_NAND_GPMI_INTERRUPT_RES_NAME "GPMI NAND GPMI Interrupt" | 27 | #define GPMI_NAND_GPMI_INTERRUPT_RES_NAME "GPMI NAND GPMI Interrupt" |
28 | #define GPMI_NAND_BCH_REGS_ADDR_RES_NAME "GPMI NAND BCH Registers" | 28 | #define GPMI_NAND_BCH_REGS_ADDR_RES_NAME "bch" |
29 | #define GPMI_NAND_BCH_INTERRUPT_RES_NAME "GPMI NAND BCH Interrupt" | 29 | #define GPMI_NAND_BCH_INTERRUPT_RES_NAME "bch" |
30 | #define GPMI_NAND_DMA_CHANNELS_RES_NAME "GPMI NAND DMA Channels" | 30 | #define GPMI_NAND_DMA_CHANNELS_RES_NAME "GPMI NAND DMA Channels" |
31 | #define GPMI_NAND_DMA_INTERRUPT_RES_NAME "GPMI NAND DMA Interrupt" | 31 | #define GPMI_NAND_DMA_INTERRUPT_RES_NAME "gpmi-dma" |
32 | 32 | ||
33 | /** | 33 | /** |
34 | * struct gpmi_nand_platform_data - GPMI NAND driver platform data. | 34 | * struct gpmi_nand_platform_data - GPMI NAND driver platform data. |
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index cf5ea8cdcf8e..63dadc0dfb62 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h | |||
@@ -157,6 +157,15 @@ struct mtd_info { | |||
157 | unsigned int erasesize_mask; | 157 | unsigned int erasesize_mask; |
158 | unsigned int writesize_mask; | 158 | unsigned int writesize_mask; |
159 | 159 | ||
160 | /* | ||
161 | * read ops return -EUCLEAN if max number of bitflips corrected on any | ||
162 | * one region comprising an ecc step equals or exceeds this value. | ||
163 | * Settable by driver, else defaults to ecc_strength. User can override | ||
164 | * in sysfs. N.B. The meaning of the -EUCLEAN return code has changed; | ||
165 | * see Documentation/ABI/testing/sysfs-class-mtd for more detail. | ||
166 | */ | ||
167 | unsigned int bitflip_threshold; | ||
168 | |||
160 | // Kernel-only stuff starts here. | 169 | // Kernel-only stuff starts here. |
161 | const char *name; | 170 | const char *name; |
162 | int index; | 171 | int index; |
@@ -164,7 +173,7 @@ struct mtd_info { | |||
164 | /* ECC layout structure pointer - read only! */ | 173 | /* ECC layout structure pointer - read only! */ |
165 | struct nand_ecclayout *ecclayout; | 174 | struct nand_ecclayout *ecclayout; |
166 | 175 | ||
167 | /* max number of correctible bit errors per writesize */ | 176 | /* max number of correctible bit errors per ecc step */ |
168 | unsigned int ecc_strength; | 177 | unsigned int ecc_strength; |
169 | 178 | ||
170 | /* Data for variable erase regions. If numeraseregions is zero, | 179 | /* Data for variable erase regions. If numeraseregions is zero, |
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 1482340d3d9f..57977c640529 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h | |||
@@ -161,8 +161,6 @@ typedef enum { | |||
161 | * Option constants for bizarre disfunctionality and real | 161 | * Option constants for bizarre disfunctionality and real |
162 | * features. | 162 | * features. |
163 | */ | 163 | */ |
164 | /* Chip can not auto increment pages */ | ||
165 | #define NAND_NO_AUTOINCR 0x00000001 | ||
166 | /* Buswidth is 16 bit */ | 164 | /* Buswidth is 16 bit */ |
167 | #define NAND_BUSWIDTH_16 0x00000002 | 165 | #define NAND_BUSWIDTH_16 0x00000002 |
168 | /* Device supports partial programming without padding */ | 166 | /* Device supports partial programming without padding */ |
@@ -207,7 +205,6 @@ typedef enum { | |||
207 | (NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK) | 205 | (NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK) |
208 | 206 | ||
209 | /* Macros to identify the above */ | 207 | /* Macros to identify the above */ |
210 | #define NAND_CANAUTOINCR(chip) (!(chip->options & NAND_NO_AUTOINCR)) | ||
211 | #define NAND_MUST_PAD(chip) (!(chip->options & NAND_NO_PADDING)) | 208 | #define NAND_MUST_PAD(chip) (!(chip->options & NAND_NO_PADDING)) |
212 | #define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG)) | 209 | #define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG)) |
213 | #define NAND_HAS_COPYBACK(chip) ((chip->options & NAND_COPYBACK)) | 210 | #define NAND_HAS_COPYBACK(chip) ((chip->options & NAND_COPYBACK)) |
@@ -216,7 +213,7 @@ typedef enum { | |||
216 | && (chip->page_shift > 9)) | 213 | && (chip->page_shift > 9)) |
217 | 214 | ||
218 | /* Mask to zero out the chip options, which come from the id table */ | 215 | /* Mask to zero out the chip options, which come from the id table */ |
219 | #define NAND_CHIPOPTIONS_MSK (0x0000ffff & ~NAND_NO_AUTOINCR) | 216 | #define NAND_CHIPOPTIONS_MSK 0x0000ffff |
220 | 217 | ||
221 | /* Non chip related options */ | 218 | /* Non chip related options */ |
222 | /* This option skips the bbt scan during initialization. */ | 219 | /* This option skips the bbt scan during initialization. */ |
@@ -363,21 +360,20 @@ struct nand_ecc_ctrl { | |||
363 | int (*correct)(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc, | 360 | int (*correct)(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc, |
364 | uint8_t *calc_ecc); | 361 | uint8_t *calc_ecc); |
365 | int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, | 362 | int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, |
366 | uint8_t *buf, int page); | 363 | uint8_t *buf, int oob_required, int page); |
367 | void (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, | 364 | void (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, |
368 | const uint8_t *buf); | 365 | const uint8_t *buf, int oob_required); |
369 | int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, | 366 | int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, |
370 | uint8_t *buf, int page); | 367 | uint8_t *buf, int oob_required, int page); |
371 | int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip, | 368 | int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip, |
372 | uint32_t offs, uint32_t len, uint8_t *buf); | 369 | uint32_t offs, uint32_t len, uint8_t *buf); |
373 | void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, | 370 | void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, |
374 | const uint8_t *buf); | 371 | const uint8_t *buf, int oob_required); |
375 | int (*write_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip, | 372 | int (*write_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip, |
376 | int page); | 373 | int page); |
377 | int (*read_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip, | 374 | int (*read_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip, |
378 | int page, int sndcmd); | 375 | int page); |
379 | int (*read_oob)(struct mtd_info *mtd, struct nand_chip *chip, int page, | 376 | int (*read_oob)(struct mtd_info *mtd, struct nand_chip *chip, int page); |
380 | int sndcmd); | ||
381 | int (*write_oob)(struct mtd_info *mtd, struct nand_chip *chip, | 377 | int (*write_oob)(struct mtd_info *mtd, struct nand_chip *chip, |
382 | int page); | 378 | int page); |
383 | }; | 379 | }; |
@@ -459,6 +455,8 @@ struct nand_buffers { | |||
459 | * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1 | 455 | * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1 |
460 | * @pagebuf: [INTERN] holds the pagenumber which is currently in | 456 | * @pagebuf: [INTERN] holds the pagenumber which is currently in |
461 | * data_buf. | 457 | * data_buf. |
458 | * @pagebuf_bitflips: [INTERN] holds the bitflip count for the page which is | ||
459 | * currently in data_buf. | ||
462 | * @subpagesize: [INTERN] holds the subpagesize | 460 | * @subpagesize: [INTERN] holds the subpagesize |
463 | * @onfi_version: [INTERN] holds the chip ONFI version (BCD encoded), | 461 | * @onfi_version: [INTERN] holds the chip ONFI version (BCD encoded), |
464 | * non 0 if ONFI supported. | 462 | * non 0 if ONFI supported. |
@@ -505,7 +503,8 @@ struct nand_chip { | |||
505 | int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, | 503 | int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, |
506 | int status, int page); | 504 | int status, int page); |
507 | int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, | 505 | int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, |
508 | const uint8_t *buf, int page, int cached, int raw); | 506 | const uint8_t *buf, int oob_required, int page, |
507 | int cached, int raw); | ||
509 | 508 | ||
510 | int chip_delay; | 509 | int chip_delay; |
511 | unsigned int options; | 510 | unsigned int options; |
@@ -519,6 +518,7 @@ struct nand_chip { | |||
519 | uint64_t chipsize; | 518 | uint64_t chipsize; |
520 | int pagemask; | 519 | int pagemask; |
521 | int pagebuf; | 520 | int pagebuf; |
521 | unsigned int pagebuf_bitflips; | ||
522 | int subpagesize; | 522 | int subpagesize; |
523 | uint8_t cellinfo; | 523 | uint8_t cellinfo; |
524 | int badblockpos; | 524 | int badblockpos; |
@@ -654,6 +654,7 @@ struct platform_nand_ctrl { | |||
654 | void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl); | 654 | void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl); |
655 | void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); | 655 | void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); |
656 | void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len); | 656 | void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len); |
657 | unsigned char (*read_byte)(struct mtd_info *mtd); | ||
657 | void *priv; | 658 | void *priv; |
658 | }; | 659 | }; |
659 | 660 | ||