diff options
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 | ||
